diff options
Diffstat (limited to 'include/llvm/ADT')
44 files changed, 12544 insertions, 0 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h new file mode 100644 index 0000000000000..928ecc0c3cf57 --- /dev/null +++ b/include/llvm/ADT/APFloat.h @@ -0,0 +1,367 @@ +//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares a class to represent arbitrary precision floating +// point values and provide a variety of arithmetic operations on them. +// +//===----------------------------------------------------------------------===// + +/* A self-contained host- and target-independent arbitrary-precision + floating-point software implementation. It uses bignum integer + arithmetic as provided by static functions in the APInt class. + The library will work with bignum integers whose parts are any + unsigned type at least 16 bits wide, but 64 bits is recommended. + + Written for clarity rather than speed, in particular with a view + to use in the front-end of a cross compiler so that target + arithmetic can be correctly performed on the host. Performance + should nonetheless be reasonable, particularly for its intended + use. It may be useful as a base implementation for a run-time + library during development of a faster target-specific one. + + All 5 rounding modes in the IEEE-754R draft are handled correctly + for all implemented operations. Currently implemented operations + are add, subtract, multiply, divide, fused-multiply-add, + conversion-to-float, conversion-to-integer and + conversion-from-integer. New rounding modes (e.g. away from zero) + can be added with three or four lines of code. + + Four formats are built-in: IEEE single precision, double + precision, quadruple precision, and x87 80-bit extended double + (when operating with full extended precision). Adding a new + format that obeys IEEE semantics only requires adding two lines of + code: a declaration and definition of the format. + + All operations return the status of that operation as an exception + bit-mask, so multiple operations can be done consecutively with + their results or-ed together. The returned status can be useful + for compiler diagnostics; e.g., inexact, underflow and overflow + can be easily diagnosed on constant folding, and compiler + optimizers can determine what exceptions would be raised by + folding operations and optimize, or perhaps not optimize, + accordingly. + + At present, underflow tininess is detected after rounding; it + should be straight forward to add support for the before-rounding + case too. + + The library reads hexadecimal floating point numbers as per C99, + and correctly rounds if necessary according to the specified + rounding mode. Syntax is required to have been validated by the + caller. It also converts floating point numbers to hexadecimal + text as per the C99 %a and %A conversions. The output precision + (or alternatively the natural minimal precision) can be specified; + if the requested precision is less than the natural precision the + output is correctly rounded for the specified rounding mode. + + It also reads decimal floating point numbers and correctly rounds + according to the specified rounding mode. + + Conversion to decimal text is not currently implemented. + + Non-zero finite numbers are represented internally as a sign bit, + a 16-bit signed exponent, and the significand as an array of + integer parts. After normalization of a number of precision P the + exponent is within the range of the format, and if the number is + not denormal the P-th bit of the significand is set as an explicit + integer bit. For denormals the most significant bit is shifted + right so that the exponent is maintained at the format's minimum, + so that the smallest denormal has just the least significant bit + of the significand set. The sign of zeroes and infinities is + significant; the exponent and significand of such numbers is not + stored, but has a known implicit (deterministic) value: 0 for the + significands, 0 for zero exponent, all 1 bits for infinity + exponent. For NaNs the sign and significand are deterministic, + although not really meaningful, and preserved in non-conversion + operations. The exponent is implicitly all 1 bits. + + TODO + ==== + + Some features that may or may not be worth adding: + + Binary to decimal conversion (hard). + + Optional ability to detect underflow tininess before rounding. + + New formats: x87 in single and double precision mode (IEEE apart + from extended exponent range) (hard). + + New operations: sqrt, IEEE remainder, C90 fmod, nextafter, + nexttoward. +*/ + +#ifndef LLVM_FLOAT_H +#define LLVM_FLOAT_H + +// APInt contains static functions implementing bignum arithmetic. +#include "llvm/ADT/APInt.h" + +namespace llvm { + + /* Exponents are stored as signed numbers. */ + typedef signed short exponent_t; + + struct fltSemantics; + + /* When bits of a floating point number are truncated, this enum is + used to indicate what fraction of the LSB those bits represented. + It essentially combines the roles of guard and sticky bits. */ + enum lostFraction { // Example of truncated bits: + lfExactlyZero, // 000000 + lfLessThanHalf, // 0xxxxx x's not all zero + lfExactlyHalf, // 100000 + lfMoreThanHalf // 1xxxxx x's not all zero + }; + + class APFloat { + public: + + /* We support the following floating point semantics. */ + static const fltSemantics IEEEsingle; + static const fltSemantics IEEEdouble; + static const fltSemantics IEEEquad; + static const fltSemantics PPCDoubleDouble; + static const fltSemantics x87DoubleExtended; + /* And this pseudo, used to construct APFloats that cannot + conflict with anything real. */ + static const fltSemantics Bogus; + + static unsigned int semanticsPrecision(const fltSemantics &); + + /* Floating point numbers have a four-state comparison relation. */ + enum cmpResult { + cmpLessThan, + cmpEqual, + cmpGreaterThan, + cmpUnordered + }; + + /* IEEE-754R gives five rounding modes. */ + enum roundingMode { + rmNearestTiesToEven, + rmTowardPositive, + rmTowardNegative, + rmTowardZero, + rmNearestTiesToAway + }; + + // Operation status. opUnderflow or opOverflow are always returned + // or-ed with opInexact. + enum opStatus { + opOK = 0x00, + opInvalidOp = 0x01, + opDivByZero = 0x02, + opOverflow = 0x04, + opUnderflow = 0x08, + opInexact = 0x10 + }; + + // Category of internally-represented number. + enum fltCategory { + fcInfinity, + fcNaN, + fcNormal, + fcZero + }; + + // Constructors. + APFloat(const fltSemantics &, const char *); + APFloat(const fltSemantics &, integerPart); + APFloat(const fltSemantics &, fltCategory, bool negative, unsigned type=0); + explicit APFloat(double d); + explicit APFloat(float f); + explicit APFloat(const APInt &, bool isIEEE = false); + APFloat(const APFloat &); + ~APFloat(); + + // Convenience "constructors" + static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcZero, Negative); + } + static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { + return APFloat(Sem, fcInfinity, Negative); + } + /// getNaN - 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) { + return APFloat(Sem, fcNaN, Negative, type); + } + + /// Profile - Used to insert APFloat objects, or objects that contain + /// APFloat objects, into FoldingSets. + void Profile(FoldingSetNodeID& NID) const; + + /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer& S) const; + + /// @brief Used by the Bitcode deserializer to deserialize APInts. + static APFloat ReadVal(Deserializer& D); + + /* Arithmetic. */ + opStatus add(const APFloat &, roundingMode); + opStatus subtract(const APFloat &, roundingMode); + opStatus multiply(const APFloat &, roundingMode); + opStatus divide(const APFloat &, roundingMode); + /* IEEE remainder. */ + opStatus remainder(const APFloat &); + /* C fmod, or llvm frem. */ + opStatus mod(const APFloat &, roundingMode); + opStatus fusedMultiplyAdd(const APFloat &, const APFloat &, roundingMode); + + /* Sign operations. */ + void changeSign(); + void clearSign(); + void copySign(const APFloat &); + + /* Conversions. */ + opStatus convert(const fltSemantics &, roundingMode, bool *); + opStatus convertToInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromAPInt(const APInt &, + bool, roundingMode); + opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int, + bool, roundingMode); + opStatus convertFromString(const char *, roundingMode); + APInt bitcastToAPInt() const; + double convertToDouble() const; + float convertToFloat() const; + + /* The definition of equality is not straightforward for floating point, + so we won't use operator==. Use one of the following, or write + whatever it is you really mean. */ + // bool operator==(const APFloat &) const; // DO NOT IMPLEMENT + + /* IEEE comparison with another floating point number (NaNs + compare unordered, 0==-0). */ + cmpResult compare(const APFloat &) const; + + /* Bitwise comparison for equality (QNaNs compare equal, 0!=-0). */ + bool bitwiseIsEqual(const APFloat &) 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. Return the number of characters written, + excluding the terminating NUL. */ + unsigned int convertToHexString(char *dst, unsigned int hexDigits, + bool upperCase, roundingMode) const; + + /* Simple queries. */ + fltCategory getCategory() const { return category; } + const fltSemantics &getSemantics() const { return *semantics; } + bool isZero() const { return category == fcZero; } + bool isNonZero() const { return category != fcZero; } + bool isNaN() const { return category == fcNaN; } + bool isInfinity() const { return category == fcInfinity; } + bool isNegative() const { return sign; } + bool isPosZero() const { return isZero() && !isNegative(); } + bool isNegZero() const { return isZero() && isNegative(); } + + APFloat& operator=(const APFloat &); + + /* Return an arbitrary integer value usable for hashing. */ + uint32_t getHashValue() const; + + private: + + /* Trivial queries. */ + integerPart *significandParts(); + const integerPart *significandParts() const; + unsigned int partCount() const; + + /* 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 &); + void incrementSignificand(); + void initialize(const fltSemantics *); + void shiftSignificandLeft(unsigned int); + lostFraction shiftSignificandRight(unsigned int); + unsigned int significandLSB() const; + unsigned int significandMSB() const; + void zeroSignificand(); + + /* Arithmetic on special values. */ + opStatus addOrSubtractSpecials(const APFloat &, bool subtract); + opStatus divideSpecials(const APFloat &); + opStatus multiplySpecials(const APFloat &); + opStatus modSpecials(const APFloat &); + + /* Miscellany. */ + void makeNaN(unsigned = 0); + opStatus normalize(roundingMode, lostFraction); + opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); + cmpResult compareAbsoluteValue(const APFloat &) const; + opStatus handleOverflow(roundingMode); + bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const; + opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool, + roundingMode, bool *) const; + opStatus convertFromUnsignedParts(const integerPart *, unsigned int, + roundingMode); + opStatus convertFromHexadecimalString(const char *, roundingMode); + opStatus convertFromDecimalString (const char *, roundingMode); + char *convertNormalToHexString(char *, unsigned int, bool, + roundingMode) const; + opStatus roundSignificandWithExponent(const integerPart *, unsigned int, + int, roundingMode); + + APInt convertFloatAPFloatToAPInt() const; + APInt convertDoubleAPFloatToAPInt() const; + APInt convertF80LongDoubleAPFloatToAPInt() const; + APInt convertPPCDoubleDoubleAPFloatToAPInt() const; + void initFromAPInt(const APInt& api, bool isIEEE = false); + void initFromFloatAPInt(const APInt& api); + void initFromDoubleAPInt(const APInt& api); + void initFromF80LongDoubleAPInt(const APInt& api); + void initFromPPCDoubleDoubleAPInt(const APInt& api); + + void assign(const APFloat &); + void copySignificand(const APFloat &); + void freeSignificand(); + + /* What kind of semantics does this value obey? */ + const fltSemantics *semantics; + + /* Significand - the fraction with an explicit integer bit. Must be + at least one bit wider than the target precision. */ + union Significand + { + integerPart part; + integerPart *parts; + } significand; + + /* The exponent - a signed number. */ + exponent_t exponent; + + /* What kind of floating point number this is. */ + /* Only 2 bits are required, but VisualStudio incorrectly sign extends + it. Using the extra bit keeps it from failing under VisualStudio */ + fltCategory category: 3; + + /* The sign bit of this number. */ + unsigned int sign: 1; + + /* For PPCDoubleDouble, we have a second exponent and sign (the second + significand is appended to the first one, although it would be wrong to + regard these as a single number for arithmetic purposes). These fields + are not meaningful for any other type. */ + exponent_t exponent2 : 11; + unsigned int sign2: 1; + }; +} /* namespace llvm */ + +#endif /* LLVM_FLOAT_H */ diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h new file mode 100644 index 0000000000000..63bf4f6d9ba0b --- /dev/null +++ b/include/llvm/ADT/APInt.h @@ -0,0 +1,1612 @@ +//===-- llvm/ADT/APInt.h - For Arbitrary Precision Integer -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integral +// constant values and operations on them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APINT_H +#define LLVM_APINT_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <climits> +#include <cstring> +#include <string> + +namespace llvm { + class Serializer; + class Deserializer; + class FoldingSetNodeID; + class raw_ostream; + + template<typename T> + class SmallVectorImpl; + + /* An unsigned host type used as a single part of a multi-part + bignum. */ + typedef uint64_t integerPart; + + const unsigned int host_char_bit = 8; + const unsigned int integerPartWidth = host_char_bit * + static_cast<unsigned int>(sizeof(integerPart)); + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// APInt - This class represents arbitrary precision constant integral values. +/// It is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +/// @brief Class for arbitrary precision integers. +class APInt { + unsigned BitWidth; ///< The number of bits in this APInt. + + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + /// This enum is used to hold the constants we needed for APInt. + enum { + /// Bits in a word + APINT_BITS_PER_WORD = static_cast<unsigned int>(sizeof(uint64_t)) * + CHAR_BIT, + /// Byte size of a word + APINT_WORD_SIZE = static_cast<unsigned int>(sizeof(uint64_t)) + }; + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /// @brief Fast internal constructor + APInt(uint64_t* val, unsigned bits) : BitWidth(bits), pVal(val) { } + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this APInt just has one word to store value. + bool isSingleWord() const { + return BitWidth <= APINT_BITS_PER_WORD; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static unsigned whichWord(unsigned bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// @returns the bit position in a word for the specified bit position + /// in the APInt. + /// @brief Determine which bit in a word a bit is in. + static unsigned whichBit(unsigned bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static uint64_t maskBit(unsigned bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + APInt& clearUnusedBits() { + // Compute how many bits are used in the final word + unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shift is the same size as + // the word size (64). + return *this; + + // Mask out the high bits. + uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits); + if (isSingleWord()) + VAL &= mask; + else + pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + uint64_t getWord(unsigned bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an APInt + void fromString(unsigned numBits, const char *strStart, unsigned slen, + uint8_t radix); + + /// This is used by the toString method to divide by the radix. It simply + /// provides a more convenient form of divide for internal use since KnuthDiv + /// has specific constraints on its inputs. If those constraints are not met + /// then it provides a simpler form of divide. + /// @brief An internal division function for dividing APInts. + static void divide(const APInt LHS, unsigned lhsWords, + const APInt &RHS, unsigned rhsWords, + APInt *Quotient, APInt *Remainder); + + /// out-of-line slow case for inline constructor + void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt& that); + + /// out-of-line slow case for shl + APInt shlSlowCase(unsigned shiftAmt) const; + + /// out-of-line slow case for operator& + APInt AndSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator| + APInt OrSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator^ + APInt XorSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator= + APInt& AssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator== + bool EqualSlowCase(uint64_t Val) const; + + /// out-of-line slow case for countLeadingZeros + unsigned countLeadingZerosSlowCase() const; + + /// out-of-line slow case for countTrailingOnes + unsigned countTrailingOnesSlowCase() const; + + /// out-of-line slow case for countPopulation + unsigned countPopulationSlowCase() const; + +public: + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed APInt + /// @param val the initial value of the APInt + /// @param isSigned how to treat signedness of val + /// @brief Create a new APInt of numBits width, initialized as val. + APInt(unsigned numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = val; + else + initSlowCase(numBits, val, isSigned); + clearUnusedBits(); + } + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed APInt + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the APInt + /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed APInt + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @param radix the radix to use for the conversion + /// @brief Construct an APInt from a string representation. + APInt(unsigned numBits, const char strStart[], unsigned slen, uint8_t radix); + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + APInt(const APInt& that) + : BitWidth(that.BitWidth), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = that.VAL; + else + initSlowCase(that); + } + + /// @brief Destructor. + ~APInt() { + if (!isSingleWord()) + delete [] pVal; + } + + /// Default constructor that creates an uninitialized APInt. This is useful + /// for object deserialization (pair this with the static method Read). + explicit APInt() : BitWidth(1) {} + + /// Profile - Used to insert APInt objects, or objects that contain APInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& id) const; + + /// @brief Used by the Bitcode serializer to emit APInts to Bitcode. + void Emit(Serializer& S) const; + + /// @brief Used by the Bitcode deserializer to deserialize APInts. + void Read(Deserializer& D); + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this APInt to determine if it is set. + /// @returns true if this APInt is negative, false otherwise + /// @brief Determine sign of this APInt. + bool isNegative() const { + return (*this)[BitWidth - 1]; + } + + /// This tests the high bit of the APInt to determine if it is unset. + /// @brief Determine if this APInt Value is non-negative (>= 0) + bool isNonNegative() const { + return !isNegative(); + } + + /// This tests if the value of this APInt is positive (> 0). Note + /// that 0 is not a positive value. + /// @returns true if this APInt is positive. + /// @brief Determine if this APInt Value is positive. + bool isStrictlyPositive() const { + return isNonNegative() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the APInt are set or not. + /// @brief Determine if all bits are set + bool isAllOnesValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the largest unsigned value. + bool isMaxValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the largest signed value. + bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == BitWidth - 1; + } + + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest unsigned value. + bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest signed value. + bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// @brief Check if this APInt has an N-bits unsigned integer value. + bool isIntN(unsigned N) const { + assert(N && "N == 0 ???"); + if (N >= getBitWidth()) + return true; + + if (isSingleWord()) + return VAL == (VAL & (~0ULL >> (64 - N))); + APInt Tmp(N, getNumWords(), pVal); + Tmp.zext(getBitWidth()); + return Tmp == (*this); + } + + /// @brief Check if this APInt has an N-bits signed integer value. + bool isSignedIntN(unsigned N) const { + assert(N && "N == 0 ???"); + return getMinSignedBits() <= N; + } + + /// @returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const; + + /// isSignBit - Return true if this is the value returned by getSignBit. + bool isSignBit() const { return isMinSignedValue(); } + + /// This converts the APInt to a boolean value as a test against zero. + /// @brief Boolean conversion function. + bool getBoolValue() const { + return *this != 0; + } + + /// getLimitedValue - If this value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return (getActiveBits() > 64 || getZExtValue() > Limit) ? + Limit : getZExtValue(); + } + + /// @} + /// @name Value Generators + /// @{ + /// @brief Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(unsigned numBits) { + return APInt(numBits, 0).set(); + } + + /// @brief Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(unsigned numBits) { + return APInt(numBits, 0).set().clear(numBits - 1); + } + + /// @brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// @brief Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(unsigned numBits) { + return APInt(numBits, 0).set(numBits - 1); + } + + /// getSignBit - This is just a wrapper function of getSignedMinValue(), and + /// it helps code readability when we want to get a SignBit. + /// @brief Get the SignBit for a specific bit width. + static APInt getSignBit(unsigned BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// @returns the all-ones value for an APInt of the specified bit-width. + /// @brief Get the all-ones value. + static APInt getAllOnesValue(unsigned numBits) { + return APInt(numBits, 0).set(); + } + + /// @returns the '0' value for an APInt of the specified bit-width. + /// @brief Get the '0' value. + static APInt getNullValue(unsigned numBits) { + return APInt(numBits, 0); + } + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// @returns the high "numBits" bits of this APInt. + APInt getHiBits(unsigned numBits) const; + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// @returns the low "numBits" bits of this APInt. + APInt getLoBits(unsigned numBits) const; + + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other + /// bits will be zero. For example, with parameters(32, 0, 16) you would get + /// 0x0000FFFF. If hiBit is less than loBit then the set bits "wrap". For + /// example, with parameters (32, 28, 4), you would get 0xF000000F. + /// @param numBits the intended bit width of the result + /// @param loBit the index of the lowest bit set. + /// @param hiBit the index of the highest bit set. + /// @returns An APInt value with the requested bits set. + /// @brief Get a value with a block of bits set. + static APInt getBitsSet(unsigned numBits, unsigned loBit, unsigned hiBit) { + assert(hiBit <= numBits && "hiBit out of range"); + assert(loBit < numBits && "loBit out of range"); + if (hiBit < loBit) + return getLowBitsSet(numBits, hiBit) | + getHighBitsSet(numBits, numBits-loBit); + return getLowBitsSet(numBits, hiBit-loBit).shl(loBit); + } + + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param hiBitsSet the number of high-order bits set in the result. + /// @brief Get a value with high bits set + static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet) { + assert(hiBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (hiBitsSet == 0) + return APInt(numBits, 0); + unsigned shiftAmt = numBits - hiBitsSet; + // For small values, return quickly + if (numBits <= APINT_BITS_PER_WORD) + return APInt(numBits, ~0ULL << shiftAmt); + return (~APInt(numBits, 0)).shl(shiftAmt); + } + + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param loBitsSet the number of low-order bits set in the result. + /// @brief Get a value with low bits set + static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet) { + assert(loBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (loBitsSet == 0) + return APInt(numBits, 0); + if (loBitsSet == APINT_BITS_PER_WORD) + return APInt(numBits, -1ULL); + // For small values, return quickly. + if (numBits < APINT_BITS_PER_WORD) + return APInt(numBits, (1ULL << loBitsSet) - 1); + return (~APInt(numBits, 0)).lshr(numBits - loBitsSet); + } + + /// The hash value is computed as the sum of the words and the bit width. + /// @returns A hash value computed from the sum of the APInt words. + /// @brief Get a hash value based on this APInt + uint64_t getHashValue() const; + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new APInt value representing *this incremented by one + /// @brief Postfix increment operator. + const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + APInt& operator++(); + + /// @returns a new APInt representing *this decremented by one. + /// @brief Postfix decrement operator. + const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + APInt& operator--(); + + /// Performs a bitwise complement operation on this APInt. + /// @returns an APInt that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + APInt operator~() const { + APInt Result(*this); + Result.flip(); + return Result; + } + + /// Negates *this using two's complement logic. + /// @returns An APInt value representing the negation of *this. + /// @brief Unary negation operator + APInt operator-() const { + return APInt(BitWidth, 0) - (*this); + } + + /// Performs logical negation operation on this APInt. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + bool operator!() const; + + /// @} + /// @name Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + APInt& operator=(const APInt& RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + VAL = RHS.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + return AssignSlowCase(RHS); + } + + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// @returns *this after assignment of RHS value. + /// @brief Assignment operator. + APInt& operator=(uint64_t RHS); + + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after ANDing with RHS. + /// @brief Bitwise AND assignment operator. + APInt& operator&=(const APInt& RHS); + + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// @returns *this after ORing with RHS. + /// @brief Bitwise OR assignment operator. + APInt& operator|=(const APInt& RHS); + + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after XORing with RHS. + /// @brief Bitwise XOR assignment operator. + APInt& operator^=(const APInt& RHS); + + /// Multiplies this APInt by RHS and assigns the result to *this. + /// @returns *this + /// @brief Multiplication assignment operator. + APInt& operator*=(const APInt& RHS); + + /// Adds RHS to *this and assigns the result to *this. + /// @returns *this + /// @brief Addition assignment operator. + APInt& operator+=(const APInt& RHS); + + /// Subtracts RHS from *this and assigns the result to *this. + /// @returns *this + /// @brief Subtraction assignment operator. + APInt& operator-=(const APInt& RHS); + + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// @returns *this after shifting left by shiftAmt + /// @brief Left-shift assignment function. + APInt& operator<<=(unsigned shiftAmt) { + *this = shl(shiftAmt); + return *this; + } + + /// @} + /// @name Binary Operators + /// @{ + /// Performs a bitwise AND operation on *this and RHS. + /// @returns An APInt value representing the bitwise AND of *this and RHS. + /// @brief Bitwise AND operator. + APInt operator&(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL & RHS.VAL); + return AndSlowCase(RHS); + } + APInt And(const APInt& RHS) const { + return this->operator&(RHS); + } + + /// Performs a bitwise OR operation on *this and RHS. + /// @returns An APInt value representing the bitwise OR of *this and RHS. + /// @brief Bitwise OR operator. + APInt operator|(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL | RHS.VAL); + return OrSlowCase(RHS); + } + APInt Or(const APInt& RHS) const { + return this->operator|(RHS); + } + + /// Performs a bitwise XOR operation on *this and RHS. + /// @returns An APInt value representing the bitwise XOR of *this and RHS. + /// @brief Bitwise XOR operator. + APInt operator^(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + return XorSlowCase(RHS); + } + APInt Xor(const APInt& RHS) const { + return this->operator^(RHS); + } + + /// Multiplies this APInt by RHS and returns the result. + /// @brief Multiplication operator. + APInt operator*(const APInt& RHS) const; + + /// Adds RHS to this APInt and returns the result. + /// @brief Addition operator. + APInt operator+(const APInt& RHS) const; + APInt operator+(uint64_t RHS) const { + return (*this) + APInt(BitWidth, RHS); + } + + /// Subtracts RHS from this APInt and returns the result. + /// @brief Subtraction operator. + APInt operator-(const APInt& RHS) const; + APInt operator-(uint64_t RHS) const { + return (*this) - APInt(BitWidth, RHS); + } + + APInt operator<<(unsigned Bits) const { + return shl(Bits); + } + + APInt operator<<(const APInt &Bits) const { + return shl(Bits); + } + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(unsigned shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(unsigned shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + return shlSlowCase(shiftAmt); + } + + /// @brief Rotate left by rotateAmt. + APInt rotl(unsigned rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(unsigned rotateAmt) const; + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(const APInt &shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(const APInt &shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(const APInt &shiftAmt) const; + + /// @brief Rotate left by rotateAmt. + APInt rotl(const APInt &rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(const APInt &rotateAmt) const; + + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new APInt value containing the division result + /// @brief Unsigned division operation. + APInt udiv(const APInt& RHS) const; + + /// Signed divide this APInt by APInt RHS. + /// @brief Signed division function for APInt. + APInt sdiv(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new APInt value containing the remainder result + /// @brief Unsigned remainder operation. + APInt urem(const APInt& RHS) const; + + /// Signed remainder operation on APInt. + /// @brief Function for signed remainder operation. + APInt srem(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS.isNegative()) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two APInt values and obtain both the + /// quotient and remainder. This function does both operations in the same + /// computation making it a little more efficient. The pair of input arguments + /// may overlap with the pair of output arguments. It is safe to call + /// udivrem(X, Y, X, Y), for example. + /// @brief Dual division/remainder interface. + static void udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) + { + if (LHS.isNegative()) { + if (RHS.isNegative()) + APInt::udivrem(-LHS, -RHS, Quotient, Remainder); + else + APInt::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + APInt::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + APInt::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// @returns the bit value at bitPosition + /// @brief Array-indexing support. + bool operator[](unsigned bitPosition) const; + + /// @} + /// @name Comparison Operators + /// @{ + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @brief Equality operator. + bool operator==(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return VAL == RHS.VAL; + return EqualSlowCase(RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality operator. + bool operator==(uint64_t Val) const { + if (isSingleWord()) + return VAL == Val; + return EqualSlowCase(Val); + } + + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + bool eq(const APInt &RHS) const { + return (*this) == RHS; + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(const APInt& RHS) const { + return !((*this) == RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + bool ne(const APInt &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + bool ult(const APInt& RHS) const; + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + bool slt(const APInt& RHS) const; + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + bool ule(const APInt& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + bool sle(const APInt& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + bool ugt(const APInt& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + bool sgt(const APInt& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + bool uge(const APInt& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + bool sge(const APInt& RHS) const { + return !slt(RHS); + } + + /// This operation tests if there are any pairs of corresponding bits + /// between this APInt and RHS that are both set. + bool intersects(const APInt &RHS) const { + return (*this & RHS) != 0; + } + + /// @} + /// @name Resizing Operators + /// @{ + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + /// @brief Truncate to new width. + APInt &trunc(unsigned width); + + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + /// @brief Sign extend to a new width. + APInt &sext(unsigned width); + + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + /// @brief Zero extend to a new width. + APInt &zext(unsigned width); + + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + /// @brief Sign extend or truncate to width + APInt &sextOrTrunc(unsigned width); + + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + /// @brief Zero extend or truncate to width + APInt &zextOrTrunc(unsigned width); + + /// @} + /// @name Bit Manipulation Operators + /// @{ + /// @brief Set every bit to 1. + APInt& set() { + if (isSingleWord()) { + VAL = -1ULL; + return clearUnusedBits(); + } + + // Set all the bits in all the words. + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; + // Clear the unused ones + return clearUnusedBits(); + } + + /// Set the given bit to 1 whose position is given as "bitPosition". + /// @brief Set a given bit to 1. + APInt& set(unsigned bitPosition); + + /// @brief Set every bit to 0. + APInt& clear() { + if (isSingleWord()) + VAL = 0; + else + memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + APInt& clear(unsigned bitPosition); + + /// @brief Toggle every bit to its opposite value. + APInt& flip() { + if (isSingleWord()) { + VAL ^= -1ULL; + return clearUnusedBits(); + } + for (unsigned i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; + return clearUnusedBits(); + } + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + APInt& flip(unsigned bitPosition); + + /// @} + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + unsigned getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this APInt. + /// @brief Get the number of words. + unsigned getNumWords() const { + return getNumWords(BitWidth); + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value with a + /// given bit width. + /// @brief Get the number of words. + static unsigned getNumWords(unsigned BitWidth) { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + unsigned getActiveBits() const { + return BitWidth - countLeadingZeros(); + } + + /// This function returns the number of active words in the value of this + /// APInt. This is used in conjunction with getActiveData to extract the raw + /// value of the APInt. + unsigned getActiveWords() const { + return whichWord(getActiveBits()-1) + 1; + } + + /// Computes the minimum bit width for this APInt while considering it to be + /// a signed (and probably negative) value. If the value is not negative, + /// this function returns the same value as getActiveBits()+1. Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + /// @brief Get the minimum bit size for this signed APInt + unsigned getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits()+1; + } + + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + uint64_t getZExtValue() const { + if (isSingleWord()) + return VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return pVal[0]; + } + + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + int64_t getSExtValue() const { + if (isSingleWord()) + return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> + (APINT_BITS_PER_WORD - BitWidth); + assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static unsigned getBitsNeeded(const char* str, unsigned slen, uint8_t radix); + + /// countLeadingZeros - This function is an APInt version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + unsigned countLeadingZeros() const { + if (isSingleWord()) { + unsigned unusedBits = APINT_BITS_PER_WORD - BitWidth; + return CountLeadingZeros_64(VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } + + /// countLeadingOnes - This function is an APInt version of the + /// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number + /// of ones from the most significant bit to the first zero bit. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + unsigned countLeadingOnes() const; + + /// countTrailingZeros - This function is an APInt version of the + /// countTrailingZeros_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first set bit. + /// @returns BitWidth if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + unsigned countTrailingZeros() const; + + /// countTrailingOnes - This function is an APInt version of the + /// countTrailingOnes_{32,64} functions in MathExtras.h. It counts + /// the number of ones from the least significant bit to the first zero bit. + /// @returns BitWidth if the value is all ones. + /// @returns the number of ones from the least significant bit to the first + /// zero bit. + /// @brief Count the number of trailing one bits. + unsigned countTrailingOnes() const { + if (isSingleWord()) + return CountTrailingOnes_64(VAL); + return countTrailingOnesSlowCase(); + } + + /// countPopulation - This function is an APInt version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the APInt value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + unsigned countPopulation() const { + if (isSingleWord()) + return CountPopulation_64(VAL); + return countPopulationSlowCase(); + } + + /// @} + /// @name Conversion Functions + /// @{ + void print(raw_ostream &OS, bool isSigned) const; + + /// toString - Converts an APInt to a string and append it to Str. Str is + /// commonly a SmallString. + void toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed) const; + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, false); + } + + /// Considers the APInt to be signed and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + toString(Str, Radix, true); + } + + /// toString - This returns the APInt as a std::string. Note that this is an + /// inefficient method. It is better to pass in a SmallVector/SmallString + /// to the methods above to avoid thrashing the heap for the string. + std::string toString(unsigned Radix, bool Signed) const; + + + /// @returns a byte-swapped representation of this APInt Value. + APInt byteSwap() const; + + /// @brief Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// @brief Converts this unsigned APInt to a double value. + double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts APInt bits to a double + double bitsToDouble() const { + union { + uint64_t I; + double D; + } T; + T.I = (isSingleWord() ? VAL : pVal[0]); + return T.D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts APInt bits to a double + float bitsToFloat() const { + union { + unsigned I; + float F; + } T; + T.I = unsigned((isSingleWord() ? VAL : pVal[0])); + return T.F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to APInt bits. + APInt& doubleToBits(double V) { + union { + uint64_t I; + double D; + } T; + T.D = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to APInt bits. + APInt& floatToBits(float V) { + union { + unsigned I; + float F; + } T; + T.F = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// @} + /// @name Mathematics Operations + /// @{ + + /// @returns the floor log base 2 of this APInt. + unsigned logBase2() const { + return BitWidth - 1 - countLeadingZeros(); + } + + /// @returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// @brief Compute the square root + APInt sqrt() const; + + /// If *this is < 0 then return -(*this), otherwise *this; + /// @brief Get the absolute value; + APInt abs() const { + if (isNegative()) + return -(*this); + return *this; + } + + /// @returns the multiplicative inverse for a given modulo. + APInt multiplicativeInverse(const APInt& modulo) const; + + /// @} + /// @name Support for division by constant + /// @{ + + /// Calculate the magic number for signed division by a constant. + struct ms; + ms magic() const; + + /// Calculate the magic number for unsigned division by a constant. + struct mu; + mu magicu() const; + + /// @} + /// @name Building-block Operations for APInt and APFloat + /// @{ + + // These building block operations operate on a representation of + // arbitrary precision, two's-complement, bignum integer values. + // They should be sufficient to implement APInt and APFloat bignum + // requirements. Inputs are generally a pointer to the base of an + // array of integer parts, representing an unsigned bignum, and a + // count of how many parts there are. + + /// Sets the least significant part of a bignum to the input value, + /// and zeroes out higher parts. */ + static void tcSet(integerPart *, integerPart, unsigned int); + + /// Assign one bignum to another. + static void tcAssign(integerPart *, const integerPart *, unsigned int); + + /// Returns true if a bignum is zero, false otherwise. + static bool tcIsZero(const integerPart *, unsigned int); + + /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. + static int tcExtractBit(const integerPart *, unsigned int bit); + + /// Copy the bit vector of width srcBITS from SRC, starting at bit + /// srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB + /// becomes the least significant bit of DST. All high bits above + /// srcBITS in DST are zero-filled. + static void tcExtract(integerPart *, unsigned int dstCount, + const integerPart *, + unsigned int srcBits, unsigned int srcLSB); + + /// Set the given bit of a bignum. Zero-based. + static void tcSetBit(integerPart *, unsigned int bit); + + /// Returns the bit number of the least or most significant set bit + /// of a number. If the input number has no bits set -1U is + /// returned. + static unsigned int tcLSB(const integerPart *, unsigned int); + static unsigned int tcMSB(const integerPart *parts, unsigned int n); + + /// Negate a bignum in-place. + static void tcNegate(integerPart *, unsigned int); + + /// DST += RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcAdd(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST -= RHS + CARRY where CARRY is zero or one. Returns the + /// carry flag. + static integerPart tcSubtract(integerPart *, const integerPart *, + integerPart carry, unsigned); + + /// DST += SRC * MULTIPLIER + PART if add is true + /// DST = SRC * MULTIPLIER + PART if add is false + /// + /// Requires 0 <= DSTPARTS <= SRCPARTS + 1. If DST overlaps SRC + /// they must start at the same point, i.e. DST == SRC. + /// + /// If DSTPARTS == SRC_PARTS + 1 no overflow occurs and zero is + /// returned. Otherwise DST is filled with the least significant + /// DSTPARTS parts of the result, and if all of the omitted higher + /// parts were zero return zero, otherwise overflow occurred and + /// return one. + static int tcMultiplyPart(integerPart *dst, const integerPart *src, + integerPart multiplier, integerPart carry, + unsigned int srcParts, unsigned int dstParts, + bool add); + + /// DST = LHS * RHS, where DST has the same width as the operands + /// and is filled with the least significant parts of the result. + /// Returns one if overflow occurred, otherwise zero. DST must be + /// disjoint from both operands. + static int tcMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned); + + /// DST = LHS * RHS, where DST has width the sum of the widths of + /// the operands. No overflow occurs. DST must be disjoint from + /// both operands. Returns the number of parts required to hold the + /// result. + static unsigned int tcFullMultiply(integerPart *, const integerPart *, + const integerPart *, unsigned, unsigned); + + /// If RHS is zero LHS and REMAINDER are left unchanged, return one. + /// Otherwise set LHS to LHS / RHS with the fractional part + /// discarded, set REMAINDER to the remainder, return zero. i.e. + /// + /// OLD_LHS = RHS * LHS + REMAINDER + /// + /// SCRATCH is a bignum of the same size as the operands and result + /// for use by the routine; its contents need not be initialized + /// and are destroyed. LHS, REMAINDER and SCRATCH must be + /// distinct. + static int tcDivide(integerPart *lhs, const integerPart *rhs, + integerPart *remainder, integerPart *scratch, + unsigned int parts); + + /// Shift a bignum left COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftLeft(integerPart *, unsigned int parts, + unsigned int count); + + /// Shift a bignum right COUNT bits. Shifted in bits are zero. + /// There are no restrictions on COUNT. + static void tcShiftRight(integerPart *, unsigned int parts, + unsigned int count); + + /// The obvious AND, OR and XOR and complement operations. + static void tcAnd(integerPart *, const integerPart *, unsigned int); + static void tcOr(integerPart *, const integerPart *, unsigned int); + static void tcXor(integerPart *, const integerPart *, unsigned int); + static void tcComplement(integerPart *, unsigned int); + + /// Comparison (unsigned) of two bignums. + static int tcCompare(const integerPart *, const integerPart *, + unsigned int); + + /// Increment a bignum in-place. Return the carry flag. + static integerPart tcIncrement(integerPart *, unsigned int); + + /// Set the least significant BITS and clear the rest. + static void tcSetLeastSignificantBits(integerPart *, unsigned int, + unsigned int bits); + + /// @brief debug method + void dump() const; + + /// @} +}; + +/// Magic data for optimising signed division by a constant. +struct APInt::ms { + APInt m; ///< magic number + unsigned s; ///< shift amount +}; + +/// Magic data for optimising unsigned division by a constant. +struct APInt::mu { + APInt m; ///< magic number + bool a; ///< add indicator + unsigned s; ///< shift amount +}; + +inline bool operator==(uint64_t V1, const APInt& V2) { + return V2 == V1; +} + +inline bool operator!=(uint64_t V1, const APInt& V2) { + return V2 != V1; +} + +inline raw_ostream &operator<<(raw_ostream &OS, const APInt &I) { + I.print(OS, true); + return OS; +} + +namespace APIntOps { + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be signed. +inline APInt smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be unsigned. +inline APInt umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// @brief Check if the specified APInt has a N-bits unsigned integer value. +inline bool isIntN(unsigned N, const APInt& APIVal) { + return APIVal.isIntN(N); +} + +/// @brief Check if the specified APInt has a N-bits signed integer value. +inline bool isSignedIntN(unsigned N, const APInt& APIVal) { + return APIVal.isSignedIntN(N); +} + +/// @returns true if the argument APInt value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +inline bool isMask(unsigned numBits, const APInt& APIVal) { + return numBits <= APIVal.getBitWidth() && + APIVal == APInt::getLowBitsSet(APIVal.getBitWidth(), numBits); +} + +/// @returns true if the argument APInt value contains a sequence of ones +/// with the remainder zero. +inline bool isShiftedMask(unsigned numBits, const APInt& APIVal) { + return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal); +} + +/// @returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt& APIVal) { + return APIVal.byteSwap(); +} + +/// @returns the floor log base 2 of the specified APInt value. +inline unsigned logBase2(const APInt& APIVal) { + return APIVal.logBase2(); +} + +/// GreatestCommonDivisor - This function returns the greatest common +/// divisor of the two APInt values using Euclid's algorithm. +/// @returns the greatest common divisor of Val1 and Val2 +/// @brief Compute GCD of two APInt values. +APInt GreatestCommonDivisor(const APInt& Val1, const APInt& Val2); + +/// Treats the APInt as an unsigned value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundAPIntToDouble(const APInt& APIVal) { + return APIVal.roundToDouble(); +} + +/// Treats the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundSignedAPIntToDouble(const APInt& APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// @brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt& APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// Treast the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a float value. +inline float RoundSignedAPIntToFloat(const APInt& APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// RoundDoubleToAPInt - This function convert a double value to an APInt value. +/// @brief Converts the given double value into a APInt. +APInt RoundDoubleToAPInt(double Double, unsigned width); + +/// RoundFloatToAPInt - Converts a float value into an APInt value. +/// @brief Converts a float value into a APInt. +inline APInt RoundFloatToAPInt(float Float, unsigned width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +inline APInt ashr(const APInt& LHS, unsigned shiftAmt) { + return LHS.ashr(shiftAmt); +} + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +inline APInt lshr(const APInt& LHS, unsigned shiftAmt) { + return LHS.lshr(shiftAmt); +} + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +inline APInt shl(const APInt& LHS, unsigned shiftAmt) { + return LHS.shl(shiftAmt); +} + +/// Signed divide APInt LHS by APInt RHS. +/// @brief Signed division function for APInt. +inline APInt sdiv(const APInt& LHS, const APInt& RHS) { + return LHS.sdiv(RHS); +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +inline APInt udiv(const APInt& LHS, const APInt& RHS) { + return LHS.udiv(RHS); +} + +/// Signed remainder operation on APInt. +/// @brief Function for signed remainder operation. +inline APInt srem(const APInt& LHS, const APInt& RHS) { + return LHS.srem(RHS); +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +inline APInt urem(const APInt& LHS, const APInt& RHS) { + return LHS.urem(RHS); +} + +/// Performs multiplication on APInt values. +/// @brief Function for multiplication operation. +inline APInt mul(const APInt& LHS, const APInt& RHS) { + return LHS * RHS; +} + +/// Performs addition on APInt values. +/// @brief Function for addition operation. +inline APInt add(const APInt& LHS, const APInt& RHS) { + return LHS + RHS; +} + +/// Performs subtraction on APInt values. +/// @brief Function for subtraction operation. +inline APInt sub(const APInt& LHS, const APInt& RHS) { + return LHS - RHS; +} + +/// Performs bitwise AND operation on APInt LHS and +/// APInt RHS. +/// @brief Bitwise AND function for APInt. +inline APInt And(const APInt& LHS, const APInt& RHS) { + return LHS & RHS; +} + +/// Performs bitwise OR operation on APInt LHS and APInt RHS. +/// @brief Bitwise OR function for APInt. +inline APInt Or(const APInt& LHS, const APInt& RHS) { + return LHS | RHS; +} + +/// Performs bitwise XOR operation on APInt. +/// @brief Bitwise XOR function for APInt. +inline APInt Xor(const APInt& LHS, const APInt& RHS) { + return LHS ^ RHS; +} + +/// Performs a bitwise complement operation on APInt. +/// @brief Bitwise complement function. +inline APInt Not(const APInt& APIVal) { + return ~APIVal; +} + +} // End of APIntOps namespace + +} // End of llvm namespace + +#endif diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h new file mode 100644 index 0000000000000..1c9931c30fe51 --- /dev/null +++ b/include/llvm/ADT/APSInt.h @@ -0,0 +1,264 @@ +//===-- llvm/ADT/APSInt.h - Arbitrary Precision Signed Int -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APSINT_H +#define LLVM_APSINT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + +class APSInt : public APInt { + bool IsUnsigned; +public: + /// Default constructor that creates an uninitialized APInt. + explicit APSInt() {} + + /// APSInt ctor - Create an APSInt with the specified width, default to + /// unsigned. + explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) + : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} + + explicit APSInt(const APInt &I, bool isUnsigned = true) + : APInt(I), IsUnsigned(isUnsigned) {} + + APSInt &operator=(const APSInt &RHS) { + APInt::operator=(RHS); + IsUnsigned = RHS.IsUnsigned; + return *this; + } + + APSInt &operator=(const APInt &RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + APSInt &operator=(uint64_t RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + // Query sign information. + bool isSigned() const { return !IsUnsigned; } + bool isUnsigned() const { return IsUnsigned; } + void setIsUnsigned(bool Val) { IsUnsigned = Val; } + void setIsSigned(bool Val) { IsUnsigned = !Val; } + + /// toString - Append this APSInt to the specified SmallString. + void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { + APInt::toString(Str, Radix, isSigned()); + } + /// toString - Converts an APInt to a std::string. This is an inefficient + /// method, your should prefer passing in a SmallString instead. + std::string toString(unsigned Radix) const { + return APInt::toString(Radix, isSigned()); + } + using APInt::toString; + + APSInt& extend(uint32_t width) { + if (IsUnsigned) + zext(width); + else + sext(width); + return *this; + } + + APSInt& extOrTrunc(uint32_t width) { + if (IsUnsigned) + zextOrTrunc(width); + else + sextOrTrunc(width); + return *this; + } + + const APSInt &operator%=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = urem(RHS); + else + *this = srem(RHS); + return *this; + } + const APSInt &operator/=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = udiv(RHS); + else + *this = sdiv(RHS); + return *this; + } + APSInt operator%(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(urem(RHS), true) : APSInt(srem(RHS), false); + } + APSInt operator/(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? APSInt(udiv(RHS), true) : APSInt(sdiv(RHS), false); + } + + APSInt operator>>(unsigned Amt) const { + return IsUnsigned ? APSInt(lshr(Amt), true) : APSInt(ashr(Amt), false); + } + APSInt& operator>>=(unsigned Amt) { + *this = *this >> Amt; + return *this; + } + + inline bool operator<(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ult(RHS) : slt(RHS); + } + inline bool operator>(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ugt(RHS) : sgt(RHS); + } + inline bool operator<=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ule(RHS) : sle(RHS); + } + inline bool operator>=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? uge(RHS) : sge(RHS); + } + + // The remaining operators just wrap the logic of APInt, but retain the + // signedness information. + + APSInt operator<<(unsigned Bits) const { + return APSInt(static_cast<const APInt&>(*this) << Bits, IsUnsigned); + } + APSInt& operator<<=(unsigned Amt) { + *this = *this << Amt; + return *this; + } + + APSInt& operator++() { + static_cast<APInt&>(*this)++; + return *this; + } + APSInt& operator--() { + static_cast<APInt&>(*this)--; + return *this; + } + APSInt operator++(int) { + return APSInt(++static_cast<APInt&>(*this), IsUnsigned); + } + APSInt operator--(int) { + return APSInt(--static_cast<APInt&>(*this), IsUnsigned); + } + APSInt operator-() const { + return APSInt(-static_cast<const APInt&>(*this), IsUnsigned); + } + APSInt& operator+=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) += RHS; + return *this; + } + APSInt& operator-=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) -= RHS; + return *this; + } + APSInt& operator*=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) *= RHS; + return *this; + } + APSInt& operator&=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) &= RHS; + return *this; + } + APSInt& operator|=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) |= RHS; + return *this; + } + APSInt& operator^=(const APSInt& RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + static_cast<APInt&>(*this) ^= RHS; + return *this; + } + + APSInt operator&(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) & RHS, IsUnsigned); + } + 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<const APInt&>(*this) | RHS, IsUnsigned); + } + 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<const APInt&>(*this) ^ RHS, IsUnsigned); + } + APSInt Xor(const APSInt& RHS) const { + return this->operator^(RHS); + } + + APSInt operator*(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) * RHS, IsUnsigned); + } + APSInt operator+(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) + RHS, IsUnsigned); + } + APSInt operator-(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return APSInt(static_cast<const APInt&>(*this) - RHS, IsUnsigned); + } + APSInt operator~() const { + return APSInt(~static_cast<const APInt&>(*this), IsUnsigned); + } + + /// getMaxValue - Return the APSInt representing the maximum integer value + /// with the given bit width and signedness. + static APSInt getMaxValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMaxValue(numBits) + : APInt::getSignedMaxValue(numBits), Unsigned); + } + + /// getMinValue - Return the APSInt representing the minimum integer value + /// with the given bit width and signedness. + static APSInt getMinValue(uint32_t numBits, bool Unsigned) { + return APSInt(Unsigned ? APInt::getMinValue(numBits) + : APInt::getSignedMinValue(numBits), Unsigned); + } + + /// Profile - Used to insert APSInt objects, or objects that contain APSInt + /// objects, into FoldingSets. + void Profile(FoldingSetNodeID& ID) const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) { + I.print(OS, I.isSigned()); + return OS; +} + + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h new file mode 100644 index 0000000000000..9c046efaaddd9 --- /dev/null +++ b/include/llvm/ADT/BitVector.h @@ -0,0 +1,409 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cassert> +#include <climits> +#include <cstring> + +namespace llvm { + +class BitVector { + typedef unsigned long BitWord; + + enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; + + BitWord *Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Size of allocated memory in BitWord. + +public: + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + reference(); // Undefined + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + ~reference() {} + + reference& operator=(bool t) { + if (t) + *WordRef |= 1L << BitPos; + else + *WordRef &= ~(1L << BitPos); + return *this; + } + + operator bool() const { + return ((*WordRef) & (1L << BitPos)) ? true : false; + } + }; + + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0), Capacity(0) { + Bits = 0; + } + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + Capacity = NumBitWords(s); + Bits = new BitWord[Capacity]; + init_words(Bits, Capacity, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = 0; + Capacity = 0; + return; + } + + Capacity = NumBitWords(RHS.size()); + Bits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits); + } + + ~BitVector() { + delete[] Bits; + } + + /// size - Returns the number of bits in this bitvector. + unsigned size() const { return Size; } + + /// count - Returns the number of bits which are set. + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + ++Prev; + if (Prev >= Size) + return -1; + + unsigned WordPos = Prev / BITWORD_SIZE; + unsigned BitPos = Prev % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// clear - Clear all bits. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > Capacity * BITWORD_SIZE) { + unsigned OldCapacity = Capacity; + grow(N); + init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + } + + // Set any old unused bits that are now included in the BitVector. This + // may set bits that are not included in the new vector, but we will clear + // them back out below. + if (N > Size) + set_unused_bits(t); + + // Update the size, and clear out any bits that are now unused + unsigned OldSize = Size; + Size = N; + if (t || N < OldSize) + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > Capacity * BITWORD_SIZE) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, Capacity, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + BitVector &reset() { + init_words(Bits, Capacity, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + // No argument flip. + BitVector operator~() const { + return BitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + assert (Idx < Size && "Out-of-bounds Bit access."); + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + assert (Idx < Size && "Out-of-bounds Bit access."); + BitWord Mask = 1L << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + + // Verify that any extra words are all zeros. + if (i != ThisWords) { + for (; i != ThisWords; ++i) + if (Bits[i]) + return false; + } else if (i != RHSWords) { + for (; i != RHSWords; ++i) + if (RHS.Bits[i]) + return false; + } + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + BitVector &operator&=(const BitVector &RHS) { + unsigned ThisWords = NumBitWords(size()); + unsigned RHSWords = NumBitWords(RHS.size()); + unsigned i; + for (i = 0; i != std::min(ThisWords, RHSWords); ++i) + Bits[i] &= RHS.Bits[i]; + + // Any bits that are just in this bitvector become zero, because they aren't + // in the RHS bit vector. Any words only in RHS are ignored because they + // are already zero in the LHS. + for (; i != ThisWords; ++i) + Bits[i] = 0; + + return *this; + } + + BitVector &operator|=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector &operator^=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= Capacity * BITWORD_SIZE) { + std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + Capacity = RHSWords; + BitWord *NewBits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + + return *this; + } + +private: + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Set the unused bits in the high words. + void set_unused_bits(bool t = true) { + // Set high words first. + unsigned UsedWords = NumBitWords(Size); + if (Capacity > UsedWords) + init_words(&Bits[UsedWords], (Capacity-UsedWords), t); + + // Then set any stray high bits of the last used word. + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + Bits[UsedWords-1] &= ~(~0L << ExtraBits); + Bits[UsedWords-1] |= (0 - (BitWord)t) << ExtraBits; + } + } + + // Clear the unused bits in the high words. + void clear_unused_bits() { + set_unused_bits(false); + } + + void grow(unsigned NewSize) { + unsigned OldCapacity = Capacity; + Capacity = NumBitWords(NewSize); + BitWord *NewBits = new BitWord[Capacity]; + + // Copy the old bits over. + if (OldCapacity != 0) + std::copy(Bits, &Bits[OldCapacity], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + + clear_unused_bits(); + } + + void init_words(BitWord *B, unsigned NumWords, bool t) { + memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); + } +}; + +inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace +#endif diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h new file mode 100644 index 0000000000000..e18be8963d48b --- /dev/null +++ b/include/llvm/ADT/DenseMap.h @@ -0,0 +1,570 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <utility> +#include <new> + +namespace llvm { + +template<typename T> +struct DenseMapInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isEqual(const T &LHS, const T &RHS); + //static bool isPod() +}; + +// Provide DenseMapInfo for all pointers. +template<typename T> +struct DenseMapInfo<T*> { + static inline T* getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + static inline T* getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable; + return reinterpret_cast<T*>(Val); + } + static unsigned getHashValue(const T *PtrVal) { + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } + static bool isPod() { return true; } +}; + +// Provide DenseMapInfo for chars. +template<> struct DenseMapInfo<char> { + static inline char getEmptyKey() { return ~0; } + static inline char getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const char& Val) { return Val * 37; } + static bool isPod() { return true; } + static bool isEqual(const char &LHS, const char &RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned ints. +template<> struct DenseMapInfo<unsigned> { + static inline unsigned getEmptyKey() { return ~0; } + static inline unsigned getTombstoneKey() { return ~0 - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37; } + static bool isPod() { return true; } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for unsigned longs. +template<> struct DenseMapInfo<unsigned long> { + static inline unsigned long getEmptyKey() { return ~0L; } + static inline unsigned long getTombstoneKey() { return ~0L - 1L; } + static unsigned getHashValue(const unsigned long& Val) { + return (unsigned)(Val * 37L); + } + static bool isPod() { return true; } + static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { + return LHS == RHS; + } +}; + +// Provide DenseMapInfo for all pairs whose members have info. +template<typename T, typename U> +struct DenseMapInfo<std::pair<T, U> > { + typedef std::pair<T, U> Pair; + typedef DenseMapInfo<T> FirstInfo; + typedef DenseMapInfo<U> SecondInfo; + + static inline Pair getEmptyKey() { + return std::make_pair(FirstInfo::getEmptyKey(), + SecondInfo::getEmptyKey()); + } + static inline Pair getTombstoneKey() { + return std::make_pair(FirstInfo::getTombstoneKey(), + SecondInfo::getEmptyKey()); + } + static unsigned getHashValue(const Pair& PairVal) { + uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 + | (uint64_t)SecondInfo::getHashValue(PairVal.second); + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return (unsigned)key; + } + static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } + static bool isPod() { return FirstInfo::isPod() && SecondInfo::isPod(); } +}; + +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename ValueInfoT = DenseMapInfo<ValueT> > +class DenseMapIterator; +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename ValueInfoT = DenseMapInfo<ValueT> > +class DenseMapConstIterator; + +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename ValueInfoT = DenseMapInfo<ValueT> > +class DenseMap { + typedef std::pair<KeyT, ValueT> BucketT; + unsigned NumBuckets; + BucketT *Buckets; + + unsigned NumEntries; + unsigned NumTombstones; +public: + typedef KeyT key_type; + typedef ValueT mapped_type; + typedef BucketT value_type; + + DenseMap(const DenseMap& other) { + NumBuckets = 0; + CopyFrom(other); + } + + explicit DenseMap(unsigned NumInitBuckets = 64) { + init(NumInitBuckets); + } + + ~DenseMap() { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } + operator delete(Buckets); + } + + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; + typedef DenseMapConstIterator<KeyT, ValueT, KeyInfoT> const_iterator; + inline iterator begin() { + return iterator(Buckets, Buckets+NumBuckets); + } + inline iterator end() { + return iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + inline const_iterator begin() const { + return const_iterator(Buckets, Buckets+NumBuckets); + } + inline const_iterator end() const { + return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + + bool empty() const { return NumEntries == 0; } + unsigned size() const { return NumEntries; } + + /// Grow the densemap so that it has at least Size buckets. Does not shrink + void resize(size_t Size) { grow(Size); } + + void clear() { + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (NumEntries * 4 < NumBuckets && NumBuckets > 64) { + shrink_and_clear(); + return; + } + + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey)) { + if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { + P->second.~ValueT(); + --NumEntries; + } + P->first = EmptyKey; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + NumTombstones = 0; + } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket); + } + + iterator find(const KeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + const_iterator find(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueT lookup(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return TheBucket->second; + return ValueT(); + } + + std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { + BucketT *TheBucket; + if (LookupBucketFor(KV.first, TheBucket)) + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + false); // Already in map. + + // Otherwise, insert the new element. + TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket); + return std::make_pair(iterator(TheBucket, Buckets+NumBuckets), + true); + } + + /// insert - Range insertion of pairs. + template<typename InputIt> + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } + + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + bool erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + + value_type& FindAndConstruct(const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return *TheBucket; + + return *InsertIntoBucket(Key, ValueT(), TheBucket); + } + + ValueT &operator[](const KeyT &Key) { + return FindAndConstruct(Key).second; + } + + DenseMap& operator=(const DenseMap& other) { + CopyFrom(other); + return *this; + } + + /// isPointerIntoBucketsArray - Return true if the specified pointer points + /// somewhere into the DenseMap's array of buckets (i.e. either to a key or + /// value in the DenseMap). + bool isPointerIntoBucketsArray(const void *Ptr) const { + return Ptr >= Buckets && Ptr < Buckets+NumBuckets; + } + + /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets + /// array. In conjunction with the previous method, this can be used to + /// determine whether an insertion caused the DenseMap to reallocate. + const void *getPointerIntoBucketsArray() const { return Buckets; } + +private: + void CopyFrom(const DenseMap& other) { + if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (!KeyInfoT::isEqual(P->first, EmptyKey) && + !KeyInfoT::isEqual(P->first, TombstoneKey)) + P->second.~ValueT(); + P->first.~KeyT(); + } + } + + NumEntries = other.NumEntries; + NumTombstones = other.NumTombstones; + + if (NumBuckets) + operator delete(Buckets); + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * + other.NumBuckets)); + + if (KeyInfoT::isPod() && ValueInfoT::isPod()) + memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); + else + for (size_t i = 0; i < other.NumBuckets; ++i) { + new (&Buckets[i].first) KeyT(other.Buckets[i].first); + if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && + !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) + new (&Buckets[i].second) ValueT(other.Buckets[i].second); + } + NumBuckets = other.NumBuckets; + } + + BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, + BucketT *TheBucket) { + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + ++NumEntries; + if (NumEntries*4 >= NumBuckets*3 || + NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + this->grow(NumBuckets * 2); + LookupBucketFor(Key, TheBucket); + } + + // If we are writing over a tombstone, remember this. + if (!KeyInfoT::isEqual(TheBucket->first, getEmptyKey())) + --NumTombstones; + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(Value); + return TheBucket; + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const { + unsigned BucketNo = getHashValue(Val); + unsigned ProbeAmt = 1; + BucketT *BucketsPtr = Buckets; + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + BucketT *FoundTombstone = 0; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(!KeyInfoT::isEqual(Val, EmptyKey) && + !KeyInfoT::isEqual(Val, TombstoneKey) && + "Empty/Tombstone value shouldn't be inserted into map!"); + + while (1) { + BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); + // Found Val's bucket? If so, return it. + if (KeyInfoT::isEqual(ThisBucket->first, Val)) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + if (FoundTombstone) ThisBucket = FoundTombstone; + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + } + } + + void init(unsigned InitBuckets) { + NumEntries = 0; + NumTombstones = 0; + NumBuckets = InitBuckets; + assert(InitBuckets && (InitBuckets & (InitBuckets-1)) == 0 && + "# initial buckets must be a power of two!"); + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*InitBuckets)); + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0; i != InitBuckets; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + } + + void grow(unsigned AtLeast) { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Double the number of buckets. + while (NumBuckets <= AtLeast) + NumBuckets <<= 1; + NumTombstones = 0; + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Insert all the old elements. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->first, DestBucket); + FoundVal = FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->first = B->first; + new (&DestBucket->second) ValueT(B->second); + + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + + // Free the old table. + operator delete(OldBuckets); + } + + void shrink_and_clear() { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Reduce the number of buckets. + NumBuckets = NumEntries > 32 ? 1 << (Log2_32_Ceil(NumEntries) + 1) + : 64; + NumTombstones = 0; + Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT)*NumBuckets)); + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Free the old buckets. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (!KeyInfoT::isEqual(B->first, EmptyKey) && + !KeyInfoT::isEqual(B->first, TombstoneKey)) { + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + + // Free the old table. + operator delete(OldBuckets); + + NumEntries = 0; + } +}; + +template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT> +class DenseMapIterator { + typedef std::pair<KeyT, ValueT> BucketT; +protected: + const BucketT *Ptr, *End; +public: + DenseMapIterator(void) : Ptr(0), End(0) {} + + DenseMapIterator(const BucketT *Pos, const BucketT *E) : Ptr(Pos), End(E) { + AdvancePastEmptyBuckets(); + } + + std::pair<KeyT, ValueT> &operator*() const { + return *const_cast<BucketT*>(Ptr); + } + std::pair<KeyT, ValueT> *operator->() const { + return const_cast<BucketT*>(Ptr); + } + + bool operator==(const DenseMapIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const DenseMapIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline DenseMapIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && + (KeyInfoT::isEqual(Ptr->first, Empty) || + KeyInfoT::isEqual(Ptr->first, Tombstone))) + ++Ptr; + } +}; + +template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT> +class DenseMapConstIterator : public DenseMapIterator<KeyT, ValueT, KeyInfoT> { +public: + DenseMapConstIterator(void) : DenseMapIterator<KeyT, ValueT, KeyInfoT>() {} + DenseMapConstIterator(const std::pair<KeyT, ValueT> *Pos, + const std::pair<KeyT, ValueT> *E) + : DenseMapIterator<KeyT, ValueT, KeyInfoT>(Pos, E) { + } + const std::pair<KeyT, ValueT> &operator*() const { + return *this->Ptr; + } + const std::pair<KeyT, ValueT> *operator->() const { + return this->Ptr; + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h new file mode 100644 index 0000000000000..ce7344bc1f99b --- /dev/null +++ b/include/llvm/ADT/DenseSet.h @@ -0,0 +1,104 @@ +//===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSESET_H +#define LLVM_ADT_DENSESET_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +/// DenseSet - This implements a dense probed hash-table based set. +/// +/// FIXME: This is currently implemented directly in terms of DenseMap, this +/// should be optimized later if there is a need. +template<typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT> > +class DenseSet { + typedef DenseMap<ValueT, char, ValueInfoT> MapTy; + MapTy TheMap; +public: + DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} + explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {} + + bool empty() const { return TheMap.empty(); } + unsigned size() const { return TheMap.size(); } + + void clear() { + TheMap.clear(); + } + + bool count(const ValueT &V) const { + return TheMap.count(V); + } + + void erase(const ValueT &V) { + TheMap.erase(V); + } + + DenseSet &operator=(const DenseSet &RHS) { + TheMap = RHS.TheMap; + return *this; + } + + // Iterators. + + class Iterator { + typename MapTy::iterator I; + public: + Iterator(const typename MapTy::iterator &i) : I(i) {} + + ValueT& operator*() { return I->first; } + ValueT* operator->() { return &I->first; } + + Iterator& operator++() { ++I; return *this; }; + bool operator==(const Iterator& X) const { return I == X.I; } + bool operator!=(const Iterator& X) const { return I != X.I; } + }; + + class ConstIterator { + typename MapTy::const_iterator I; + public: + ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} + + const ValueT& operator*() { return I->first; } + const ValueT* operator->() { return &I->first; } + + ConstIterator& operator++() { ++I; return *this; }; + bool operator==(const ConstIterator& X) const { return I == X.I; } + bool operator!=(const ConstIterator& X) const { return I != X.I; } + }; + + typedef Iterator iterator; + typedef ConstIterator const_iterator; + + iterator begin() { return Iterator(TheMap.begin()); } + iterator end() { return Iterator(TheMap.end()); } + + const_iterator begin() const { return ConstIterator(TheMap.begin()); } + const_iterator end() const { return ConstIterator(TheMap.end()); } + + std::pair<iterator, bool> insert(const ValueT &V) { + return TheMap.insert(std::make_pair(V, 0)); + } + + // Range insertion of values. + template<typename InputIt> + void insert(InputIt I, InputIt E) { + for (; I != E; ++I) + insert(*I); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h new file mode 100644 index 0000000000000..517768f402df9 --- /dev/null +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -0,0 +1,232 @@ +//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build generic depth +// first graph iterator. This file exposes the following functions/types: +// +// df_begin/df_end/df_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// +// idf_begin/idf_end/idf_iterator +// * Depth-first iteration on the 'inverse' graph. +// +// df_ext_begin/df_ext_end/df_ext_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +// idf_ext_begin/idf_ext_end/idf_ext_iterator +// * Depth-first iteration on the 'inverse' graph. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H +#define LLVM_ADT_DEPTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/SmallPtrSet.h" +#include <set> +#include <vector> + +namespace llvm { + +// df_iterator_storage - A private class which is used to figure out where to +// store the visited set. +template<class SetType, bool External> // Non-external set +class df_iterator_storage { +public: + SetType Visited; +}; + +template<class SetType> +class df_iterator_storage<SetType, true> { +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<class GraphT, +class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>, + bool ExtStorage = false, class GT = GraphTraits<GraphT> > +class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>, + public df_iterator_storage<SetType, ExtStorage> { + typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super; + + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is node pointer, second is the 'next child' to visit + std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; +private: + inline df_iterator(NodeType *Node) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node))); + } + inline df_iterator() { /* End is when stack is empty */ } + + inline df_iterator(NodeType *Node, SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + if (!S.count(Node)) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node))); + } + } + inline df_iterator(SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + // End is when stack is empty + } + +public: + typedef typename super::pointer pointer; + typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self; + + // Provide static begin and end methods as our public "constructors" + static inline _Self begin(const GraphT& G) { + return _Self(GT::getEntryNode(G)); + } + static inline _Self end(const GraphT& G) { return _Self(); } + + // Static begin and end methods as our public ctors for external iterators + static inline _Self begin(const GraphT& G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end(const GraphT& G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack.size() == x.VisitStack.size() && + VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.back().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the Node, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + do { + std::pair<NodeType *, ChildItTy> &Top = VisitStack.back(); + NodeType *Node = Top.first; + ChildItTy &It = Top.second; + + while (It != GT::child_end(Node)) { + NodeType *Next = *It++; + if (!this->Visited.count(Next)) { // Has our next sibling been visited? + // No, do it now. + this->Visited.insert(Next); + VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next))); + return *this; + } + } + + // Oops, ran out of successors... go up a level on the stack. + VisitStack.pop_back(); + } while (!VisitStack.empty()); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // nodeVisited - return true if this iterator has already visited the + // specified node. This is public, and will probably be used to iterate over + // nodes that a depth first iteration did not find: ie unreachable nodes. + // + inline bool nodeVisited(NodeType *Node) const { + return this->Visited.count(Node) != 0; + } +}; + + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +df_iterator<T> df_begin(const T& G) { + return df_iterator<T>::begin(G); +} + +template <class T> +df_iterator<T> df_end(const T& G) { + return df_iterator<T>::end(G); +} + +// Provide global definitions of external depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > +struct df_ext_iterator : public df_iterator<T, SetTy, true> { + df_ext_iterator(const df_iterator<T, SetTy, true> &V) + : df_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_begin(const T& G, SetTy &S) { + return df_ext_iterator<T, SetTy>::begin(G, S); +} + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) { + return df_ext_iterator<T, SetTy>::end(G, S); +} + + +// Provide global definitions of inverse depth first iterators... +template <class T, + class SetTy = llvm::SmallPtrSet<typename GraphTraits<T>::NodeType*, 8>, + bool External = false> +struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> { + idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V) + : df_iterator<Inverse<T>, SetTy, External>(V) {} +}; + +template <class T> +idf_iterator<T> idf_begin(const T& G) { + return idf_iterator<T>::begin(Inverse<T>(G)); +} + +template <class T> +idf_iterator<T> idf_end(const T& G){ + return idf_iterator<T>::end(Inverse<T>(G)); +} + +// Provide global definitions of external inverse depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > +struct idf_ext_iterator : public idf_iterator<T, SetTy, true> { + idf_ext_iterator(const idf_iterator<T, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} + idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_begin(const T& G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::begin(Inverse<T>(G), S); +} + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::end(Inverse<T>(G), S); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h new file mode 100644 index 0000000000000..6e00a217bebfe --- /dev/null +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -0,0 +1,279 @@ +//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generic implementation of equivalence classes through the use Tarjan's +// efficient union-find algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EQUIVALENCECLASSES_H +#define LLVM_ADT_EQUIVALENCECLASSES_H + +#include "llvm/ADT/iterator.h" +#include "llvm/Support/DataTypes.h" +#include <set> + +namespace llvm { + +/// EquivalenceClasses - This represents a collection of equivalence classes and +/// supports three efficient operations: insert an element into a class of its +/// own, union two classes, and find the class for a given element. In +/// addition to these modification methods, it is possible to iterate over all +/// of the equivalence classes and all of the elements in a class. +/// +/// This implementation is an efficient implementation that only stores one copy +/// of the element being indexed per entry in the set, and allows any arbitrary +/// type to be indexed (as long as it can be ordered with operator<). +/// +/// Here is a simple example using integers: +/// +/// EquivalenceClasses<int> EC; +/// EC.unionSets(1, 2); // insert 1, 2 into the same set +/// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets +/// EC.unionSets(5, 1); // merge the set for 1 with 5's set. +/// +/// for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end(); +/// I != E; ++I) { // Iterate over all of the equivalence sets. +/// if (!I->isLeader()) continue; // Ignore non-leader sets. +/// for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I); +/// MI != EC.member_end(); ++MI) // Loop over members in this set. +/// cerr << *MI << " "; // Print member. +/// cerr << "\n"; // Finish set. +/// } +/// +/// This example prints: +/// 4 +/// 5 1 2 +/// +template <class ElemTy> +class EquivalenceClasses { + /// ECValue - The EquivalenceClasses data structure is just a set of these. + /// Each of these represents a relation for a value. First it stores the + /// value itself, which provides the ordering that the set queries. Next, it + /// provides a "next pointer", which is used to enumerate all of the elements + /// in the unioned set. Finally, it defines either a "end of list pointer" or + /// "leader pointer" depending on whether the value itself is a leader. A + /// "leader pointer" points to the node that is the leader for this element, + /// if the node is not a leader. A "end of list pointer" points to the last + /// node in the list of members of this list. Whether or not a node is a + /// leader is determined by a bit stolen from one of the pointers. + class ECValue { + 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) + : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {} + + const ECValue *getLeader() const { + if (isLeader()) return this; + if (Leader->isLeader()) return Leader; + // 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; + } + + void setNext(const ECValue *NewNext) const { + assert(getNext() == 0 && "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) { + // Only support copying of singleton nodes. + assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!"); + } + + bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } + + bool isLeader() const { return (intptr_t)Next & 1; } + const ElemTy &getData() const { return Data; } + + const ECValue *getNext() const { + return (ECValue*)((intptr_t)Next & ~(intptr_t)1); + } + + template<typename T> + bool operator<(const T &Val) const { return Data < Val; } + }; + + /// TheMapping - This implicitly provides a mapping from ElemTy values to the + /// ECValues, it just keeps the key as part of the value. + std::set<ECValue> TheMapping; + +public: + EquivalenceClasses() {} + EquivalenceClasses(const EquivalenceClasses &RHS) { + operator=(RHS); + } + + const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) { + TheMapping.clear(); + for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) + if (I->isLeader()) { + member_iterator MI = RHS.member_begin(I); + member_iterator LeaderIt = member_begin(insert(*MI)); + for (++MI; MI != member_end(); ++MI) + unionSets(LeaderIt, member_begin(insert(*MI))); + } + return *this; + } + + //===--------------------------------------------------------------------===// + // Inspection methods + // + + /// iterator* - Provides a way to iterate over all values in the set. + typedef typename std::set<ECValue>::const_iterator iterator; + iterator begin() const { return TheMapping.begin(); } + iterator end() const { return TheMapping.end(); } + + bool empty() const { return TheMapping.empty(); } + + /// member_* Iterate over the members of an equivalence class. + /// + class member_iterator; + member_iterator member_begin(iterator I) const { + // Only leaders provide anything to iterate over. + return member_iterator(I->isLeader() ? &*I : 0); + } + member_iterator member_end() const { + return member_iterator(0); + } + + /// findValue - Return an iterator to the specified value. If it does not + /// exist, end() is returned. + iterator findValue(const ElemTy &V) const { + return TheMapping.find(V); + } + + /// getLeaderValue - Return the leader for the specified value that is in the + /// set. It is an error to call this method for a value that is not yet in + /// the set. For that, call getOrInsertLeaderValue(V). + const ElemTy &getLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(V); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getOrInsertLeaderValue - Return the leader for the specified value that is + /// in the set. If the member is not in the set, it is inserted, then + /// returned. + const ElemTy &getOrInsertLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(insert(V)); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getNumClasses - Return the number of equivalence classes in this set. + /// Note that this is a linear time operation. + unsigned getNumClasses() const { + unsigned NC = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->isLeader()) ++NC; + return NC; + } + + + //===--------------------------------------------------------------------===// + // Mutation methods + + /// insert - Insert a new value into the union/find set, ignoring the request + /// if the value already exists. + iterator insert(const ElemTy &Data) { + return TheMapping.insert(Data).first; + } + + /// findLeader - Given a value in the set, return a member iterator for the + /// equivalence class it is in. This does the path-compression part that + /// makes union-find "union findy". This returns an end iterator if the value + /// is not in the equivalence class. + /// + member_iterator findLeader(iterator I) const { + if (I == TheMapping.end()) return member_end(); + return member_iterator(I->getLeader()); + } + member_iterator findLeader(const ElemTy &V) const { + 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) { + iterator V1I = insert(V1), V2I = insert(V2); + return unionSets(findLeader(V1I), findLeader(V2I)); + } + member_iterator unionSets(member_iterator L1, member_iterator L2) { + assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!"); + if (L1 == L2) return L1; // Unifying the same two sets, noop. + + // Otherwise, this is a real union operation. Set the end of the L1 list to + // point to the L2 leader node. + const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node; + L1LV.getEndOfList()->setNext(&L2LV); + + // Update L1LV's end of list pointer. + L1LV.Leader = L2LV.getEndOfList(); + + // Clear L2's leader flag: + L2LV.Next = L2LV.getNext(); + + // L2's leader is now L1. + L2LV.Leader = &L1LV; + return L1; + } + + class member_iterator : public forward_iterator<ElemTy, ptrdiff_t> { + typedef forward_iterator<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(const ECValue *N) : Node(N) {} + member_iterator(const member_iterator &I) : Node(I.Node) {} + + reference operator*() const { + assert(Node != 0 && "Dereferencing end()!"); + return Node->getData(); + } + reference operator->() const { return operator*(); } + + member_iterator &operator++() { + assert(Node != 0 && "++'d off the end of the list!"); + Node = Node->getNext(); + return *this; + } + + member_iterator operator++(int) { // postincrement operators. + member_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const member_iterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const member_iterator &RHS) const { + return Node != RHS.Node; + } + }; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h new file mode 100644 index 0000000000000..e31e112d0e61e --- /dev/null +++ b/include/llvm/ADT/FoldingSet.h @@ -0,0 +1,461 @@ +//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include <string> +#include <iterator> + +namespace llvm { + class APFloat; + class APInt; + +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplify node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet<MyNode> MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M with be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new +/// node with FindNodeOrInsertPos; +/// +/// InsertNode(N, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = RemoveNode(N); +/// +/// The result indicates whether the node existed in the folding set. + +class FoldingSetNodeID; + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetImpl { +protected: + /// Buckets - Array of bucket chains. + /// + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + +public: + explicit FoldingSetImpl(unsigned Log2InitSize = 6); + virtual ~FoldingSetImpl(); + + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + /// + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; + + public: + + Node() : NextInFoldingSetBucket(0) {} + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// clear - Remove all nodes from the folding set. + void clear(); + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); + + /// size - Returns the number of nodes in the folding set. + unsigned size() const { return NumNodes; } + + /// empty - Returns true if there are no nodes in the folding set. + bool empty() const { return NumNodes == 0; } + +private: + + /// GrowHashTable - Double the size of the hash table and rehash everything. + /// + void GrowHashTable(); + +protected: + + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(FoldingSetNodeID &ID, Node *N) const = 0; +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetTrait - This trait class is used to define behavior of how +/// to "profile" (in the FoldingSet parlance) an object of a given type. +/// The default behavior is to invoke a 'Profile' method on an object, but +/// through template specialization the behavior can be tailored for specific +/// types. Combined with the FoldingSetNodeWrapper classs, one can add objects +/// to FoldingSets that were not originally designed to have that behavior. +/// +template<typename T> struct FoldingSetTrait { + static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);} + static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); } +}; + +//===--------------------------------------------------------------------===// +/// FoldingSetNodeID - This class is used to gather all the unique data bits of +/// a node. When all the bits are gathered this class is used to produce a +/// hash value for the node. +/// +class FoldingSetNodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector<unsigned, 32> Bits; + +public: + FoldingSetNodeID() {} + + /// getRawData - Return the ith entry in the Bits data. + /// + unsigned getRawData(unsigned i) const { + return Bits[i]; + } + + /// Add* - Add various data types to Bit data. + /// + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(long I); + void AddInteger(unsigned long I); + void AddInteger(long long I); + void AddInteger(unsigned long long I); + void AddBoolean(bool B) { AddInteger(B ? 1U : 0U); } + void AddString(const char* String, const char* End); + void AddString(const std::string &String); + void AddString(const char* String); + + template <typename T> + inline void Add(const T& x) { FoldingSetTrait<T>::Profile(x, *this); } + + /// clear - Clear the accumulated profile, allowing this FoldingSetNodeID + /// object to be used to compute a new profile. + inline void clear() { Bits.clear(); } + + /// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used + /// to lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + /// + bool operator==(const FoldingSetNodeID &RHS) const; +}; + +// Convenience type to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +template<class T> class FoldingSetIterator; +template<class T> class FoldingSetBucketIterator; + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +template<class T> class FoldingSet : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(FoldingSetNodeID &ID, Node *N) const { + T *TN = static_cast<T *>(N); + FoldingSetTrait<T>::Profile(*TN,ID); + } + +public: + explicit FoldingSet(unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize) + {} + + typedef FoldingSetIterator<T> iterator; + iterator begin() { return iterator(Buckets); } + iterator end() { return iterator(Buckets+NumBuckets); } + + typedef FoldingSetIterator<const T> const_iterator; + const_iterator begin() const { return const_iterator(Buckets); } + const_iterator end() const { return const_iterator(Buckets+NumBuckets); } + + typedef FoldingSetBucketIterator<T> bucket_iterator; + + bucket_iterator bucket_begin(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1))); + } + + bucket_iterator bucket_end(unsigned hash) { + return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true); + } + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetIteratorImpl - This is the common iterator support shared by all +/// folding sets, which knows how to walk the folding set hash table. +class FoldingSetIteratorImpl { +protected: + FoldingSetNode *NodePtr; + FoldingSetIteratorImpl(void **Bucket); + void advance(); + +public: + bool operator==(const FoldingSetIteratorImpl &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const FoldingSetIteratorImpl &RHS) const { + return NodePtr != RHS.NodePtr; + } +}; + + +template<class T> +class FoldingSetIterator : public FoldingSetIteratorImpl { +public: + explicit FoldingSetIterator(void **Bucket) : FoldingSetIteratorImpl(Bucket) {} + + T &operator*() const { + return *static_cast<T*>(NodePtr); + } + + T *operator->() const { + return static_cast<T*>(NodePtr); + } + + inline FoldingSetIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetIterator operator++(int) { // Postincrement + FoldingSetIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support +/// shared by all folding sets, which knows how to walk a particular bucket +/// of a folding set hash table. + +class FoldingSetBucketIteratorImpl { +protected: + void *Ptr; + + explicit FoldingSetBucketIteratorImpl(void **Bucket); + + FoldingSetBucketIteratorImpl(void **Bucket, bool) + : Ptr(Bucket) {} + + void advance() { + void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket(); + uintptr_t x = reinterpret_cast<uintptr_t>(Probe) & ~0x1; + Ptr = reinterpret_cast<void*>(x); + } + +public: + bool operator==(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const FoldingSetBucketIteratorImpl &RHS) const { + return Ptr != RHS.Ptr; + } +}; + + +template<class T> +class FoldingSetBucketIterator : public FoldingSetBucketIteratorImpl { +public: + explicit FoldingSetBucketIterator(void **Bucket) : + FoldingSetBucketIteratorImpl(Bucket) {} + + FoldingSetBucketIterator(void **Bucket, bool) : + FoldingSetBucketIteratorImpl(Bucket, true) {} + + T& operator*() const { return *static_cast<T*>(Ptr); } + T* operator->() const { return static_cast<T*>(Ptr); } + + inline FoldingSetBucketIterator& operator++() { // Preincrement + advance(); + return *this; + } + FoldingSetBucketIterator operator++(int) { // Postincrement + FoldingSetBucketIterator tmp = *this; ++*this; return tmp; + } +}; + +//===----------------------------------------------------------------------===// +/// FoldingSetNodeWrapper - This template class is used to "wrap" arbitrary +/// types in an enclosing object so that they can be inserted into FoldingSets. +template <typename T> +class FoldingSetNodeWrapper : public FoldingSetNode { + T data; +public: + explicit FoldingSetNodeWrapper(const T& x) : data(x) {} + virtual ~FoldingSetNodeWrapper() {} + + template<typename A1> + explicit FoldingSetNodeWrapper(const A1& a1) + : data(a1) {} + + template <typename A1, typename A2> + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2) + : data(a1,a2) {} + + template <typename A1, typename A2, typename A3> + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3) + : data(a1,a2,a3) {} + + template <typename A1, typename A2, typename A3, typename A4> + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) + : data(a1,a2,a3,a4) {} + + template <typename A1, typename A2, typename A3, typename A4, typename A5> + explicit FoldingSetNodeWrapper(const A1& a1, const A2& a2, const A3& a3, + const A4& a4, const A5& a5) + : data(a1,a2,a3,a4,a5) {} + + + void Profile(FoldingSetNodeID& ID) { FoldingSetTrait<T>::Profile(data, ID); } + + T& getValue() { return data; } + const T& getValue() const { return data; } + + operator T&() { return data; } + operator const T&() const { return data; } +}; + +//===----------------------------------------------------------------------===// +// Partial specializations of FoldingSetTrait. + +template<typename T> struct FoldingSetTrait<T*> { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } + static inline void Profile(T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +template<typename T> struct FoldingSetTrait<const T*> { + static inline void Profile(const T* X, FoldingSetNodeID& ID) { + ID.AddPointer(X); + } +}; + +} // End of namespace llvm. + +#endif diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h new file mode 100644 index 0000000000000..2d103cf83eb83 --- /dev/null +++ b/include/llvm/ADT/GraphTraits.h @@ -0,0 +1,103 @@ +//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the little GraphTraits<X> template class that should be +// specialized by classes that want to be iteratable by generic graph iterators. +// +// This file also defines the marker class Inverse that is used to iterate over +// graphs in a graph defined, inverse ordering... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_GRAPHTRAITS_H +#define LLVM_ADT_GRAPHTRAITS_H + +namespace llvm { + +// GraphTraits - This class should be specialized by different graph types... +// which is why the default version is empty. +// +template<class GraphType> +struct GraphTraits { + // Elements to provide: + + // typedef NodeType - Type of Node in the graph + // typedef ChildIteratorType - Type used to iterate over children in graph + + // static NodeType *getEntryNode(GraphType *) + // Return the entry node of the graph + + // static ChildIteratorType child_begin(NodeType *) + // static ChildIteratorType child_end (NodeType *) + // Return iterators that point to the beginning and ending of the child + // node list for the specified node. + // + + + // typedef ...iterator nodes_iterator; + // 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 + + + // If anyone tries to use this class without having an appropriate + // specialization, make an error. If you get this error, it's because you + // need to include the appropriate specialization of GraphTraits<> for your + // graph, or you need to define it for a new graph type. Either that or + // your argument to XXX_begin(...) is unknown or needs to have the proper .h + // file #include'd. + // + typedef typename GraphType::UnknownGraphTypeError NodeType; +}; + + +// Inverse - This class is used as a little marker class to tell the graph +// iterator to iterate over the graph in a graph defined "Inverse" ordering. +// Not all graphs define an inverse ordering, and if they do, it depends on +// the graph exactly what that is. Here's an example of usage with the +// df_iterator: +// +// idf_iterator<Method*> I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +// Which is equivalent to: +// df_iterator<Inverse<Method*> > I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +template <class GraphType> +struct Inverse { + const GraphType &Graph; + + inline Inverse(const GraphType &G) : Graph(G) {} +}; + +// Provide a partial specialization of GraphTraits so that the inverse of an +// inverse falls back to the original graph. +template<class T> +struct GraphTraits<Inverse<Inverse<T> > > { + typedef typename GraphTraits<T>::NodeType NodeType; + typedef typename GraphTraits<T>::ChildIteratorType ChildIteratorType; + + static NodeType *getEntryNode(Inverse<Inverse<T> > *G) { + return GraphTraits<T>::getEntryNode(G->Graph.Graph); + } + + static ChildIteratorType child_begin(NodeType* N) { + return GraphTraits<T>::child_begin(N); + } + + static ChildIteratorType child_end(NodeType* N) { + return GraphTraits<T>::child_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/HashExtras.h b/include/llvm/ADT/HashExtras.h new file mode 100644 index 0000000000000..20c4fd3058a28 --- /dev/null +++ b/include/llvm/ADT/HashExtras.h @@ -0,0 +1,40 @@ +//===-- llvm/ADT/HashExtras.h - Useful functions for STL hash ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL Hashed containers. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASHEXTRAS_H +#define LLVM_ADT_HASHEXTRAS_H + +#include <string> + +// Cannot specialize hash template from outside of the std namespace. +namespace HASH_NAMESPACE { + +// Provide a hash function for arbitrary pointers... +template <class T> struct hash<T *> { + inline size_t operator()(const T *Val) const { + return reinterpret_cast<size_t>(Val); + } +}; + +template <> struct hash<std::string> { + size_t operator()(std::string const &str) const { + return hash<char const *>()(str.c_str()); + } +}; + +} // End namespace std + +#endif diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h new file mode 100644 index 0000000000000..a7f5819fa510b --- /dev/null +++ b/include/llvm/ADT/ImmutableList.h @@ -0,0 +1,219 @@ +//==--- ImmutableList.h - Immutable (functional) list interface --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableList class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMLIST_H +#define LLVM_ADT_IMLIST_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { + +template <typename T> class ImmutableListFactory; + +template <typename T> +class ImmutableListImpl : public FoldingSetNode { + T Head; + const ImmutableListImpl* Tail; + + ImmutableListImpl(const T& head, const ImmutableListImpl* tail = 0) + : Head(head), Tail(tail) {} + + friend class ImmutableListFactory<T>; + + // Do not implement. + void operator=(const ImmutableListImpl&); + ImmutableListImpl(const ImmutableListImpl&); + +public: + const T& getHead() const { return Head; } + const ImmutableListImpl* getTail() const { return Tail; } + + static inline void Profile(FoldingSetNodeID& ID, const T& H, + const ImmutableListImpl* L){ + ID.AddPointer(L); + ID.Add(H); + } + + void Profile(FoldingSetNodeID& ID) { + Profile(ID, Head, Tail); + } +}; + +/// ImmutableList - This class represents an immutable (functional) list. +/// It is implemented as a smart pointer (wraps ImmutableListImpl), so it +/// it is intended to always be copied by value as if it were a pointer. +/// This interface matches ImmutableSet and ImmutableMap. ImmutableList +/// objects should almost never be created directly, and instead should +/// be created by ImmutableListFactory objects that manage the lifetime +/// of a group of lists. When the factory object is reclaimed, all lists +/// created by that factory are released as well. +template <typename T> +class ImmutableList { +public: + typedef T value_type; + typedef ImmutableListFactory<T> Factory; + +private: + const ImmutableListImpl<T>* X; + +public: + // This constructor should normally only be called by ImmutableListFactory<T>. + // There may be cases, however, when one needs to extract the internal pointer + // and reconstruct a list object from that pointer. + ImmutableList(const ImmutableListImpl<T>* x = 0) : X(x) {} + + const ImmutableListImpl<T>* getInternalPointer() const { + return X; + } + + class iterator { + const ImmutableListImpl<T>* L; + public: + iterator() : L(0) {} + 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; } + }; + + /// begin - Returns an iterator referring to the head of the list, or + /// an iterator denoting the end of the list if the list is empty. + iterator begin() const { return iterator(X); } + + /// end - Returns an iterator denoting the end of the list. This iterator + /// does not refer to a valid list element. + iterator end() const { return iterator(); } + + /// isEmpty - Returns true if the list is empty. + bool isEmpty() const { return !X; } + + /// isEqual - Returns true if two lists are equal. Because all lists created + /// from the same ImmutableListFactory are uniqued, this has O(1) complexity + /// because it the contents of the list do not need to be compared. Note + /// that you should only compare two lists created from the same + /// ImmutableListFactory. + bool isEqual(const ImmutableList& L) const { return X == L.X; } + + bool operator==(const ImmutableList& L) const { return isEqual(L); } + + /// getHead - Returns the head of the list. + const T& getHead() { + assert (!isEmpty() && "Cannot get the head of an empty list."); + return X->getHead(); + } + + /// getTail - Returns the tail of the list, which is another (possibly empty) + /// ImmutableList. + ImmutableList getTail() { + return X ? X->getTail() : 0; + } + + void Profile(FoldingSetNodeID& ID) const { + ID.AddPointer(X); + } +}; + +template <typename T> +class ImmutableListFactory { + typedef ImmutableListImpl<T> ListTy; + typedef FoldingSet<ListTy> CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1); + } + +public: + ImmutableListFactory() + : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {} + + ImmutableListFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {} + + ~ImmutableListFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + ImmutableList<T> Concat(const T& Head, ImmutableList<T> Tail) { + // Profile the new list to see if it already exists in our cache. + FoldingSetNodeID ID; + void* InsertPos; + + const ListTy* TailImpl = Tail.getInternalPointer(); + ListTy::Profile(ID, Head, TailImpl); + ListTy* L = Cache.FindNodeOrInsertPos(ID, InsertPos); + + if (!L) { + // The list does not exist in our cache. Create it. + BumpPtrAllocator& A = getAllocator(); + L = (ListTy*) A.Allocate<ListTy>(); + new (L) ListTy(Head, TailImpl); + + // Insert the new list into the cache. + Cache.InsertNode(L, InsertPos); + } + + return L; + } + + ImmutableList<T> Add(const T& D, ImmutableList<T> L) { + return Concat(D, L); + } + + ImmutableList<T> GetEmptyList() const { + return ImmutableList<T>(0); + } + + ImmutableList<T> Create(const T& X) { + return Concat(X, GetEmptyList()); + } +}; + +//===----------------------------------------------------------------------===// +// Partially-specialized Traits. +//===----------------------------------------------------------------------===// + +template<typename T> struct DenseMapInfo; +template<typename T> struct DenseMapInfo<ImmutableList<T> > { + static inline ImmutableList<T> getEmptyKey() { + return reinterpret_cast<ImmutableListImpl<T>*>(-1); + } + static inline ImmutableList<T> getTombstoneKey() { + return reinterpret_cast<ImmutableListImpl<T>*>(-2); + } + static unsigned getHashValue(ImmutableList<T> X) { + uintptr_t PtrVal = reinterpret_cast<uintptr_t>(X.getInternalPointer()); + return (unsigned((uintptr_t)PtrVal) >> 4) ^ + (unsigned((uintptr_t)PtrVal) >> 9); + } + static bool isEqual(ImmutableList<T> X1, ImmutableList<T> X2) { + return X1 == X2; + } + static bool isPod() { return true; } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h new file mode 100644 index 0000000000000..52708bc8a1087 --- /dev/null +++ b/include/llvm/ADT/ImmutableMap.h @@ -0,0 +1,230 @@ +//===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImmutableMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMMAP_H +#define LLVM_ADT_IMMAP_H + +#include "llvm/ADT/ImmutableSet.h" + +namespace llvm { + +/// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first +/// and second elements in a pair are used to generate profile information, +/// only the first element (the key) is used by isEqual and isLess. +template <typename T, typename S> +struct ImutKeyValueInfo { + typedef const std::pair<T,S> value_type; + typedef const value_type& value_type_ref; + typedef const T key_type; + typedef const T& key_type_ref; + typedef const S data_type; + typedef const S& data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref V) { + return V.first; + } + + static inline data_type_ref DataOfValue(value_type_ref V) { + return V.second; + } + + static inline bool isEqual(key_type_ref L, key_type_ref R) { + return ImutContainerInfo<T>::isEqual(L,R); + } + static inline bool isLess(key_type_ref L, key_type_ref R) { + return ImutContainerInfo<T>::isLess(L,R); + } + + static inline bool isDataEqual(data_type_ref L, data_type_ref R) { + return ImutContainerInfo<S>::isEqual(L,R); + } + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref V) { + ImutContainerInfo<T>::Profile(ID, V.first); + ImutContainerInfo<S>::Profile(ID, V.second); + } +}; + + +template <typename KeyT, typename ValT, + typename ValInfo = ImutKeyValueInfo<KeyT,ValT> > +class ImmutableMap { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef typename ValInfo::key_type key_type; + typedef typename ValInfo::key_type_ref key_type_ref; + typedef typename ValInfo::data_type data_type; + typedef typename ValInfo::data_type_ref data_type_ref; + typedef ImutAVLTree<ValInfo> TreeTy; + +private: + TreeTy* Root; + +public: + /// Constructs a map from a pointer to a tree root. In general one + /// should use a Factory object to create maps instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableMap(const TreeTy* R) : Root(const_cast<TreeTy*>(R)) {} + + class Factory { + typename TreeTy::Factory F; + + public: + Factory() {} + + Factory(BumpPtrAllocator& Alloc) + : F(Alloc) {} + + ImmutableMap GetEmptyMap() { return ImmutableMap(F.GetEmptyTree()); } + + ImmutableMap Add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + return ImmutableMap(F.Add(Old.Root, + std::make_pair<key_type,data_type>(K,D))); + } + + ImmutableMap Remove(ImmutableMap Old, key_type_ref K) { + return ImmutableMap(F.Remove(Old.Root,K)); + } + + private: + Factory(const Factory& RHS) {}; + void operator=(const Factory& RHS) {}; + }; + + friend class Factory; + + bool contains(key_type_ref K) const { + return Root ? Root->contains(K) : false; + } + + + bool operator==(ImmutableMap RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(ImmutableMap RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy* getRoot() const { return Root; } + + bool isEmpty() const { return !Root; } + + //===--------------------------------------------------===// + // Foreach - A limited form of map iteration. + //===--------------------------------------------------===// + +private: + template <typename Callback> + struct CBWrapper { + Callback C; + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + + template <typename Callback> + struct CBWrapperRef { + Callback &C; + CBWrapperRef(Callback& c) : C(c) {} + + void operator()(value_type_ref V) { C(V.first,V.second); } + }; + +public: + template <typename Callback> + void foreach(Callback& C) { + if (Root) { + CBWrapperRef<Callback> CB(C); + Root->foreach(CB); + } + } + + template <typename Callback> + void foreach() { + if (Root) { + CBWrapper<Callback> CB; + Root->foreach(CB); + } + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + + iterator() {} + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableMap; + + public: + value_type_ref operator*() const { return itr->getValue(); } + value_type* operator->() const { return &itr->getValue(); } + + key_type_ref getKey() const { return itr->getValue().first; } + data_type_ref getData() const { return itr->getValue().second; } + + + iterator& operator++() { ++itr; return *this; } + iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + iterator& operator--() { --itr; return *this; } + iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + data_type* lookup(key_type_ref K) const { + if (Root) { + TreeTy* T = Root->find(K); + if (T) return &T->getValue().second; + } + + return 0; + } + + /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for + /// which key is the highest in the ordering of keys in the map. This + /// method returns NULL if the map is empty. + value_type* getMaxElement() const { + return Root ? &(Root->getMaxElement()->getValue()) : 0; + } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) { + ID.AddPointer(M.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h new file mode 100644 index 0000000000000..be274dbe6758c --- /dev/null +++ b/include/llvm/ADT/ImmutableSet.h @@ -0,0 +1,1070 @@ +//===--- ImmutableSet.h - Immutable (functional) set interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ImutAVLTree and ImmutableSet classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_IMSET_H +#define LLVM_ADT_IMSET_H + +#include "llvm/Support/Allocator.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <functional> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Definition. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo> class ImutAVLFactory; +template <typename ImutInfo> class ImutAVLTreeInOrderIterator; +template <typename ImutInfo> class ImutAVLTreeGenericIterator; + +template <typename ImutInfo > +class ImutAVLTree : public FoldingSetNode { +public: + typedef typename ImutInfo::key_type_ref key_type_ref; + typedef typename ImutInfo::value_type value_type; + typedef typename ImutInfo::value_type_ref value_type_ref; + + typedef ImutAVLFactory<ImutInfo> Factory; + friend class ImutAVLFactory<ImutInfo>; + + friend class ImutAVLTreeGenericIterator<ImutInfo>; + friend class FoldingSet<ImutAVLTree>; + + typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator; + + //===----------------------------------------------------===// + // Public Interface. + //===----------------------------------------------------===// + + /// getLeft - Returns a pointer to the left subtree. This value + /// is NULL if there is no left subtree. + ImutAVLTree* getLeft() const { + assert (!isMutable() && "Node is incorrectly marked mutable."); + + return reinterpret_cast<ImutAVLTree*>(Left); + } + + /// getRight - Returns a pointer to the right subtree. This value is + /// NULL if there is no right subtree. + ImutAVLTree* getRight() const { return Right; } + + /// getHeight - Returns the height of the tree. A tree with no subtrees + /// has a height of 1. + unsigned getHeight() const { return Height; } + + /// getValue - Returns the data value associated with the tree node. + const value_type& getValue() const { return Value; } + + /// find - Finds the subtree associated with the specified key value. + /// This method returns NULL if no matching subtree is found. + ImutAVLTree* find(key_type_ref K) { + ImutAVLTree *T = this; + + while (T) { + key_type_ref CurrentKey = ImutInfo::KeyOfValue(T->getValue()); + + if (ImutInfo::isEqual(K,CurrentKey)) + return T; + else if (ImutInfo::isLess(K,CurrentKey)) + T = T->getLeft(); + else + T = T->getRight(); + } + + return NULL; + } + + /// getMaxElement - Find the subtree associated with the highest ranged + /// key value. + ImutAVLTree* getMaxElement() { + ImutAVLTree *T = this; + ImutAVLTree *Right = T->getRight(); + while (Right) { T = Right; Right = T->getRight(); } + return T; + } + + /// size - Returns the number of nodes in the tree, which includes + /// both leaves and non-leaf nodes. + unsigned size() const { + unsigned n = 1; + + if (const ImutAVLTree* L = getLeft()) n += L->size(); + if (const ImutAVLTree* R = getRight()) n += R->size(); + + return n; + } + + /// begin - Returns an iterator that iterates over the nodes of the tree + /// in an inorder traversal. The returned iterator thus refers to the + /// the tree node with the minimum data element. + iterator begin() const { return iterator(this); } + + /// end - Returns an iterator for the tree that denotes the end of an + /// inorder traversal. + iterator end() const { return iterator(); } + + bool ElementEqual(value_type_ref V) const { + // Compare the keys. + if (!ImutInfo::isEqual(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(V))) + return false; + + // Also compare the data values. + if (!ImutInfo::isDataEqual(ImutInfo::DataOfValue(getValue()), + ImutInfo::DataOfValue(V))) + return false; + + return true; + } + + bool ElementEqual(const ImutAVLTree* RHS) const { + return ElementEqual(RHS->getValue()); + } + + /// isEqual - Compares two trees for structural equality and returns true + /// if they are equal. This worst case performance of this operation is + // linear in the sizes of the trees. + bool isEqual(const ImutAVLTree& RHS) const { + if (&RHS == this) + return true; + + iterator LItr = begin(), LEnd = end(); + iterator RItr = RHS.begin(), REnd = RHS.end(); + + while (LItr != LEnd && RItr != REnd) { + if (*LItr == *RItr) { + LItr.SkipSubTree(); + RItr.SkipSubTree(); + continue; + } + + if (!LItr->ElementEqual(*RItr)) + return false; + + ++LItr; + ++RItr; + } + + return LItr == LEnd && RItr == REnd; + } + + /// isNotEqual - Compares two trees for structural inequality. Performance + /// is the same is isEqual. + bool isNotEqual(const ImutAVLTree& RHS) const { return !isEqual(RHS); } + + /// contains - Returns true if this tree contains a subtree (node) that + /// has an data element that matches the specified key. Complexity + /// is logarithmic in the size of the tree. + bool contains(const key_type_ref K) { return (bool) find(K); } + + /// foreach - A member template the accepts invokes operator() on a functor + /// object (specifed by Callback) for every node/subtree in the tree. + /// Nodes are visited using an inorder traversal. + template <typename Callback> + void foreach(Callback& C) { + if (ImutAVLTree* L = getLeft()) L->foreach(C); + + C(Value); + + if (ImutAVLTree* R = getRight()) R->foreach(C); + } + + /// verify - A utility method that checks that the balancing and + /// ordering invariants of the tree are satisifed. It is a recursive + /// method that returns the height of the tree, which is then consumed + /// by the enclosing verify call. External callers should ignore the + /// return value. An invalid tree will cause an assertion to fire in + /// a debug build. + unsigned verify() const { + unsigned HL = getLeft() ? getLeft()->verify() : 0; + unsigned HR = getRight() ? getRight()->verify() : 0; + + assert (getHeight() == ( HL > HR ? HL : HR ) + 1 + && "Height calculation wrong."); + + assert ((HL > HR ? HL-HR : HR-HL) <= 2 + && "Balancing invariant violated."); + + + assert (!getLeft() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getLeft()->getValue()), + ImutInfo::KeyOfValue(getValue())) + && "Value in left child is not less that current value."); + + + assert (!getRight() + || ImutInfo::isLess(ImutInfo::KeyOfValue(getValue()), + ImutInfo::KeyOfValue(getRight()->getValue())) + && "Current value is not less that value of right child."); + + return getHeight(); + } + + /// Profile - Profiling for ImutAVLTree. + void Profile(llvm::FoldingSetNodeID& ID) { + ID.AddInteger(ComputeDigest()); + } + + //===----------------------------------------------------===// + // Internal Values. + //===----------------------------------------------------===// + +private: + uintptr_t Left; + ImutAVLTree* Right; + unsigned Height; + value_type Value; + unsigned Digest; + + //===----------------------------------------------------===// + // Internal methods (node manipulation; used by Factory). + //===----------------------------------------------------===// + +private: + + enum { Mutable = 0x1 }; + + /// ImutAVLTree - Internal constructor that is only called by + /// ImutAVLFactory. + ImutAVLTree(ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) + : Left(reinterpret_cast<uintptr_t>(l) | Mutable), + Right(r), Height(height), Value(v), Digest(0) {} + + + /// isMutable - Returns true if the left and right subtree references + /// (as well as height) can be changed. If this method returns false, + /// the tree is truly immutable. Trees returned from an ImutAVLFactory + /// object should always have this method return true. Further, if this + /// method returns false for an instance of ImutAVLTree, all subtrees + /// will also have this method return false. The converse is not true. + bool isMutable() const { return Left & Mutable; } + + /// getSafeLeft - Returns the pointer to the left tree by always masking + /// out the mutable bit. This is used internally by ImutAVLFactory, + /// as no trees returned to the client should have the mutable flag set. + ImutAVLTree* getSafeLeft() const { + return reinterpret_cast<ImutAVLTree*>(Left & ~Mutable); + } + + //===----------------------------------------------------===// + // Mutating operations. A tree root can be manipulated as + // long as its reference has not "escaped" from internal + // methods of a factory object (see below). When a tree + // pointer is externally viewable by client code, the + // internal "mutable bit" is cleared to mark the tree + // immutable. Note that a tree that still has its mutable + // bit set may have children (subtrees) that are themselves + // immutable. + //===----------------------------------------------------===// + + + /// MarkImmutable - Clears the mutable flag for a tree. After this happens, + /// it is an error to call setLeft(), setRight(), and setHeight(). It + /// is also then safe to call getLeft() instead of getSafeLeft(). + void MarkImmutable() { + assert (isMutable() && "Mutable flag already removed."); + Left &= ~Mutable; + } + + /// setLeft - Changes the reference of the left subtree. Used internally + /// by ImutAVLFactory. + void setLeft(ImutAVLTree* NewLeft) { + assert (isMutable() && + "Only a mutable tree can have its left subtree changed."); + + Left = reinterpret_cast<uintptr_t>(NewLeft) | Mutable; + } + + /// setRight - Changes the reference of the right subtree. Used internally + /// by ImutAVLFactory. + void setRight(ImutAVLTree* NewRight) { + assert (isMutable() && + "Only a mutable tree can have its right subtree changed."); + + Right = NewRight; + } + + /// setHeight - Changes the height of the tree. Used internally by + /// ImutAVLFactory. + void setHeight(unsigned h) { + assert (isMutable() && "Only a mutable tree can have its height changed."); + Height = h; + } + + + static inline + unsigned ComputeDigest(ImutAVLTree* L, ImutAVLTree* R, value_type_ref V) { + unsigned digest = 0; + + if (L) digest += L->ComputeDigest(); + + { // Compute digest of stored data. + FoldingSetNodeID ID; + ImutInfo::Profile(ID,V); + digest += ID.ComputeHash(); + } + + if (R) digest += R->ComputeDigest(); + + return digest; + } + + inline unsigned ComputeDigest() { + if (Digest) return Digest; + + unsigned X = ComputeDigest(getSafeLeft(), getRight(), getValue()); + if (!isMutable()) Digest = X; + + return X; + } +}; + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Factory class. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo > +class ImutAVLFactory { + typedef ImutAVLTree<ImutInfo> TreeTy; + typedef typename TreeTy::value_type_ref value_type_ref; + typedef typename TreeTy::key_type_ref key_type_ref; + + typedef FoldingSet<TreeTy> CacheTy; + + CacheTy Cache; + uintptr_t Allocator; + + bool ownsAllocator() const { + return Allocator & 0x1 ? false : true; + } + + BumpPtrAllocator& getAllocator() const { + return *reinterpret_cast<BumpPtrAllocator*>(Allocator & ~0x1); + } + + //===--------------------------------------------------===// + // Public interface. + //===--------------------------------------------------===// + +public: + ImutAVLFactory() + : Allocator(reinterpret_cast<uintptr_t>(new BumpPtrAllocator())) {} + + ImutAVLFactory(BumpPtrAllocator& Alloc) + : Allocator(reinterpret_cast<uintptr_t>(&Alloc) | 0x1) {} + + ~ImutAVLFactory() { + if (ownsAllocator()) delete &getAllocator(); + } + + TreeTy* Add(TreeTy* T, value_type_ref V) { + T = Add_internal(V,T); + MarkImmutable(T); + return T; + } + + TreeTy* Remove(TreeTy* T, key_type_ref V) { + T = Remove_internal(V,T); + MarkImmutable(T); + return T; + } + + TreeTy* GetEmptyTree() const { return NULL; } + + //===--------------------------------------------------===// + // A bunch of quick helper functions used for reasoning + // about the properties of trees and their children. + // These have succinct names so that the balancing code + // is as terse (and readable) as possible. + //===--------------------------------------------------===// +private: + + bool isEmpty(TreeTy* T) const { return !T; } + unsigned Height(TreeTy* T) const { return T ? T->getHeight() : 0; } + TreeTy* Left(TreeTy* T) const { return T->getSafeLeft(); } + TreeTy* Right(TreeTy* T) const { return T->getRight(); } + value_type_ref Value(TreeTy* T) const { return T->Value; } + + unsigned IncrementHeight(TreeTy* L, TreeTy* R) const { + unsigned hl = Height(L); + unsigned hr = Height(R); + return ( hl > hr ? hl : hr ) + 1; + } + + + static bool CompareTreeWithSection(TreeTy* T, + typename TreeTy::iterator& TI, + typename TreeTy::iterator& TE) { + + typename TreeTy::iterator I = T->begin(), E = T->end(); + + for ( ; I!=E ; ++I, ++TI) + if (TI == TE || !I->ElementEqual(*TI)) + return false; + + return true; + } + + //===--------------------------------------------------===// + // "CreateNode" is used to generate new tree roots that link + // to other trees. The functon may also simply move links + // in an existing root if that root is still marked mutable. + // This is necessary because otherwise our balancing code + // would leak memory as it would create nodes that are + // then discarded later before the finished tree is + // returned to the caller. + //===--------------------------------------------------===// + + TreeTy* CreateNode(TreeTy* L, value_type_ref V, TreeTy* R) { + // Search the FoldingSet bucket for a Tree with the same digest. + FoldingSetNodeID ID; + unsigned digest = TreeTy::ComputeDigest(L, R, V); + ID.AddInteger(digest); + unsigned hash = ID.ComputeHash(); + + typename CacheTy::bucket_iterator I = Cache.bucket_begin(hash); + typename CacheTy::bucket_iterator E = Cache.bucket_end(hash); + + for (; I != E; ++I) { + TreeTy* T = &*I; + + if (T->ComputeDigest() != digest) + continue; + + // We found a collision. Perform a comparison of Contents('T') + // with Contents('L')+'V'+Contents('R'). + + typename TreeTy::iterator TI = T->begin(), TE = T->end(); + + // First compare Contents('L') with the (initial) contents of T. + if (!CompareTreeWithSection(L, TI, TE)) + continue; + + // Now compare the new data element. + if (TI == TE || !TI->ElementEqual(V)) + continue; + + ++TI; + + // Now compare the remainder of 'T' with 'R'. + if (!CompareTreeWithSection(R, TI, TE)) + continue; + + if (TI != TE) // Contents('R') did not match suffix of 'T'. + continue; + + // Trees did match! Return 'T'. + return T; + } + + // No tree with the contents: Contents('L')+'V'+Contents('R'). + // Create it. + + // Allocate the new tree node and insert it into the cache. + BumpPtrAllocator& A = getAllocator(); + TreeTy* T = (TreeTy*) A.Allocate<TreeTy>(); + new (T) TreeTy(L,R,V,IncrementHeight(L,R)); + + // We do not insert 'T' into the FoldingSet here. This is because + // this tree is still mutable and things may get rebalanced. + // Because our digest is associative and based on the contents of + // the set, this should hopefully not cause any strange bugs. + // 'T' is inserted by 'MarkImmutable'. + + return T; + } + + TreeTy* CreateNode(TreeTy* L, TreeTy* OldTree, TreeTy* R) { + assert (!isEmpty(OldTree)); + + if (OldTree->isMutable()) { + OldTree->setLeft(L); + OldTree->setRight(R); + OldTree->setHeight(IncrementHeight(L,R)); + return OldTree; + } + else return CreateNode(L, Value(OldTree), R); + } + + /// Balance - Used by Add_internal and Remove_internal to + /// balance a newly created tree. + TreeTy* Balance(TreeTy* L, value_type_ref V, TreeTy* R) { + + unsigned hl = Height(L); + unsigned hr = Height(R); + + if (hl > hr + 2) { + assert (!isEmpty(L) && + "Left tree cannot be empty to have a height >= 2."); + + TreeTy* LL = Left(L); + TreeTy* LR = Right(L); + + if (Height(LL) >= Height(LR)) + return CreateNode(LL, L, CreateNode(LR,V,R)); + + assert (!isEmpty(LR) && + "LR cannot be empty because it has a height >= 1."); + + TreeTy* LRL = Left(LR); + TreeTy* LRR = Right(LR); + + return CreateNode(CreateNode(LL,L,LRL), LR, CreateNode(LRR,V,R)); + } + else if (hr > hl + 2) { + assert (!isEmpty(R) && + "Right tree cannot be empty to have a height >= 2."); + + TreeTy* RL = Left(R); + TreeTy* RR = Right(R); + + if (Height(RR) >= Height(RL)) + return CreateNode(CreateNode(L,V,RL), R, RR); + + assert (!isEmpty(RL) && + "RL cannot be empty because it has a height >= 1."); + + TreeTy* RLL = Left(RL); + TreeTy* RLR = Right(RL); + + return CreateNode(CreateNode(L,V,RLL), RL, CreateNode(RLR,R,RR)); + } + else + return CreateNode(L,V,R); + } + + /// Add_internal - Creates a new tree that includes the specified + /// data and the data from the original tree. If the original tree + /// already contained the data item, the original tree is returned. + TreeTy* Add_internal(value_type_ref V, TreeTy* T) { + if (isEmpty(T)) + return CreateNode(T, V, T); + + assert (!T->isMutable()); + + key_type_ref K = ImutInfo::KeyOfValue(V); + key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return CreateNode(Left(T), V, Right(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return Balance(Add_internal(V,Left(T)), Value(T), Right(T)); + else + return Balance(Left(T), Value(T), Add_internal(V,Right(T))); + } + + /// Remove_internal - Creates a new tree that includes all the data + /// from the original tree except the specified data. If the + /// specified data did not exist in the original tree, the original + /// tree is returned. + TreeTy* Remove_internal(key_type_ref K, TreeTy* T) { + if (isEmpty(T)) + return T; + + assert (!T->isMutable()); + + key_type_ref KCurrent = ImutInfo::KeyOfValue(Value(T)); + + if (ImutInfo::isEqual(K,KCurrent)) + return CombineLeftRightTrees(Left(T),Right(T)); + else if (ImutInfo::isLess(K,KCurrent)) + return Balance(Remove_internal(K,Left(T)), Value(T), Right(T)); + else + return Balance(Left(T), Value(T), Remove_internal(K,Right(T))); + } + + TreeTy* CombineLeftRightTrees(TreeTy* L, TreeTy* R) { + if (isEmpty(L)) return R; + if (isEmpty(R)) return L; + + TreeTy* OldNode; + TreeTy* NewRight = RemoveMinBinding(R,OldNode); + return Balance(L,Value(OldNode),NewRight); + } + + TreeTy* RemoveMinBinding(TreeTy* T, TreeTy*& NodeRemoved) { + assert (!isEmpty(T)); + + if (isEmpty(Left(T))) { + NodeRemoved = T; + return Right(T); + } + + return Balance(RemoveMinBinding(Left(T),NodeRemoved),Value(T),Right(T)); + } + + /// MarkImmutable - Clears the mutable bits of a root and all of its + /// descendants. + void MarkImmutable(TreeTy* T) { + if (!T || !T->isMutable()) + return; + + T->MarkImmutable(); + MarkImmutable(Left(T)); + MarkImmutable(Right(T)); + + // Now that the node is immutable it can safely be inserted + // into the node cache. + llvm::FoldingSetNodeID ID; + ID.AddInteger(T->ComputeDigest()); + Cache.InsertNode(T, (void*) &*Cache.bucket_end(ID.ComputeHash())); + } +}; + + +//===----------------------------------------------------------------------===// +// Immutable AVL-Tree Iterators. +//===----------------------------------------------------------------------===// + +template <typename ImutInfo> +class ImutAVLTreeGenericIterator { + SmallVector<uintptr_t,20> stack; +public: + enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3, + Flags=0x3 }; + + typedef ImutAVLTree<ImutInfo> TreeTy; + typedef ImutAVLTreeGenericIterator<ImutInfo> _Self; + + inline ImutAVLTreeGenericIterator() {} + inline ImutAVLTreeGenericIterator(const TreeTy* Root) { + if (Root) stack.push_back(reinterpret_cast<uintptr_t>(Root)); + } + + TreeTy* operator*() const { + assert (!stack.empty()); + return reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + } + + uintptr_t getVisitState() { + assert (!stack.empty()); + return stack.back() & Flags; + } + + + bool AtEnd() const { return stack.empty(); } + + bool AtBeginning() const { + return stack.size() == 1 && getVisitState() == VisitedNone; + } + + void SkipToParent() { + assert (!stack.empty()); + stack.pop_back(); + + if (stack.empty()) + return; + + switch (getVisitState()) { + case VisitedNone: + stack.back() |= VisitedLeft; + break; + case VisitedLeft: + stack.back() |= VisitedRight; + break; + default: + assert (false && "Unreachable."); + } + } + + inline bool operator==(const _Self& x) const { + if (stack.size() != x.stack.size()) + return false; + + for (unsigned i = 0 ; i < stack.size(); i++) + if (stack[i] != x.stack[i]) + return false; + + return true; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + _Self& operator++() { + assert (!stack.empty()); + + TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + assert (Current); + + switch (getVisitState()) { + case VisitedNone: + if (TreeTy* L = Current->getSafeLeft()) + stack.push_back(reinterpret_cast<uintptr_t>(L)); + else + stack.back() |= VisitedLeft; + + break; + + case VisitedLeft: + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast<uintptr_t>(R)); + else + stack.back() |= VisitedRight; + + break; + + case VisitedRight: + SkipToParent(); + break; + + default: + assert (false && "Unreachable."); + } + + return *this; + } + + _Self& operator--() { + assert (!stack.empty()); + + TreeTy* Current = reinterpret_cast<TreeTy*>(stack.back() & ~Flags); + assert (Current); + + switch (getVisitState()) { + case VisitedNone: + stack.pop_back(); + break; + + case VisitedLeft: + stack.back() &= ~Flags; // Set state to "VisitedNone." + + if (TreeTy* L = Current->getLeft()) + stack.push_back(reinterpret_cast<uintptr_t>(L) | VisitedRight); + + break; + + case VisitedRight: + stack.back() &= ~Flags; + stack.back() |= VisitedLeft; + + if (TreeTy* R = Current->getRight()) + stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight); + + break; + + default: + assert (false && "Unreachable."); + } + + return *this; + } +}; + +template <typename ImutInfo> +class ImutAVLTreeInOrderIterator { + typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy; + InternalIteratorTy InternalItr; + +public: + typedef ImutAVLTree<ImutInfo> TreeTy; + typedef ImutAVLTreeInOrderIterator<ImutInfo> _Self; + + ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) { + if (Root) operator++(); // Advance to first element. + } + + ImutAVLTreeInOrderIterator() : InternalItr() {} + + inline bool operator==(const _Self& x) const { + return InternalItr == x.InternalItr; + } + + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline TreeTy* operator*() const { return *InternalItr; } + inline TreeTy* operator->() const { return *InternalItr; } + + inline _Self& operator++() { + do ++InternalItr; + while (!InternalItr.AtEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline _Self& operator--() { + do --InternalItr; + while (!InternalItr.AtBeginning() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft); + + return *this; + } + + inline void SkipSubTree() { + InternalItr.SkipToParent(); + + while (!InternalItr.AtEnd() && + InternalItr.getVisitState() != InternalIteratorTy::VisitedLeft) + ++InternalItr; + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes for Profile information. +//===----------------------------------------------------------------------===// + +/// Generic profile template. The default behavior is to invoke the +/// profile method of an object. Specializations for primitive integers +/// and generic handling of pointers is done below. +template <typename T> +struct ImutProfileInfo { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + FoldingSetTrait<T>::Profile(X,ID); + } +}; + +/// Profile traits for integers. +template <typename T> +struct ImutProfileInteger { + typedef const T value_type; + typedef const T& value_type_ref; + + static inline void Profile(FoldingSetNodeID& ID, value_type_ref X) { + ID.AddInteger(X); + } +}; + +#define PROFILE_INTEGER_INFO(X)\ +template<> struct ImutProfileInfo<X> : ImutProfileInteger<X> {}; + +PROFILE_INTEGER_INFO(char) +PROFILE_INTEGER_INFO(unsigned char) +PROFILE_INTEGER_INFO(short) +PROFILE_INTEGER_INFO(unsigned short) +PROFILE_INTEGER_INFO(unsigned) +PROFILE_INTEGER_INFO(signed) +PROFILE_INTEGER_INFO(long) +PROFILE_INTEGER_INFO(unsigned long) +PROFILE_INTEGER_INFO(long long) +PROFILE_INTEGER_INFO(unsigned long long) + +#undef PROFILE_INTEGER_INFO + +/// Generic profile trait for pointer types. We treat pointers as +/// references to unique objects. +template <typename T> +struct ImutProfileInfo<T*> { + typedef const T* value_type; + typedef value_type value_type_ref; + + static inline void Profile(FoldingSetNodeID &ID, value_type_ref X) { + ID.AddPointer(X); + } +}; + +//===----------------------------------------------------------------------===// +// Trait classes that contain element comparison operators and type +// definitions used by ImutAVLTree, ImmutableSet, and ImmutableMap. These +// inherit from the profile traits (ImutProfileInfo) to include operations +// 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. +template <typename T> +struct ImutContainerInfo : public ImutProfileInfo<T> { + typedef typename ImutProfileInfo<T>::value_type value_type; + typedef typename ImutProfileInfo<T>::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return std::equal_to<key_type>()(LHS,RHS); + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return std::less<key_type>()(LHS,RHS); + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +/// ImutContainerInfo - Specialization for pointer values to treat pointers +/// as references to unique objects. Pointers are thus compared by +/// their addresses. +template <typename T> +struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> { + typedef typename ImutProfileInfo<T*>::value_type value_type; + typedef typename ImutProfileInfo<T*>::value_type_ref value_type_ref; + typedef value_type key_type; + typedef value_type_ref key_type_ref; + typedef bool data_type; + typedef bool data_type_ref; + + static inline key_type_ref KeyOfValue(value_type_ref D) { return D; } + static inline data_type_ref DataOfValue(value_type_ref) { return true; } + + static inline bool isEqual(key_type_ref LHS, key_type_ref RHS) { + return LHS == RHS; + } + + static inline bool isLess(key_type_ref LHS, key_type_ref RHS) { + return LHS < RHS; + } + + static inline bool isDataEqual(data_type_ref,data_type_ref) { return true; } +}; + +//===----------------------------------------------------------------------===// +// Immutable Set +//===----------------------------------------------------------------------===// + +template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> > +class ImmutableSet { +public: + typedef typename ValInfo::value_type value_type; + typedef typename ValInfo::value_type_ref value_type_ref; + typedef ImutAVLTree<ValInfo> TreeTy; + +private: + TreeTy* Root; + +public: + /// Constructs a set from a pointer to a tree root. In general one + /// should use a Factory object to create sets instead of directly + /// invoking the constructor, but there are cases where make this + /// constructor public is useful. + explicit ImmutableSet(TreeTy* R) : Root(R) {} + + class Factory { + typename TreeTy::Factory F; + + public: + Factory() {} + + Factory(BumpPtrAllocator& Alloc) + : F(Alloc) {} + + /// GetEmptySet - Returns an immutable set that contains no elements. + ImmutableSet GetEmptySet() { return ImmutableSet(F.GetEmptyTree()); } + + /// Add - Creates a new immutable set that contains all of the values + /// of the original set with the addition of the specified value. If + /// the original set already included the value, then the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet Add(ImmutableSet Old, value_type_ref V) { + return ImmutableSet(F.Add(Old.Root,V)); + } + + /// Remove - Creates a new immutable set that contains all of the values + /// of the original set with the exception of the specified value. If + /// the original set did not contain the value, the original set is + /// returned and no memory is allocated. The time and space complexity + /// of this operation is logarithmic in the size of the original set. + /// The memory allocated to represent the set is released when the + /// factory object that created the set is destroyed. + ImmutableSet Remove(ImmutableSet Old, value_type_ref V) { + return ImmutableSet(F.Remove(Old.Root,V)); + } + + BumpPtrAllocator& getAllocator() { return F.getAllocator(); } + + private: + Factory(const Factory& RHS) {}; + void operator=(const Factory& RHS) {}; + }; + + friend class Factory; + + /// contains - Returns true if the set contains the specified value. + bool contains(const value_type_ref V) const { + return Root ? Root->contains(V) : false; + } + + bool operator==(ImmutableSet RHS) const { + return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root; + } + + bool operator!=(ImmutableSet RHS) const { + return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root; + } + + TreeTy* getRoot() const { return Root; } + + /// isEmpty - Return true if the set contains no elements. + bool isEmpty() const { return !Root; } + + /// isSingleton - Return true if the set contains exactly one element. + /// This method runs in constant time. + bool isSingleton() const { return getHeight() == 1; } + + template <typename Callback> + void foreach(Callback& C) { if (Root) Root->foreach(C); } + + template <typename Callback> + void foreach() { if (Root) { Callback C; Root->foreach(C); } } + + //===--------------------------------------------------===// + // Iterators. + //===--------------------------------------------------===// + + class iterator { + typename TreeTy::iterator itr; + + iterator() {} + iterator(TreeTy* t) : itr(t) {} + friend class ImmutableSet<ValT,ValInfo>; + public: + inline value_type_ref operator*() const { return itr->getValue(); } + inline iterator& operator++() { ++itr; return *this; } + inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; } + inline iterator& operator--() { --itr; return *this; } + inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; } + inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; } + inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; } + inline value_type *operator->() const { return &(operator*()); } + }; + + iterator begin() const { return iterator(Root); } + iterator end() const { return iterator(); } + + //===--------------------------------------------------===// + // Utility methods. + //===--------------------------------------------------===// + + inline unsigned getHeight() const { return Root ? Root->getHeight() : 0; } + + static inline void Profile(FoldingSetNodeID& ID, const ImmutableSet& S) { + ID.AddPointer(S.Root); + } + + inline void Profile(FoldingSetNodeID& ID) const { + return Profile(ID,*this); + } + + //===--------------------------------------------------===// + // For testing. + //===--------------------------------------------------===// + + void verify() const { if (Root) Root->verify(); } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h new file mode 100644 index 0000000000000..ff5d3a139c705 --- /dev/null +++ b/include/llvm/ADT/IndexedMap.h @@ -0,0 +1,75 @@ +//===- llvm/ADT/IndexedMap.h - An index map implementation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an indexed map. The index map template takes two +// types. The first is the mapped type and the second is a functor +// that maps its argument to a size_t. On instantiation a "null" value +// can be provided to be used as a "does not exist" indicator in the +// map. A member function grow() is provided that given the value of +// the maximally indexed key (the argument of the functor) makes sure +// the map has enough space for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INDEXEDMAP_H +#define LLVM_ADT_INDEXEDMAP_H + +#include <cassert> +#include <functional> +#include <vector> + +namespace llvm { + + struct IdentityFunctor : std::unary_function<unsigned, unsigned> { + unsigned operator()(unsigned Index) const { + return Index; + } + }; + + template <typename T, typename ToIndexT = IdentityFunctor> + class IndexedMap { + typedef typename ToIndexT::argument_type IndexT; + typedef std::vector<T> StorageT; + StorageT storage_; + T nullVal_; + ToIndexT toIndex_; + + public: + IndexedMap() : nullVal_(T()) { } + + explicit IndexedMap(const T& val) : nullVal_(val) { } + + typename StorageT::reference operator[](IndexT n) { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + typename StorageT::const_reference operator[](IndexT n) const { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + void clear() { + storage_.clear(); + } + + void grow(IndexT n) { + unsigned NewSize = toIndex_(n) + 1; + if (NewSize > storage_.size()) + storage_.resize(NewSize, nullVal_); + } + + typename StorageT::size_type size() const { + return storage_.size(); + } + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h new file mode 100644 index 0000000000000..37d4ac9d29df5 --- /dev/null +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -0,0 +1,230 @@ +//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- 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 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. +// +// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added +// LLVM-style casting. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INTRUSIVE_REF_CNT_PTR +#define LLVM_ADT_INTRUSIVE_REF_CNT_PTR + +#include <cassert> + +#include "llvm/Support/Casting.h" + +namespace llvm { + + template <class T> + 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 IntrusivePtr "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 Derived> + class RefCountedBase { + unsigned ref_cnt; + + protected: + RefCountedBase() : ref_cnt(0) {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete static_cast<Derived*>(this); + } + + friend class IntrusiveRefCntPtr<Derived>; + }; + +//===----------------------------------------------------------------------===// +/// 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. +//===----------------------------------------------------------------------===// + template <class Derived> + class RefCountedBaseVPTR { + unsigned ref_cnt; + + protected: + RefCountedBaseVPTR() : ref_cnt(0) {} + virtual ~RefCountedBaseVPTR() {} + + void Retain() { ++ref_cnt; } + void Release() { + assert (ref_cnt > 0 && "Reference count is already zero."); + if (--ref_cnt == 0) delete this; + } + + friend class IntrusiveRefCntPtr<Derived>; + }; + +//===----------------------------------------------------------------------===// +/// 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. +/// +/// 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 <typename T> + class IntrusiveRefCntPtr { + T* Obj; + typedef IntrusiveRefCntPtr this_type; + public: + typedef T element_type; + + explicit IntrusiveRefCntPtr() : Obj(0) {} + + explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) { + retain(); + } + + IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) { + retain(); + } + + template <class X> + IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) + : Obj(S.getPtr()) { + retain(); + } + + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr& S) { + replace(S.getPtr()); + return *this; + } + + template <class X> + IntrusiveRefCntPtr& operator=(const IntrusiveRefCntPtr<X>& S) { + replace(S.getPtr()); + return *this; + } + + IntrusiveRefCntPtr& operator=(T * S) { + replace(S); + return *this; + } + + ~IntrusiveRefCntPtr() { release(); } + + T& operator*() const { return *Obj; } + + T* operator->() const { return Obj; } + + T* getPtr() const { return Obj; } + + typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; + operator unspecified_bool_type() const { + return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; + } + + void swap(IntrusiveRefCntPtr& other) { + T* tmp = other.Obj; + other.Obj = Obj; + Obj = tmp; + } + + private: + void retain() { if (Obj) Obj->Retain(); } + void release() { if (Obj) Obj->Release(); } + + void replace(T* S) { + this_type(S).swap(*this); + } + }; + + template<class T, class U> + inline bool operator==(const IntrusiveRefCntPtr<T>& A, + const IntrusiveRefCntPtr<U>& B) + { + return A.getPtr() == B.getPtr(); + } + + template<class T, class U> + inline bool operator!=(const IntrusiveRefCntPtr<T>& A, + const IntrusiveRefCntPtr<U>& B) + { + return A.getPtr() != B.getPtr(); + } + + template<class T, class U> + inline bool operator==(const IntrusiveRefCntPtr<T>& A, + U* B) + { + return A.getPtr() == B; + } + + template<class T, class U> + inline bool operator!=(const IntrusiveRefCntPtr<T>& A, + U* B) + { + return A.getPtr() != B; + } + + template<class T, class U> + inline bool operator==(T* A, + const IntrusiveRefCntPtr<U>& B) + { + return A == B.getPtr(); + } + + template<class T, class U> + inline bool operator!=(T* A, + const IntrusiveRefCntPtr<U>& B) + { + return A != B.getPtr(); + } + +//===----------------------------------------------------------------------===// +// LLVM-style downcasting support for IntrusiveRefCntPtr objects +//===----------------------------------------------------------------------===// + + template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { + return Val.getPtr(); + } + }; + + template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { + typedef T* SimpleType; + static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { + return Val.getPtr(); + } + }; + +} // end namespace llvm + +#endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h new file mode 100644 index 0000000000000..cc53c8c30c121 --- /dev/null +++ b/include/llvm/ADT/OwningPtr.h @@ -0,0 +1,134 @@ +//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 and implements the OwningPtr class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_OWNING_PTR_H +#define LLVM_ADT_OWNING_PTR_H + +#include <cassert> +#include <cstddef> + +namespace llvm { + +/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it +/// guarantees deletion of the object pointed to, either on destruction of the +/// OwningPtr or via an explicit reset(). Once created, ownership of the +/// pointee object can be taken away from OwningPtr by using the take method. +template<class T> +class OwningPtr { + OwningPtr(OwningPtr const &); // DO NOT IMPLEMENT + OwningPtr &operator=(OwningPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningPtr(T *P = 0) : Ptr(P) {} + + ~OwningPtr() { + delete Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator*() const { + assert(Ptr && "Cannot dereference null pointer"); + return *Ptr; + } + + T *operator->() const { return Ptr; } + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template<class T> +inline void swap(OwningPtr<T> &a, OwningPtr<T> &b) { + a.swap(b); +} + +/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same +/// functionality as OwningPtr, except that it works for array types. +template<class T> +class OwningArrayPtr { + OwningArrayPtr(OwningArrayPtr const &); // DO NOT IMPLEMENT + OwningArrayPtr &operator=(OwningArrayPtr const &); // DO NOT IMPLEMENT + T *Ptr; +public: + explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} + + ~OwningArrayPtr() { + delete [] Ptr; + } + + /// reset - Change the current pointee to the specified pointer. Note that + /// calling this with any pointer (including a null pointer) deletes the + /// current pointer. + void reset(T *P = 0) { + if (P == Ptr) return; + T *Tmp = Ptr; + Ptr = P; + delete [] Tmp; + } + + /// take - Reset the owning pointer to null and return its pointer. This does + /// not delete the pointer before returning it. + T *take() { + T *Tmp = Ptr; + Ptr = 0; + return Tmp; + } + + T &operator[](std::ptrdiff_t i) const { + assert(Ptr && "Cannot dereference null pointer"); + return Ptr[i]; + } + + T *get() const { return Ptr; } + operator bool() const { return Ptr != 0; } + bool operator!() const { return Ptr == 0; } + + void swap(OwningArrayPtr &RHS) { + T *Tmp = RHS.Ptr; + RHS.Ptr = Ptr; + Ptr = Tmp; + } +}; + +template<class T> +inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) { + a.swap(b); +} + + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h new file mode 100644 index 0000000000000..0aa478b1ff61c --- /dev/null +++ b/include/llvm/ADT/PointerIntPair.h @@ -0,0 +1,150 @@ +//===- llvm/ADT/PointerIntPair.h - Pair for pointer and int -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerIntPair class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERINTPAIR_H +#define LLVM_ADT_POINTERINTPAIR_H + +#include "llvm/Support/PointerLikeTypeTraits.h" +#include <cassert> + +namespace llvm { + +template<typename T> +struct DenseMapInfo; + +/// PointerIntPair - This class implements a pair of a pointer and small +/// integer. It is designed to represent this in the space required by one +/// pointer by bitmangling the integer into the low part of the pointer. This +/// can only be done for small integers: typically up to 3 bits, but it depends +/// on the number of bits available according to PointerLikeTypeTraits for the +/// type. +/// +/// Note that PointerIntPair always puts the Int part in the highest bits +/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for +/// the bool into bit #2, not bit #0, which allows the low two bits to be used +/// for something else. For example, this allows: +/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool> +/// ... and the two bools will land in different bits. +/// +template <typename PointerTy, unsigned IntBits, typename IntType=unsigned, + typename PtrTraits = PointerLikeTypeTraits<PointerTy> > +class PointerIntPair { + intptr_t Value; + enum { + /// PointerBitMask - The bits that come from the pointer. + PointerBitMask = + ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), + + /// IntShift - The number of low bits that we reserve for other uses, and + /// keep zero. + IntShift = (uintptr_t)PtrTraits::NumLowBitsAvailable-IntBits, + + /// IntMask - This is the unshifted mask for valid bits of the int type. + IntMask = (uintptr_t)(((intptr_t)1 << IntBits)-1), + + // ShiftedIntMask - This is the bits for the integer shifted in place. + ShiftedIntMask = (uintptr_t)(IntMask << IntShift) + }; +public: + PointerIntPair() : Value(0) {} + PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) { + assert(IntBits <= PtrTraits::NumLowBitsAvailable && + "PointerIntPair formed with integer size too large for pointer"); + setPointer(Ptr); + setInt(Int); + } + + PointerTy getPointer() const { + return reinterpret_cast<PointerTy>(Value & PointerBitMask); + } + + IntType getInt() const { + return (IntType)((Value >> IntShift) & IntMask); + } + + void setPointer(PointerTy Ptr) { + intptr_t PtrVal = reinterpret_cast<intptr_t>(Ptr); + assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + "Pointer is not sufficiently aligned"); + // Preserve all low bits, just update the pointer. + Value = PtrVal | (Value & ~PointerBitMask); + } + + void setInt(IntType Int) { + intptr_t IntVal = Int; + assert(IntVal < (1 << IntBits) && "Integer too large for field"); + + // Preserve all bits other than the ones we are updating. + Value &= ~ShiftedIntMask; // Remove integer field. + Value |= IntVal << IntShift; // Set new integer. + } + + void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); } + void setFromOpaqueValue(void *Val) { Value = reinterpret_cast<intptr_t>(Val);} + + static PointerIntPair getFromOpaqueValue(void *V) { + PointerIntPair P; P.setFromOpaqueValue(V); return P; + } + + bool operator==(const PointerIntPair &RHS) const {return Value == RHS.Value;} + bool operator!=(const PointerIntPair &RHS) const {return Value != RHS.Value;} + bool operator<(const PointerIntPair &RHS) const {return Value < RHS.Value;} + bool operator>(const PointerIntPair &RHS) const {return Value > RHS.Value;} + bool operator<=(const PointerIntPair &RHS) const {return Value <= RHS.Value;} + bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;} +}; + +// Provide specialization of DenseMapInfo for PointerIntPair. +template<typename PointerTy, unsigned IntBits, typename IntType> +struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > { + typedef PointerIntPair<PointerTy, IntBits, IntType> Ty; + static Ty getEmptyKey() { + intptr_t Val = -1; + Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; + return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1)); + } + static Ty getTombstoneKey() { + intptr_t Val = -2; + Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; + return Ty(reinterpret_cast<PointerTy>(Val), IntType(0)); + } + static unsigned getHashValue(Ty V) { + uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue()); + return unsigned(IV) ^ unsigned(IV >> 9); + } + static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } + static bool isPod() { return true; } +}; + +// Teach SmallPtrSet that PointerIntPair is "basically a pointer". +template<typename PointerTy, unsigned IntBits, typename IntType, + typename PtrTraits> +class PointerLikeTypeTraits<PointerIntPair<PointerTy, IntBits, IntType, + PtrTraits> > { +public: + static inline void * + getAsVoidPointer(const PointerIntPair<PointerTy, IntBits, IntType> &P) { + return P.getOpaqueValue(); + } + static inline PointerIntPair<PointerTy, IntBits, IntType> + getFromVoidPointer(void *P) { + return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P); + } + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable - IntBits + }; +}; + +} // end namespace llvm +#endif diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h new file mode 100644 index 0000000000000..b3baec1ff3772 --- /dev/null +++ b/include/llvm/ADT/PointerUnion.h @@ -0,0 +1,259 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + + /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return + /// false or true respectively. + template <typename PT1, typename PT2> + static inline int getPointerUnionTypeNum(PT1 *P) { return 0; } + template <typename PT1, typename PT2> + static inline int getPointerUnionTypeNum(PT2 *P) { return 1; } + template <typename PT1, typename PT2> + static inline int getPointerUnionTypeNum(...) { return -1; } + + + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion + /// for the two template arguments. + template <typename PT1, typename PT2> + class PointerUnionUIntTraits { + public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { + PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable, + PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable, + NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + }; + }; + + /// PointerUnion - This implements a discriminated union of two pointer types, + /// and keeps the discriminator bit-mangled into the low bits of the pointer. + /// This allows the implementation to be extremely efficient in space, but + /// permits a very natural and type-safe API. + /// + /// Common use patterns would be something like this: + /// PointerUnion<int*, float*> P; + /// P = (int*)0; + /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" + /// X = P.get<int*>(); // ok. + /// Y = P.get<float*>(); // runtime assertion failure. + /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag) + /// P = (float*)0; + /// Y = P.get<float*>(); // ok. + /// X = P.get<int*>(); // runtime assertion failure. + template <typename PT1, typename PT2> + class PointerUnion { + public: + typedef PointerIntPair<void*, 1, bool, + PointerUnionUIntTraits<PT1,PT2> > ValTy; + private: + ValTy Val; + public: + PointerUnion() {} + + PointerUnion(PT1 V) { + Val.setPointer( + const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))); + Val.setInt(0); + } + PointerUnion(PT2 V) { + Val.setPointer( + const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V))); + Val.setInt(1); + } + + /// isNull - Return true if the pointer help in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.getPointer() == 0; } + operator bool() const { return !isNull(); } + + /// is<T>() return true if the Union currently holds the type matching T. + template<typename T> + int is() const { + int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0); + assert(TyNo != -1 && "Type query could never succeed on PointerUnion!"); + return Val.getInt() == TyNo; + } + + /// get<T>() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template<typename T> + T get() const { + assert(is<T>() && "Invalid accessor called"); + return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); + } + + /// dyn_cast<T>() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template<typename T> + T dyn_cast() const { + if (is<T>()) return get<T>(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion &operator=(const PT1 &RHS) { + Val.setPointer( + const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); + Val.setInt(0); + return *this; + } + const PointerUnion &operator=(const PT2 &RHS) { + Val.setPointer( + const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); + Val.setInt(1); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits)-1. + template<typename PT1, typename PT2> + class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { + public: + static inline void * + getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion<PT1, PT2> + getFromVoidPointer(void *P) { + return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> + ::NumLowBitsAvailable + }; + }; + + + /// PointerUnion3 - This is a pointer union of three pointer types. See + /// documentation for PointerUnion for usage. + template <typename PT1, typename PT2, typename PT3> + class PointerUnion3 { + public: + typedef PointerUnion<PT1, PT2> InnerUnion; + typedef PointerUnion<InnerUnion, PT3> ValTy; + private: + ValTy Val; + public: + PointerUnion3() {} + + PointerUnion3(PT1 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT2 V) { + Val = InnerUnion(V); + } + PointerUnion3(PT3 V) { + Val = V; + } + + /// isNull - Return true if the pointer help in the union is null, + /// regardless of which type it is. + bool isNull() const { return Val.isNull(); } + operator bool() const { return !isNull(); } + + /// is<T>() return true if the Union currently holds the type matching T. + template<typename T> + int is() const { + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) + return Val.is<InnerUnion>() && Val.get<InnerUnion>().is<T>(); + return Val.is<T>(); + } + + /// get<T>() - Return the value of the specified pointer type. If the + /// specified pointer type is incorrect, assert. + template<typename T> + T get() const { + assert(is<T>() && "Invalid accessor called"); + // Is it PT1/PT2? + if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1) + return Val.get<InnerUnion>().get<T>(); + + return Val.get<T>(); + } + + /// dyn_cast<T>() - If the current value is of the specified pointer type, + /// return it, otherwise return null. + template<typename T> + T dyn_cast() const { + if (is<T>()) return get<T>(); + return T(); + } + + /// Assignment operators - Allow assigning into this union from either + /// pointer type, setting the discriminator to remember what it came from. + const PointerUnion3 &operator=(const PT1 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT2 &RHS) { + Val = InnerUnion(RHS); + return *this; + } + const PointerUnion3 &operator=(const PT3 &RHS) { + Val = RHS; + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion3 getFromOpaqueValue(void *VP) { + PointerUnion3 V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. + template<typename PT1, typename PT2, typename PT3> + class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { + public: + static inline void * + getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion3<PT1, PT2, PT3> + getFromVoidPointer(void *P) { + return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> + ::NumLowBitsAvailable + }; + }; +} + +#endif diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h new file mode 100644 index 0000000000000..bf7ce9d0bb6aa --- /dev/null +++ b/include/llvm/ADT/PostOrderIterator.h @@ -0,0 +1,231 @@ +//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic graph +// post order iterator. This should work over any graph type that has a +// GraphTraits specialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POSTORDERITERATOR_H +#define LLVM_ADT_POSTORDERITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" +#include <set> +#include <stack> +#include <vector> + +namespace llvm { + +template<class SetType, bool External> // Non-external set +class po_iterator_storage { +public: + SetType Visited; +}; + +template<class SetType> +class po_iterator_storage<SetType, true> { +public: + po_iterator_storage(SetType &VSet) : Visited(VSet) {} + po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + +template<class GraphT, + class SetType = std::set<typename GraphTraits<GraphT>::NodeType*>, + bool ExtStorage = false, + class GT = GraphTraits<GraphT> > +class po_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>, + public po_iterator_storage<SetType, ExtStorage> { + typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super; + typedef typename GT::NodeType NodeType; + 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::stack<std::pair<NodeType *, ChildItTy> > VisitStack; + + void traverseChild() { + while (VisitStack.top().second != GT::child_end(VisitStack.top().first)) { + NodeType *BB = *VisitStack.top().second++; + if (!this->Visited.count(BB)) { // If the block is not visited... + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + } + } + } + + inline po_iterator(NodeType *BB) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + inline po_iterator() {} // End is when stack is empty. + + inline po_iterator(NodeType *BB, SetType &S) : + po_iterator_storage<SetType, ExtStorage>(&S) { + if(!S.count(BB)) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + } + + inline po_iterator(SetType &S) : + po_iterator_storage<SetType, ExtStorage>(&S) { + } // End is when stack is empty. +public: + typedef typename super::pointer pointer; + typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT G) { return _Self(); } + + static inline _Self begin(GraphT G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end (GraphT G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.top().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the BasicBlock, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + VisitStack.pop(); + if (!VisitStack.empty()) + traverseChild(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); } +template <class T> +po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); } + +// Provide global definitions of external postorder iterators... +template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> > +struct po_ext_iterator : public po_iterator<T, SetType, true> { + po_ext_iterator(const po_iterator<T, SetType, true> &V) : + po_iterator<T, SetType, true>(V) {} +}; + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) { + return po_ext_iterator<T, SetType>::begin(G, S); +} + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) { + return po_ext_iterator<T, SetType>::end(G, S); +} + +// Provide global definitions of inverse post order iterators... +template <class T, + class SetType = std::set<typename GraphTraits<T>::NodeType*>, + bool External = false> +struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > { + ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) : + po_iterator<Inverse<T>, SetType, External> (V) {} +}; + +template <class T> +ipo_iterator<T> ipo_begin(T G, bool Reverse = false) { + return ipo_iterator<T>::begin(G, Reverse); +} + +template <class T> +ipo_iterator<T> ipo_end(T G){ + return ipo_iterator<T>::end(G); +} + +//Provide global definitions of external inverse postorder iterators... +template <class T, + class SetType = std::set<typename GraphTraits<T>::NodeType*> > +struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { + ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) : + ipo_iterator<T, SetType, true>(&V) {} + ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) : + ipo_iterator<T, SetType, true>(&V) {} +}; + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) { + return ipo_ext_iterator<T, SetType>::begin(G, S); +} + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) { + return ipo_ext_iterator<T, SetType>::end(G, S); +} + +//===--------------------------------------------------------------------===// +// Reverse Post Order CFG iterator code +//===--------------------------------------------------------------------===// +// +// This is used to visit basic blocks in a method in reverse post order. This +// class is awkward to use because I don't know a good incremental algorithm to +// computer RPO from a graph. Because of this, the construction of the +// ReversePostOrderTraversal object is expensive (it must walk the entire graph +// with a postorder iterator to build the data structures). The moral of this +// story is: Don't create more ReversePostOrderTraversal classes than necessary. +// +// This class should be used like this: +// { +// ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// } +// + +template<class GraphT, class GT = GraphTraits<GraphT> > +class ReversePostOrderTraversal { + typedef typename GT::NodeType NodeType; + std::vector<NodeType*> Blocks; // Block list in normal PO order + inline void Initialize(NodeType *BB) { + copy(po_begin(BB), po_end(BB), back_inserter(Blocks)); + } +public: + typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator; + + inline ReversePostOrderTraversal(GraphT G) { + Initialize(GT::getEntryNode(G)); + } + + // Because we want a reverse post order, use reverse iterators from the vector + inline rpo_iterator begin() { return Blocks.rbegin(); } + inline rpo_iterator end() { return Blocks.rend(); } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/PriorityQueue.h b/include/llvm/ADT/PriorityQueue.h new file mode 100644 index 0000000000000..a8809dc0b2676 --- /dev/null +++ b/include/llvm/ADT/PriorityQueue.h @@ -0,0 +1,83 @@ +//===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PriorityQueue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PRIORITY_QUEUE_H +#define LLVM_ADT_PRIORITY_QUEUE_H + +#include <queue> + +namespace llvm { + +/// PriorityQueue - This class behaves like std::priority_queue and +/// provides a few additional convenience functions. +/// +template<class T, + class Sequence = std::vector<T>, + class Compare = std::less<typename Sequence::value_type> > +class PriorityQueue : public std::priority_queue<T, Sequence, Compare> { +public: + explicit PriorityQueue(const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue<T, Sequence, Compare>(compare, sequence) + {} + + template<class Iterator> + PriorityQueue(Iterator begin, Iterator end, + const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue<T, Sequence, Compare>(begin, end, compare, sequence) + {} + + /// erase_one - Erase one element from the queue, regardless of its + /// position. This operation performs a linear search to find an element + /// equal to t, but then uses all logarithmic-time algorithms to do + /// the erase operation. + /// + 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(); + + // Logarithmic-time heap bubble-up. + while (i != 0) { + typename Sequence::size_type parent = (i - 1) / 2; + this->c[i] = this->c[parent]; + i = parent; + } + + // The element we want to remove is now at the root, so we can use + // priority_queue's plain pop to remove it. + this->pop(); + } + + /// reheapify - If an element in the queue has changed in a way that + /// affects its standing in the comparison function, the queue's + /// internal state becomes invalid. Calling reheapify() resets the + /// queue's state, making it valid again. This operation has time + /// complexity proportional to the number of elements in the queue, + /// so don't plan to use it a lot. + /// + void reheapify() { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } + + /// clear - Erase all elements from the queue. + /// + void clear() { + this->c.clear(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h new file mode 100644 index 0000000000000..e28f4caa5d769 --- /dev/null +++ b/include/llvm/ADT/SCCIterator.h @@ -0,0 +1,199 @@ +//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected +// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm. +// +// The SCC iterator has the important property that if a node in SCC S1 has an +// edge to a node in SCC S2, then it visits S1 *after* S2. +// +// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. +// (NOTE: This requires some simple wrappers and is not supported yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCCITERATOR_H +#define LLVM_ADT_SCCITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" +#include <map> +#include <vector> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// scc_iterator - Enumerate the SCCs of a directed graph, in +/// reverse topological order of the SCC DAG. +/// +template<class GraphT, class GT = GraphTraits<GraphT> > +class scc_iterator + : public forward_iterator<std::vector<typename GT::NodeType>, ptrdiff_t> { + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef std::vector<NodeType*> SccTy; + typedef forward_iterator<SccTy, ptrdiff_t> super; + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + // The visit counters used to detect when a complete SCC is on the stack. + // visitNum is the global counter. + // nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + unsigned visitNum; + std::map<NodeType *, unsigned> nodeVisitNumbers; + + // SCCNodeStack - Stack holding nodes of the SCC. + std::vector<NodeType *> SCCNodeStack; + + // CurrentSCC - The current SCC, retrieved using operator*(). + SccTy CurrentSCC; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; + + // MinVistNumStack - Stack holding the "min" values for each node in the DFS. + // This is used to track the minimum uplink values for all children of + // the corresponding node on the VisitStack. + std::vector<unsigned> MinVisitNumStack; + + // A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeType* N) { + ++visitNum; // Global counter for the visit order + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + MinVisitNumStack.push_back(visitNum); + VisitStack.push_back(std::make_pair(N, GT::child_begin(N))); + //DOUT << "TarjanSCC: Node " << N << + // " : visitNum = " << visitNum << "\n"; + } + + // The stack-based DFS traversal; defined below. + void DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + // TOS has at least one more child so continue DFS + NodeType *childN = *VisitStack.back().second++; + if (!nodeVisitNumbers.count(childN)) { + // this node has never been seen + DFSVisitOne(childN); + } else { + unsigned childNum = nodeVisitNumbers[childN]; + if (MinVisitNumStack.back() > childNum) + MinVisitNumStack.back() = childNum; + } + } + } + + // Compute the next SCC using the DFS traversal. + void GetNextSCC() { + assert(VisitStack.size() == MinVisitNumStack.size()); + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first)); + NodeType* visitingN = VisitStack.back().first; + unsigned minVisitNum = MinVisitNumStack.back(); + VisitStack.pop_back(); + MinVisitNumStack.pop_back(); + if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum) + MinVisitNumStack.back() = minVisitNum; + + //DOUT << "TarjanSCC: Popped node " << visitingN << + // " : minVisitNum = " << minVisitNum << "; Node visit num = " << + // nodeVisitNumbers[visitingN] << "\n"; + + if (minVisitNum == nodeVisitNumbers[visitingN]) { + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } + } + } + + inline scc_iterator(NodeType *entryN) : visitNum(0) { + DFSVisitOne(entryN); + GetNextSCC(); + } + inline scc_iterator() { /* End is when DFS stack is empty */ } + +public: + typedef scc_iterator<GraphT, GT> _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT& G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT& G) { return _Self(); } + + // Direct loop termination test (I.fini() is more efficient than I == end()) + inline bool fini() const { + assert(!CurrentSCC.empty() || VisitStack.empty()); + return CurrentSCC.empty(); + } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + // Iterator traversal: forward iteration only + inline _Self& operator++() { // Preincrement + GetNextSCC(); + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a reference to the current SCC + inline const SccTy &operator*() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + inline SccTy &operator*() { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + + // hasLoop() -- Test if the current SCC has a loop. If it has more than one + // node, this is trivially true. If not, it may still contain a loop if the + // node has an edge back to itself. + bool hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) return true; + NodeType *N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI) + if (*CI == N) + return true; + return false; + } +}; + + +// Global constructor for the SCC iterator. +template <class T> +scc_iterator<T> scc_begin(T G) { + return scc_iterator<T>::begin(G); +} + +template <class T> +scc_iterator<T> scc_end(T G) { + return scc_iterator<T>::end(G); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h new file mode 100644 index 0000000000000..964e7e07ef7d5 --- /dev/null +++ b/include/llvm/ADT/STLExtras.h @@ -0,0 +1,268 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include <cstddef> // for std::size_t +#include <functional> +#include <utility> // for std::pair +#include "llvm/ADT/iterator.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Extra additions to <functional> +//===----------------------------------------------------------------------===// + +template<class Ty> +struct greater_ptr : public std::binary_function<Ty, Ty, bool> { + bool operator()(const Ty* left, const Ty* right) const { + return *right < *left; + } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter<Interval>); +// +template <class T> +static inline void deleter(T *Ptr) { + delete Ptr; +} + + + +//===----------------------------------------------------------------------===// +// Extra additions to <iterator> +//===----------------------------------------------------------------------===// + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be dereferenced whenever operator* is invoked on the iterator. +// +template <class RootIt, class UnaryFunc> +class mapped_iterator { + RootIt current; + UnaryFunc Fn; +public: + typedef typename std::iterator_traits<RootIt>::iterator_category + iterator_category; + typedef typename std::iterator_traits<RootIt>::difference_type + difference_type; + typedef typename UnaryFunc::result_type value_type; + + typedef void pointer; + //typedef typename UnaryFunc::result_type *pointer; + typedef void reference; // Can't modify value returned by fn + + typedef RootIt iterator_type; + typedef mapped_iterator<RootIt, UnaryFunc> _Self; + + inline const RootIt &getCurrent() const { return current; } + inline const UnaryFunc &getFunc() const { return Fn; } + + inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) + : current(I), Fn(F) {} + inline mapped_iterator(const mapped_iterator &It) + : current(It.current), Fn(It.Fn) {} + + inline value_type operator*() const { // All this work to do this + return Fn(*current); // little change + } + + _Self& operator++() { ++current; return *this; } + _Self& operator--() { --current; return *this; } + _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } + _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } + _Self operator+ (difference_type n) const { + return _Self(current + n, Fn); + } + _Self& operator+= (difference_type n) { current += n; return *this; } + _Self operator- (difference_type n) const { + return _Self(current - n, Fn); + } + _Self& operator-= (difference_type n) { current -= n; return *this; } + reference operator[](difference_type n) const { return *(*this + n); } + + inline bool operator!=(const _Self &X) const { return !operator==(X); } + inline bool operator==(const _Self &X) const { return current == X.current; } + inline bool operator< (const _Self &X) const { return current < X.current; } + + inline difference_type operator-(const _Self &X) const { + return current - X.current; + } +}; + +template <class _Iterator, class Func> +inline mapped_iterator<_Iterator, Func> +operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, + const mapped_iterator<_Iterator, Func>& X) { + return mapped_iterator<_Iterator, Func>(X.getCurrent() - N, X.getFunc()); +} + + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +// +template <class ItTy, class FuncTy> +inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { + return mapped_iterator<ItTy, FuncTy>(I, F); +} + + +// next/prior - These functions unlike std::advance do not modify the +// passed iterator but return a copy. +// +// next(myIt) returns copy of myIt incremented once +// next(myIt, n) returns copy of myIt incremented n times +// prior(myIt) returns copy of myIt decremented once +// prior(myIt, n) returns copy of myIt decremented n times + +template <typename ItTy, typename Dist> +inline ItTy next(ItTy it, Dist n) +{ + std::advance(it, n); + return it; +} + +template <typename ItTy> +inline ItTy next(ItTy it) +{ + return ++it; +} + +template <typename ItTy, typename Dist> +inline ItTy prior(ItTy it, Dist n) +{ + std::advance(it, -n); + return it; +} + +template <typename ItTy> +inline ItTy prior(ItTy it) +{ + return --it; +} + +//===----------------------------------------------------------------------===// +// Extra additions to <utility> +//===----------------------------------------------------------------------===// + +// tie - this function ties two objects and returns a temporary object +// that is assignable from a std::pair. This can be used to make code +// more readable when using values returned from functions bundled in +// a std::pair. Since an example is worth 1000 words: +// +// typedef std::map<int, int> Int2IntMap; +// +// Int2IntMap myMap; +// Int2IntMap::iterator where; +// bool inserted; +// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); +// +// if (inserted) +// // do stuff +// else +// // do other stuff + +namespace +{ + template <typename T1, typename T2> + struct tier { + typedef T1 &first_type; + typedef T2 &second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair<T1, T2>& p) { + first = p.first; + second = p.second; + return *this; + } + }; +} + +template <typename T1, typename T2> +inline tier<T1, T2> tie(T1& f, T2& s) { + return tier<T1, T2>(f, s); +} + +//===----------------------------------------------------------------------===// +// Extra additions for arrays +//===----------------------------------------------------------------------===// + +/// Find where an array ends (for ending iterators) +/// This returns a pointer to the byte immediately +/// after the end of an array. +template<class T, std::size_t N> +inline T *array_endof(T (&x)[N]) { + return x+N; +} + +/// Find the length of an array. +template<class T, std::size_t N> +inline size_t array_lengthof(T (&x)[N]) { + return N; +} + +/// array_pod_sort_comparator - This is helper function for array_pod_sort, +/// which just uses operator< on T. +template<typename T> +static inline int array_pod_sort_comparator(const void *P1, const void *P2) { + if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2)) + return -1; + if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1)) + return 1; + return 0; +} + +/// get_array_pad_sort_comparator - This is an internal helper function used to +/// get type deduction of T right. +template<typename T> +static int (*get_array_pad_sort_comparator(const T &X)) + (const void*, const void*) { + return array_pod_sort_comparator<T>; +} + + +/// array_pod_sort - This sorts an array with the specified start and end +/// extent. This is just like std::sort, except that it calls qsort instead of +/// using an inlined template. qsort is slightly slower than std::sort, but +/// most sorts are not performance critical in LLVM and std::sort has to be +/// template instantiated for each type, leading to significant measured code +/// bloat. This function should generally be used instead of std::sort where +/// possible. +/// +/// This function assumes that you have simple POD-like types that can be +/// compared with operator< and can be moved with memcpy. If this isn't true, +/// you should use std::sort. +/// +/// NOTE: If qsort_r were portable, we could allow a custom comparator and +/// default to std::less. +template<class IteratorTy> +static inline void array_pod_sort(IteratorTy Start, IteratorTy End) { + // Don't dereference start iterator of empty sequence. + if (Start == End) return; + qsort(&*Start, End-Start, sizeof(*Start), + get_array_pad_sort_comparator(*Start)); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h new file mode 100644 index 0000000000000..d5382954c6332 --- /dev/null +++ b/include/llvm/ADT/ScopedHashTable.h @@ -0,0 +1,193 @@ +//===- ScopedHashTable.h - A simple scoped hash table ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an efficient scoped hash table, which is useful for +// things like dominator-based optimizations. This allows clients to do things +// like this: +// +// ScopedHashTable<int, int> HT; +// { +// ScopedHashTableScope<int, int> Scope1(HT); +// HT.insert(0, 0); +// HT.insert(1, 1); +// { +// ScopedHashTableScope<int, int> Scope2(HT); +// HT.insert(0, 42); +// } +// } +// +// Looking up the value for "0" in the Scope2 block will return 42. Looking +// up the value for 0 before 42 is inserted or after Scope2 is popped will +// return 0. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCOPEDHASHTABLE_H +#define LLVM_ADT_SCOPEDHASHTABLE_H + +#include <cassert> +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +template <typename K, typename V> +class ScopedHashTable; + +template <typename K, typename V> +class ScopedHashTableVal { + ScopedHashTableVal *NextInScope; + ScopedHashTableVal *NextForKey; + K Key; + V Val; +public: + ScopedHashTableVal(ScopedHashTableVal *nextInScope, + ScopedHashTableVal *nextForKey, const K &key, const V &val) + : NextInScope(nextInScope), NextForKey(nextForKey), Key(key), Val(val) { + } + + const K &getKey() const { return Key; } + const V &getValue() const { return Val; } + V &getValue() { return Val; } + + ScopedHashTableVal *getNextForKey() { return NextForKey; } + const ScopedHashTableVal *getNextForKey() const { return NextForKey; } +public: + ScopedHashTableVal *getNextInScope() { return NextInScope; } +}; + +template <typename K, typename V> +class ScopedHashTableScope { + /// HT - The hashtable that we are active for. + ScopedHashTable<K, V> &HT; + + /// PrevScope - This is the scope that we are shadowing in HT. + ScopedHashTableScope *PrevScope; + + /// LastValInScope - This is the last value that was inserted for this scope + /// or null if none have been inserted yet. + ScopedHashTableVal<K,V> *LastValInScope; + void operator=(ScopedHashTableScope&); // DO NOT IMPLEMENT + ScopedHashTableScope(ScopedHashTableScope&); // DO NOT IMPLEMENT +public: + ScopedHashTableScope(ScopedHashTable<K, V> &HT); + ~ScopedHashTableScope(); + +private: + friend class ScopedHashTable<K, V>; + ScopedHashTableVal<K, V> *getLastValInScope() { return LastValInScope; } + void setLastValInScope(ScopedHashTableVal<K,V> *Val) { LastValInScope = Val; } +}; + + +template <typename K, typename V> +class ScopedHashTableIterator { + ScopedHashTableVal<K,V> *Node; +public: + ScopedHashTableIterator(ScopedHashTableVal<K,V> *node) : Node(node){} + + V &operator*() const { + assert(Node && "Dereference end()"); + return Node->getValue(); + } + V *operator->() const { + return &Node->getValue(); + } + + bool operator==(const ScopedHashTableIterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const ScopedHashTableIterator &RHS) const { + return Node != RHS.Node; + } + + inline ScopedHashTableIterator& operator++() { // Preincrement + assert(Node && "incrementing past end()"); + Node = Node->getNextForKey(); + return *this; + } + ScopedHashTableIterator operator++(int) { // Postincrement + ScopedHashTableIterator tmp = *this; ++*this; return tmp; + } +}; + + +template <typename K, typename V> +class ScopedHashTable { + DenseMap<K, ScopedHashTableVal<K,V>*> TopLevelMap; + ScopedHashTableScope<K, V> *CurScope; + ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED + void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED + friend class ScopedHashTableScope<K, V>; +public: + ScopedHashTable() : CurScope(0) {} + ~ScopedHashTable() { + assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); + } + + void insert(const K &Key, const V &Val) { + assert(CurScope && "No scope active!"); + + ScopedHashTableVal<K,V> *&KeyEntry = TopLevelMap[Key]; + + KeyEntry = new ScopedHashTableVal<K,V>(CurScope->getLastValInScope(), + KeyEntry, Key, Val); + CurScope->setLastValInScope(KeyEntry); + } + + typedef ScopedHashTableIterator<K, V> iterator; + + iterator end() { return iterator(0); } + + iterator begin(const K &Key) { + typename DenseMap<K, ScopedHashTableVal<K,V>*>::iterator I = + TopLevelMap.find(Key); + if (I == TopLevelMap.end()) return end(); + return iterator(I->second); + } +}; + +/// ScopedHashTableScope ctor - Install this as the current scope for the hash +/// table. +template <typename K, typename V> +ScopedHashTableScope<K, V>::ScopedHashTableScope(ScopedHashTable<K, V> &ht) + : HT(ht) { + PrevScope = HT.CurScope; + HT.CurScope = this; + LastValInScope = 0; +} + +template <typename K, typename V> +ScopedHashTableScope<K, V>::~ScopedHashTableScope() { + assert(HT.CurScope == this && "Scope imbalance!"); + HT.CurScope = PrevScope; + + // Pop and delete all values corresponding to this scope. + while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) { + // Pop this value out of the TopLevelMap. + if (ThisEntry->getNextForKey() == 0) { + assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && + "Scope imbalance!"); + HT.TopLevelMap.erase(ThisEntry->getKey()); + } else { + ScopedHashTableVal<K,V> *&KeyEntry = HT.TopLevelMap[ThisEntry->getKey()]; + assert(KeyEntry == ThisEntry && "Scope imbalance!"); + KeyEntry = ThisEntry->getNextForKey(); + } + + // Pop this value out of the scope. + LastValInScope = ThisEntry->getNextInScope(); + + // Delete this entry. + delete ThisEntry; + } +} + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/SetOperations.h b/include/llvm/ADT/SetOperations.h new file mode 100644 index 0000000000000..71f5db380f6ea --- /dev/null +++ b/include/llvm/ADT/SetOperations.h @@ -0,0 +1,71 @@ +//===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- 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 generic set operations that may be used on set's of +// different types, and different element types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETOPERATIONS_H +#define LLVM_ADT_SETOPERATIONS_H + +namespace llvm { + +/// set_union(A, B) - Compute A := A u B, return whether A changed. +/// +template <class S1Ty, class S2Ty> +bool set_union(S1Ty &S1, const S2Ty &S2) { + bool Changed = false; + + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + if (S1.insert(*SI).second) + Changed = true; + + return Changed; +} + +/// set_intersect(A, B) - Compute A := A ^ B +/// Identical to set_intersection, except that it works on set<>'s and +/// is nicer to use. Functionally, this iterates through S1, removing +/// elements that are not contained in S2. +/// +template <class S1Ty, class S2Ty> +void set_intersect(S1Ty &S1, const S2Ty &S2) { + for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) { + const typename S1Ty::key_type &E = *I; + ++I; + if (!S2.count(E)) S1.erase(E); // Erase element if not in S2 + } +} + +/// set_difference(A, B) - Return A - B +/// +template <class S1Ty, class S2Ty> +S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) { + S1Ty Result; + for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); + SI != SE; ++SI) + if (!S2.count(*SI)) // if the element is not in set2 + Result.insert(*SI); + return Result; +} + +/// set_subtract(A, B) - Compute A := A - B +/// +template <class S1Ty, class S2Ty> +void set_subtract(S1Ty &S1, const S2Ty &S2) { + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + S1.erase(*SI); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h new file mode 100644 index 0000000000000..fab133af4c03b --- /dev/null +++ b/include/llvm/ADT/SetVector.h @@ -0,0 +1,168 @@ +//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a set that has insertion order iteration +// characteristics. This is useful for keeping a set of things that need to be +// visited later but in a deterministic order (insertion order). The interface +// is purposefully minimal. +// +// This file defines SetVector and SmallSetVector, which performs no allocations +// if the SetVector has less than a certain number of elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETVECTOR_H +#define LLVM_ADT_SETVECTOR_H + +#include "llvm/ADT/SmallSet.h" +#include <algorithm> +#include <cassert> +#include <vector> + +namespace llvm { + +/// This adapter class provides a way to keep a set of things that also has the +/// property of a deterministic iteration order. The order of iteration is the +/// order of insertion. +/// @brief A vector that has set insertion semantics. +template <typename T, typename Vector = std::vector<T>, + typename Set = SmallSet<T, 16> > +class SetVector { +public: + typedef T value_type; + typedef T key_type; + typedef T& reference; + typedef const T& const_reference; + typedef Set set_type; + typedef Vector vector_type; + typedef typename vector_type::const_iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::size_type size_type; + + /// @brief Construct an empty SetVector + SetVector() {} + + /// @brief Initialize a SetVector with a range of elements + template<typename It> + SetVector(It Start, It End) { + insert(Start, End); + } + + /// @brief Determine if the SetVector is empty or not. + bool empty() const { + return vector_.empty(); + } + + /// @brief Determine the number of elements in the SetVector. + size_type size() const { + return vector_.size(); + } + + /// @brief Get an iterator to the beginning of the SetVector. + iterator begin() { + return vector_.begin(); + } + + /// @brief Get a const_iterator to the beginning of the SetVector. + const_iterator begin() const { + return vector_.begin(); + } + + /// @brief Get an iterator to the end of the SetVector. + iterator end() { + return vector_.end(); + } + + /// @brief Get a const_iterator to the end of the SetVector. + const_iterator end() const { + return vector_.end(); + } + + /// @brief Return the last element of the SetVector. + const T &back() const { + assert(!empty() && "Cannot call back() on empty SetVector!"); + return vector_.back(); + } + + /// @brief Index into the SetVector. + const_reference operator[](size_type n) const { + assert(n < vector_.size() && "SetVector access out of range!"); + return vector_[n]; + } + + /// @returns true iff the element was inserted into the SetVector. + /// @brief Insert a new element into the SetVector. + bool insert(const value_type &X) { + bool result = set_.insert(X); + if (result) + vector_.push_back(X); + return result; + } + + /// @brief Insert a range of elements into the SetVector. + template<typename It> + void insert(It Start, It End) { + for (; Start != End; ++Start) + if (set_.insert(*Start)) + vector_.push_back(*Start); + } + + /// @brief Remove an item from the set vector. + void remove(const value_type& X) { + if (set_.erase(X)) { + typename vector_type::iterator I = + std::find(vector_.begin(), vector_.end(), X); + assert(I != vector_.end() && "Corrupted SetVector instances!"); + vector_.erase(I); + } + } + + + /// @returns 0 if the element is not in the SetVector, 1 if it is. + /// @brief Count the number of elements of a given key in the SetVector. + size_type count(const key_type &key) const { + return set_.count(key); + } + + /// @brief Completely clear the SetVector + void clear() { + set_.clear(); + vector_.clear(); + } + + /// @brief Remove the last element of the SetVector. + void pop_back() { + assert(!empty() && "Cannot remove an element from an empty SetVector!"); + set_.erase(back()); + vector_.pop_back(); + } + +private: + set_type set_; ///< The set. + vector_type vector_; ///< The vector. +}; + +/// SmallSetVector - A SetVector that performs no allocations if smaller than +/// a certain size. +template <typename T, unsigned N> +class SmallSetVector : public SetVector<T, SmallVector<T, N>, SmallSet<T, N> > { +public: + SmallSetVector() {} + + /// @brief Initialize a SmallSetVector with a range of elements + template<typename It> + SmallSetVector(It Start, It End) { + this->insert(Start, End); + } +}; + +} // End llvm namespace + +// vim: sw=2 ai +#endif diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 0000000000000..a189de2c2279d --- /dev/null +++ b/include/llvm/ADT/SmallPtrSet.h @@ -0,0 +1,284 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImpl for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include <cassert> +#include <cstring> +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PointerLikeTypeTraits.h" + +namespace llvm { + +class SmallPtrSetIteratorImpl; + +/// SmallPtrSetImpl - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImpl { + friend class SmallPtrSetIteratorImpl; +protected: + /// CurArray - This is the current set of buckets. If it points to + /// SmallArray, then the set is in 'small mode'. + const void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + /// Note that CurArray points to an array that has CurArraySize+1 elements in + /// it, so that the end iterator actually points to valid memory. + unsigned CurArraySize; + + // If small, this is # elts allocated consequtively + unsigned NumElements; + unsigned NumTombstones; + const void *SmallArray[1]; // Must be last ivar. + + // Helper to copy construct a SmallPtrSet. + SmallPtrSetImpl(const SmallPtrSetImpl& that); + explicit SmallPtrSetImpl(unsigned SmallSize) { + assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && + "Initial size must be a power of two!"); + CurArray = &SmallArray[0]; + CurArraySize = SmallSize; + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[SmallSize] = 0; + clear(); + } + ~SmallPtrSetImpl(); + +public: + bool empty() const { return size() == 0; } + unsigned size() const { return NumElements; } + + void clear() { + // If the capacity of the array is huge, and the # elements used is small, + // shrink the array. + if (!isSmall() && NumElements*4 < CurArraySize && CurArraySize > 32) + return shrink_and_clear(); + + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize*sizeof(void*)); + NumElements = 0; + NumTombstones = 0; + } + +protected: + static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); } + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + return reinterpret_cast<void*>(-1); + } + + /// insert_imp - This returns true if the pointer was new to the set, false if + /// it was already in the set. This is hidden from the client so that the + /// derived class can check that the right type of pointer is passed in. + bool insert_imp(const void * Ptr); + + /// erase_imp - If the set contains the specified pointer, remove it and + /// return true, otherwise return false. This is hidden from the client so + /// that the derived class can check that the right type of pointer is passed + /// in. + bool erase_imp(const void * Ptr); + + bool count_imp(const void * Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (const void *const *APtr = SmallArray, + *const *E = SmallArray+NumElements; APtr != E; ++APtr) + if (*APtr == Ptr) + return true; + return false; + } + + // Big set case. + return *FindBucketFor(Ptr) == Ptr; + } + +private: + bool isSmall() const { return CurArray == &SmallArray[0]; } + + unsigned Hash(const void *Ptr) const { + return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1)); + } + const void * const *FindBucketFor(const void *Ptr) const; + void shrink_and_clear(); + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(); + + void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. +protected: + void CopyFrom(const SmallPtrSetImpl &RHS); +}; + +/// SmallPtrSetIteratorImpl - This is the common base class shared between all +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + const void *const *Bucket; +public: + explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) { + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + while (*Bucket == SmallPtrSetImpl::getEmptyMarker() || + *Bucket == SmallPtrSetImpl::getTombstoneMarker()) + ++Bucket; + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template<typename PtrTy> +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { + typedef PointerLikeTypeTraits<PtrTy> PtrTraits; +public: + explicit SmallPtrSetIterator(const void *const *BP) + : SmallPtrSetIteratorImpl(BP) {} + + // Most methods provided by baseclass. + + const PtrTy operator*() const { + return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket)); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; ++*this; return tmp; + } +}; + +/// NextPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two. +template<unsigned N> +struct NextPowerOfTwo; + +/// NextPowerOfTwoH - If N is not a power of two, increase it. This is a helper +/// template used to implement NextPowerOfTwo. +template<unsigned N, bool isPowerTwo> +struct NextPowerOfTwoH { + enum { Val = N }; +}; +template<unsigned N> +struct NextPowerOfTwoH<N, false> { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template<unsigned N> +struct NextPowerOfTwo { + enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val }; +}; + + +/// SmallPtrSet - This class implements a set which is optimizer for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImpl for details of the algorithm. +template<class PtrType, unsigned SmallSize> +class SmallPtrSet : public SmallPtrSetImpl { + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val }; + void *SmallArray[SmallSizePowTwo]; + typedef PointerLikeTypeTraits<PtrType> PtrTraits; +public: + SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {} + SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {} + + template<typename It> + SmallPtrSet(It I, It E) + : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) { + insert(I, E); + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(PtrType Ptr) { + return insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(PtrType Ptr) { + return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + /// count - Return true if the specified pointer is in the set. + bool count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)); + } + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + typedef SmallPtrSetIterator<PtrType> iterator; + typedef SmallPtrSetIterator<PtrType> const_iterator; + inline iterator begin() const { + return iterator(CurArray); + } + inline iterator end() const { + return iterator(CurArray+CurArraySize); + } + + // Allow assignment from any smallptrset with the same element type even if it + // doesn't have the same smallsize. + const SmallPtrSet<PtrType, SmallSize>& + operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) { + CopyFrom(RHS); + return *this; + } + +}; + +} + +#endif diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h new file mode 100644 index 0000000000000..caaa96c045f73 --- /dev/null +++ b/include/llvm/ADT/SmallSet.h @@ -0,0 +1,118 @@ +//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSET_H +#define LLVM_ADT_SMALLSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include <set> + +namespace llvm { + +/// SmallSet - This maintains a set of unique values, optimizing for the case +/// when the set is small (less than N). In this case, the set can be +/// maintained with no mallocs. If the set gets large, we expand to using an +/// std::set to maintain reasonable lookup times. +/// +/// Note that this set does not provide a way to iterate over members in the +/// set. +template <typename T, unsigned N> +class SmallSet { + /// Use a SmallVector to hold the elements here (even though it will never + /// reach it's 'large' stage) to avoid calling the default ctors of elements + /// we will never use. + SmallVector<T, N> Vector; + std::set<T> Set; + typedef typename SmallVector<T, N>::const_iterator VIterator; + typedef typename SmallVector<T, N>::iterator mutable_iterator; +public: + SmallSet() {} + + bool empty() const { return Vector.empty() && Set.empty(); } + unsigned size() const { + return isSmall() ? Vector.size() : Set.size(); + } + + /// count - Return true if the element is in the set. + bool count(const T &V) const { + if (isSmall()) { + // Since the collection is small, just do a linear search. + return vfind(V) != Vector.end(); + } else { + return Set.count(V); + } + } + + /// insert - Insert an element into the set if it isn't already there. + bool insert(const T &V) { + if (!isSmall()) + return Set.insert(V).second; + + VIterator I = vfind(V); + if (I != Vector.end()) // Don't reinsert if it already exists. + return false; + if (Vector.size() < N) { + Vector.push_back(V); + return true; + } + + // Otherwise, grow from vector to set. + while (!Vector.empty()) { + Set.insert(Vector.back()); + Vector.pop_back(); + } + Set.insert(V); + return true; + } + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert(*I); + } + + bool erase(const T &V) { + if (!isSmall()) + return Set.erase(V); + for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) { + Vector.erase(I); + return true; + } + return false; + } + + void clear() { + Vector.clear(); + Set.clear(); + } +private: + bool isSmall() const { return Set.empty(); } + + VIterator vfind(const T &V) const { + for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) + return I; + return Vector.end(); + } +}; + +/// If this set is of pointer values, transparently switch over to using +/// SmallPtrSet for performance. +template <typename PointeeType, unsigned N> +class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h new file mode 100644 index 0000000000000..687fa2d26e246 --- /dev/null +++ b/include/llvm/ADT/SmallString.h @@ -0,0 +1,109 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include <cstring> + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template<unsigned InternalLen> +class SmallString : public SmallVector<char, InternalLen> { +public: + // Default ctor - Initialize to empty. + SmallString() {} + + // Initialize with a range. + template<typename ItTy> + SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} + + // Copy ctor. + SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {} + + + // Extra methods. + const char *c_str() const { + SmallString *This = const_cast<SmallString*>(this); + // Ensure that there is a \0 at the end of the string. + This->reserve(this->size()+1); + This->End[0] = 0; + return this->begin(); + } + + // Extra operators. + const SmallString &operator=(const char *RHS) { + this->clear(); + return *this += RHS; + } + + SmallString &operator+=(const char *RHS) { + this->append(RHS, RHS+strlen(RHS)); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } + + SmallString &append_uint_32(uint32_t N) { + char Buffer[20]; + char *BufPtr = Buffer+20; + + if (N == 0) *--BufPtr = '0'; // Handle special case. + + while (N) { + *--BufPtr = '0' + char(N % 10); + N /= 10; + } + this->append(BufPtr, Buffer+20); + return *this; + } + + SmallString &append_uint(uint64_t N) { + if (N == uint32_t(N)) + return append_uint_32(uint32_t(N)); + + char Buffer[40]; + char *BufPtr = Buffer+40; + + if (N == 0) *--BufPtr = '0'; // Handle special case... + + while (N) { + *--BufPtr = '0' + char(N % 10); + N /= 10; + } + + this->append(BufPtr, Buffer+40); + return *this; + } + + SmallString &append_sint(int64_t N) { + // TODO, wrong for minint64. + if (N < 0) { + this->push_back('-'); + N = -N; + } + return append_uint(N); + } + +}; + + +} + +#endif diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h new file mode 100644 index 0000000000000..f59a438d3eb4f --- /dev/null +++ b/include/llvm/ADT/SmallVector.h @@ -0,0 +1,617 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include "llvm/ADT/iterator.h" +#include "llvm/Support/type_traits.h" +#include <algorithm> +#include <cassert> +#include <cstring> +#include <memory> + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else +// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear +// is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace llvm { + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template <typename T> +class SmallVectorImpl { +protected: + T *Begin, *End, *Capacity; + + // Allocate raw space for N elements of type T. If T has a ctor or dtor, we + // don't want it to be automatically run, so we need to represent the space as + // something else. An array of char would work great, but might not be + // aligned sufficiently. Instead, we either use GCC extensions, or some + // number of union instances for the space, which guarantee maximal alignment. +protected: +#ifdef __GNUC__ + typedef char U; + U FirstEl __attribute__((aligned)); +#else + union U { + double D; + long double LD; + long long L; + void *P; + } FirstEl; +#endif + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. +public: + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : Begin(reinterpret_cast<T*>(&FirstEl)), + End(reinterpret_cast<T*>(&FirstEl)), + Capacity(reinterpret_cast<T*>(&FirstEl)+N) { + } + + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + operator delete(Begin); + } + + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + // forward iterator creation methods. + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + iterator end() { return End; } + const_iterator end() const { return End; } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + reference operator[](unsigned idx) { + assert (Begin + idx < End); + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + assert (Begin + idx < End); + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void push_back(const_reference Elt) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(); + goto Retry; + } + + void pop_back() { + --End; + End->~T(); + } + + T pop_back_val() { + T Result = back(); + pop_back(); + return Result; + } + + void clear() { + destroy_range(Begin, End); + End = Begin; + } + + void resize(unsigned N) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, T()); + End = Begin+N; + } + } + + void resize(unsigned N, const T &NV) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, NV); + End = Begin+N; + } + } + + void reserve(unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(N); + } + + void swap(SmallVectorImpl &RHS); + + /// append - Add the specified range to the end of the SmallVector. + /// + template<typename in_iter> + void append(in_iter in_start, in_iter in_end) { + size_type NumInputs = std::distance(in_start, in_end); + // Grow allocated space if needed. + if (NumInputs > size_type(Capacity-End)) + grow(size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_copy(in_start, in_end, End); + End += NumInputs; + } + + /// append - Add the specified range to the end of the SmallVector. + /// + void append(size_type NumInputs, const T &Elt) { + // Grow allocated space if needed. + if (NumInputs > size_type(Capacity-End)) + grow(size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_fill_n(End, NumInputs, Elt); + End += NumInputs; + } + + void assign(unsigned NumElts, const T &Elt) { + clear(); + if (unsigned(Capacity-Begin) < NumElts) + grow(NumElts); + End = Begin+NumElts; + construct_range(Begin, End, Elt); + } + + iterator erase(iterator I) { + iterator N = I; + // Shift all elts down one. + std::copy(I+1, End, I); + // Drop the last elt. + pop_back(); + return(N); + } + + iterator erase(iterator S, iterator E) { + iterator N = S; + // Shift all elts down. + iterator I = std::copy(E, End, S); + // Drop the last elts. + destroy_range(I, End); + End = I; + return(N); + } + + iterator insert(iterator I, const T &Elt) { + if (I == End) { // Important special case for empty vector. + push_back(Elt); + return end()-1; + } + + if (End < Capacity) { + Retry: + new (End) T(back()); + ++End; + // Push everything else over. + std::copy_backward(I, End-1, End); + *I = Elt; + return I; + } + size_t EltNo = I-Begin; + grow(); + I = Begin+EltNo; + goto Retry; + } + + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { + if (I == End) { // Important special case for empty vector. + append(NumToInsert, Elt); + return end()-1; + } + + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I-begin(); + + // Ensure there is enough space. + reserve(static_cast<unsigned>(size() + NumToInsert)); + + // Uninvalidate the iterator. + I = begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(end()-I) >= NumToInsert) { + T *OldEnd = End; + append(End-NumToInsert, End); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::fill_n(I, NumToInsert, Elt); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = End; + End += NumToInsert; + size_t NumOverwritten = OldEnd-I; + std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + + // Replace the overwritten part. + std::fill_n(I, NumOverwritten, Elt); + + // Insert the non-overwritten middle part. + std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); + return I; + } + + template<typename ItTy> + iterator insert(iterator I, ItTy From, ItTy To) { + if (I == End) { // Important special case for empty vector. + append(From, To); + return end()-1; + } + + size_t NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I-begin(); + + // Ensure there is enough space. + reserve(static_cast<unsigned>(size() + NumToInsert)); + + // Uninvalidate the iterator. + I = begin()+InsertElt; + + // If there are more elements between the insertion point and the end of the + // range than there are being inserted, we can use a simple approach to + // insertion. Since we already reserved space, we know that this won't + // reallocate the vector. + if (size_t(end()-I) >= NumToInsert) { + T *OldEnd = End; + append(End-NumToInsert, End); + + // Copy the existing elements that get replaced. + std::copy_backward(I, OldEnd-NumToInsert, OldEnd); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = End; + End += NumToInsert; + size_t NumOverwritten = OldEnd-I; + std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + + // Replace the overwritten part. + std::copy(From, From+NumOverwritten, I); + + // Insert the non-overwritten middle part. + std::uninitialized_copy(From+NumOverwritten, To, OldEnd); + return I; + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { + return pointer(Begin); + } + + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { + return const_pointer(Begin); + } + + const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (size() != RHS.size()) return false; + for (T *This = Begin, *That = RHS.Begin, *E = Begin+size(); + This != E; ++This, ++That) + if (*This != *That) + return false; + return true; + } + bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(begin(), end(), + RHS.begin(), RHS.end()); + } + +private: + /// isSmall - Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return static_cast<const void*>(Begin) == + static_cast<const void*>(&FirstEl); + } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_type MinSize = 0); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void SmallVectorImpl<T>::grow(size_t MinSize) { + size_t CurCapacity = Capacity-Begin; + size_t CurSize = size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T))); + + // Copy the elements over. + if (is_class<T>::value) + std::uninitialized_copy(Begin, End, NewElts); + else + // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + memcpy(NewElts, Begin, CurSize * sizeof(T)); + + // Destroy the original elements. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + operator delete(Begin); + + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +template <typename T> +void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!isSmall() && !RHS.isSmall()) { + std::swap(Begin, RHS.Begin); + std::swap(End, RHS.End); + std::swap(Capacity, RHS.Capacity); + return; + } + if (RHS.size() > size_type(Capacity-Begin)) + grow(RHS.size()); + if (size() > size_type(RHS.Capacity-RHS.begin())) + RHS.grow(size()); + + // Swap the shared elements. + size_t NumShared = size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i) + std::swap(Begin[i], RHS[i]); + + // Copy over the extra elts. + if (size() > RHS.size()) { + size_t EltDiff = size() - RHS.size(); + std::uninitialized_copy(Begin+NumShared, End, RHS.End); + RHS.End += EltDiff; + destroy_range(Begin+NumShared, End); + End = Begin+NumShared; + } else if (RHS.size() > size()) { + size_t EltDiff = RHS.size() - size(); + std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); + End += EltDiff; + destroy_range(RHS.Begin+NumShared, RHS.End); + RHS.End = RHS.Begin+NumShared; + } +} + +template <typename T> +const SmallVectorImpl<T> & +SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + unsigned RHSSize = unsigned(RHS.size()); + unsigned CurSize = unsigned(size()); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd; + if (RHSSize) + NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); + else + NewEnd = Begin; + + // Destroy excess elements. + destroy_range(NewEnd, End); + + // Trim. + End = NewEnd; + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + if (unsigned(Capacity-Begin) < RHSSize) { + // Destroy current elements. + destroy_range(Begin, End); + End = Begin; + CurSize = 0; + grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); + } + + // Copy construct the new elements in place. + std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); + + // Set end. + End = Begin+RHSSize; + return *this; +} + +/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template <typename T, unsigned N> +class SmallVector : public SmallVectorImpl<T> { + /// InlineElts - These are 'N-1' elements that are stored inline in the body + /// of the vector. The extra '1' element is stored in SmallVectorImpl. + typedef typename SmallVectorImpl<T>::U U; + enum { + // MinUs - The number of U's require to cover N T's. + MinUs = (static_cast<unsigned int>(sizeof(T))*N + + static_cast<unsigned int>(sizeof(U)) - 1) / + static_cast<unsigned int>(sizeof(U)), + + // NumInlineEltsElts - The number of elements actually in this array. There + // is already one in the parent class, and we have to round up to avoid + // having a zero-element array. + NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, + + // NumTsAvailable - The number of T's we actually have space for, which may + // be more than N due to rounding. + NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/ + static_cast<unsigned int>(sizeof(T)) + }; + U InlineElts[NumInlineEltsElts]; +public: + SmallVector() : SmallVectorImpl<T>(NumTsAvailable) { + } + + explicit SmallVector(unsigned Size, const T &Value = T()) + : SmallVectorImpl<T>(NumTsAvailable) { + this->reserve(Size); + while (Size--) + this->push_back(Value); + } + + template<typename ItTy> + SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) { + this->append(S, E); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) { + if (!RHS.empty()) + SmallVectorImpl<T>::operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl<T>::operator=(RHS); + return *this; + } + +}; + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template<typename T> + inline void + swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template<typename T, unsigned N> + inline void + swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h new file mode 100644 index 0000000000000..6230135131a7c --- /dev/null +++ b/include/llvm/ADT/SparseBitVector.h @@ -0,0 +1,901 @@ +//===- llvm/ADT/SparseBitVector.h - Efficient Sparse BitVector -*- C++ -*- ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SparseBitVector class. See the doxygen comment for +// SparseBitVector for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SPARSEBITVECTOR_H +#define LLVM_ADT_SPARSEBITVECTOR_H + +#include <cassert> +#include <climits> +#include <cstring> +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/ilist.h" + +namespace llvm { + +/// SparseBitVector is an implementation of a bitvector that is sparse by only +/// storing the elements that have non-zero bits set. In order to make this +/// fast for the most common cases, SparseBitVector is implemented as a linked +/// list of SparseBitVectorElements. We maintain a pointer to the last +/// SparseBitVectorElement accessed (in the form of a list iterator), in order +/// to make multiple in-order test/set constant time after the first one is +/// executed. Note that using vectors to store SparseBitVectorElement's does +/// not work out very well because it causes insertion in the middle to take +/// enormous amounts of time with a large amount of bits. Other structures that +/// have better worst cases for insertion in the middle (various balanced trees, +/// etc) do not perform as well in practice as a linked list with this iterator +/// kept up to date. They are also significantly more memory intensive. + + +template <unsigned ElementSize = 128> +struct SparseBitVectorElement + : ilist_node<SparseBitVectorElement<ElementSize> > { +public: + typedef unsigned long BitWord; + enum { + BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, + BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, + BITS_PER_ELEMENT = ElementSize + }; + +private: + // Index of Element in terms of where first bit starts. + unsigned ElementIndex; + BitWord Bits[BITWORDS_PER_ELEMENT]; + // Needed for sentinels + friend struct ilist_sentinel_traits<SparseBitVectorElement>; + SparseBitVectorElement() { + ElementIndex = ~0U; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + +public: + explicit SparseBitVectorElement(unsigned Idx) { + ElementIndex = Idx; + memset(&Bits[0], 0, sizeof (BitWord) * BITWORDS_PER_ELEMENT); + } + + // Comparison. + bool operator==(const SparseBitVectorElement &RHS) const { + if (ElementIndex != RHS.ElementIndex) + return false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + return true; + } + + bool operator!=(const SparseBitVectorElement &RHS) const { + return !(*this == RHS); + } + + // Return the bits that make up word Idx in our element. + BitWord word(unsigned Idx) const { + assert (Idx < BITWORDS_PER_ELEMENT); + return Bits[Idx]; + } + + unsigned index() const { + return ElementIndex; + } + + bool empty() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i]) + return false; + return true; + } + + void set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + void reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + } + + bool test(unsigned Idx) const { + return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); + } + + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32(Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// find_first - Returns the index of the first set bit. + int find_first() const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + assert(0 && "Illegal empty element"); + return 0; // Not reached + } + + /// find_next - Returns the index of the next set bit starting from the + /// "Curr" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Curr) const { + if (Curr >= BITS_PER_ELEMENT) + return -1; + + unsigned WordPos = Curr / BITWORD_SIZE; + unsigned BitPos = Curr % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + assert (WordPos <= BITWORDS_PER_ELEMENT + && "Word Position outside of element"); + + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < BITWORDS_PER_ELEMENT; ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + // Union this element with RHS and return true if this one changed. + bool unionWith(const SparseBitVectorElement &RHS) { + bool changed = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] |= RHS.Bits[i]; + if (!changed && old != Bits[i]) + changed = true; + } + return changed; + } + + // Return true if we have any bits in common with RHS + bool intersects(const SparseBitVectorElement &RHS) const { + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + if (RHS.Bits[i] & Bits[i]) + return true; + } + return false; + } + + // Intersect this Element with RHS and return true if this one changed. + // BecameZero is set to true if this element became all-zero bits. + bool intersectWith(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Intersect this Element with the complement of RHS and return true if this + // one changed. BecameZero is set to true if this element became all-zero + // bits. + bool intersectWithComplement(const SparseBitVectorElement &RHS, + bool &BecameZero) { + bool changed = false; + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + BitWord old = changed ? 0 : Bits[i]; + + Bits[i] &= ~RHS.Bits[i]; + if (Bits[i] != 0) + allzero = false; + + if (!changed && old != Bits[i]) + changed = true; + } + BecameZero = allzero; + return changed; + } + // Three argument version of intersectWithComplement that intersects + // RHS1 & ~RHS2 into this element + void intersectWithComplement(const SparseBitVectorElement &RHS1, + const SparseBitVectorElement &RHS2, + bool &BecameZero) { + bool allzero = true; + + BecameZero = false; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + Bits[i] = RHS1.Bits[i] & ~RHS2.Bits[i]; + if (Bits[i] != 0) + allzero = false; + } + BecameZero = allzero; + } + + // Get a hash value for this element; + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) { + HashVal ^= Bits[i]; + } + return HashVal; + } +}; + +template <unsigned ElementSize = 128> +class SparseBitVector { + typedef ilist<SparseBitVectorElement<ElementSize> > ElementList; + typedef typename ElementList::iterator ElementListIter; + typedef typename ElementList::const_iterator ElementListConstIter; + enum { + BITWORD_SIZE = SparseBitVectorElement<ElementSize>::BITWORD_SIZE + }; + + // Pointer to our current Element. + ElementListIter CurrElementIter; + ElementList Elements; + + // This is like std::lower_bound, except we do linear searching from the + // current position. + ElementListIter FindLowerBound(unsigned ElementIndex) { + + if (Elements.empty()) { + CurrElementIter = Elements.begin(); + return Elements.begin(); + } + + // Make sure our current iterator is valid. + if (CurrElementIter == Elements.end()) + --CurrElementIter; + + // Search from our current iterator, either backwards or forwards, + // depending on what element we are looking for. + ElementListIter ElementIter = CurrElementIter; + if (CurrElementIter->index() == ElementIndex) { + return ElementIter; + } else if (CurrElementIter->index() > ElementIndex) { + while (ElementIter != Elements.begin() + && ElementIter->index() > ElementIndex) + --ElementIter; + } else { + while (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ++ElementIter; + } + CurrElementIter = ElementIter; + return ElementIter; + } + + // Iterator to walk set bits in the bitmap. This iterator is a lot uglier + // than it would be, in order to be efficient. + class SparseBitVectorIterator { + private: + bool AtEnd; + + const SparseBitVector<ElementSize> *BitVector; + + // Current element inside of bitmap. + ElementListConstIter Iter; + + // Current bit number inside of our bitmap. + unsigned BitNumber; + + // Current word number inside of our element. + unsigned WordNumber; + + // Current bits from the element. + typename SparseBitVectorElement<ElementSize>::BitWord Bits; + + // Move our iterator to the first non-zero bit in the bitmap. + void AdvanceToFirstNonZero() { + if (AtEnd) + return; + if (BitVector->Elements.empty()) { + AtEnd = true; + return; + } + Iter = BitVector->Elements.begin(); + BitNumber = Iter->index() * ElementSize; + unsigned BitPos = Iter->find_first(); + BitNumber += BitPos; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= BitPos % BITWORD_SIZE; + } + + // Move our iterator to the next non-zero bit. + void AdvanceToNextNonZero() { + if (AtEnd) + return; + + while (Bits && !(Bits & 1)) { + Bits >>= 1; + BitNumber += 1; + } + + // See if we ran out of Bits in this word. + if (!Bits) { + int NextSetBitNumber = Iter->find_next(BitNumber % ElementSize) ; + // If we ran out of set bits in this element, move to next element. + if (NextSetBitNumber == -1 || (BitNumber % ElementSize == 0)) { + ++Iter; + WordNumber = 0; + + // We may run out of elements in the bitmap. + if (Iter == BitVector->Elements.end()) { + AtEnd = true; + return; + } + // Set up for next non zero word in bitmap. + BitNumber = Iter->index() * ElementSize; + NextSetBitNumber = Iter->find_first(); + BitNumber += NextSetBitNumber; + WordNumber = (BitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + } else { + WordNumber = (NextSetBitNumber % ElementSize) / BITWORD_SIZE; + Bits = Iter->word(WordNumber); + Bits >>= NextSetBitNumber % BITWORD_SIZE; + BitNumber = Iter->index() * ElementSize; + BitNumber += NextSetBitNumber; + } + } + } + public: + // Preincrement. + inline SparseBitVectorIterator& operator++() { + ++BitNumber; + Bits >>= 1; + AdvanceToNextNonZero(); + return *this; + } + + // Postincrement. + inline SparseBitVectorIterator operator++(int) { + SparseBitVectorIterator tmp = *this; + ++*this; + return tmp; + } + + // Return the current set bit number. + unsigned operator*() const { + return BitNumber; + } + + bool operator==(const SparseBitVectorIterator &RHS) const { + // If they are both at the end, ignore the rest of the fields. + if (AtEnd && RHS.AtEnd) + return true; + // Otherwise they are the same if they have the same bit number and + // bitmap. + return AtEnd == RHS.AtEnd && RHS.BitNumber == BitNumber; + } + bool operator!=(const SparseBitVectorIterator &RHS) const { + return !(*this == RHS); + } + SparseBitVectorIterator(): BitVector(NULL) { + } + + + SparseBitVectorIterator(const SparseBitVector<ElementSize> *RHS, + bool end = false):BitVector(RHS) { + Iter = BitVector->Elements.begin(); + BitNumber = 0; + Bits = 0; + WordNumber = ~0; + AtEnd = end; + AdvanceToFirstNonZero(); + } + }; +public: + typedef SparseBitVectorIterator iterator; + + SparseBitVector () { + CurrElementIter = Elements.begin (); + } + + ~SparseBitVector() { + } + + // SparseBitVector copy ctor. + SparseBitVector(const SparseBitVector &RHS) { + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + } + + // Clear. + void clear() { + Elements.clear(); + } + + // Assignment + SparseBitVector& operator=(const SparseBitVector& RHS) { + Elements.clear(); + + ElementListConstIter ElementIter = RHS.Elements.begin(); + while (ElementIter != RHS.Elements.end()) { + Elements.push_back(SparseBitVectorElement<ElementSize>(*ElementIter)); + ++ElementIter; + } + + CurrElementIter = Elements.begin (); + + return *this; + } + + // Test, Reset, and Set a bit in the bitmap. + bool test(unsigned Idx) { + if (Elements.empty()) + return false; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return false; + return ElementIter->test(Idx % ElementSize); + } + + void reset(unsigned Idx) { + if (Elements.empty()) + return; + + unsigned ElementIndex = Idx / ElementSize; + ElementListIter ElementIter = FindLowerBound(ElementIndex); + + // If we can't find an element that is supposed to contain this bit, there + // is nothing more to do. + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) + return; + ElementIter->reset(Idx % ElementSize); + + // When the element is zeroed out, delete it. + if (ElementIter->empty()) { + ++CurrElementIter; + Elements.erase(ElementIter); + } + } + + void set(unsigned Idx) { + unsigned ElementIndex = Idx / ElementSize; + SparseBitVectorElement<ElementSize> *Element; + ElementListIter ElementIter; + if (Elements.empty()) { + Element = new SparseBitVectorElement<ElementSize>(ElementIndex); + ElementIter = Elements.insert(Elements.end(), Element); + + } else { + ElementIter = FindLowerBound(ElementIndex); + + if (ElementIter == Elements.end() || + ElementIter->index() != ElementIndex) { + Element = new SparseBitVectorElement<ElementSize>(ElementIndex); + // We may have hit the beginning of our SparseBitVector, in which case, + // we may need to insert right after this element, which requires moving + // the current iterator forward one, because insert does insert before. + if (ElementIter != Elements.end() && + ElementIter->index() < ElementIndex) + ElementIter = Elements.insert(++ElementIter, Element); + else + ElementIter = Elements.insert(ElementIter, Element); + } + } + CurrElementIter = ElementIter; + + ElementIter->set(Idx % ElementSize); + } + + bool test_and_set (unsigned Idx) { + bool old = test(Idx); + if (!old) { + set(Idx); + return true; + } + return false; + } + + bool operator!=(const SparseBitVector &RHS) const { + return !(*this == RHS); + } + + bool operator==(const SparseBitVector &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + for (; Iter1 != Elements.end() && Iter2 != RHS.Elements.end(); + ++Iter1, ++Iter2) { + if (*Iter1 != *Iter2) + return false; + } + return Iter1 == Elements.end() && Iter2 == RHS.Elements.end(); + } + + // Union our bitmap with the RHS and return true if we changed. + bool operator|=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If RHS is empty, we are done + if (RHS.Elements.empty()) + return false; + + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end() || Iter1->index() > Iter2->index()) { + Elements.insert(Iter1, + new SparseBitVectorElement<ElementSize>(*Iter2)); + ++Iter2; + changed = true; + } else if (Iter1->index() == Iter2->index()) { + changed |= Iter1->unionWith(*Iter2); + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the RHS and return true if ours changed. + bool operator&=(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWith(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } + } + Elements.erase(Iter1, Elements.end()); + CurrElementIter = Elements.begin(); + return changed; + } + + // Intersect our bitmap with the complement of the RHS and return true + // if ours changed. + bool intersectWithComplement(const SparseBitVector &RHS) { + bool changed = false; + ElementListIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // If either our bitmap or RHS is empty, we are done + if (Elements.empty() || RHS.Elements.empty()) + return false; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) { + CurrElementIter = Elements.begin(); + return changed; + } + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero; + changed |= Iter1->intersectWithComplement(*Iter2, BecameZero); + if (BecameZero) { + ElementListIter IterTmp = Iter1; + ++Iter1; + Elements.erase(IterTmp); + } else { + ++Iter1; + } + ++Iter2; + } else { + ++Iter1; + } + } + CurrElementIter = Elements.begin(); + return changed; + } + + bool intersectWithComplement(const SparseBitVector<ElementSize> *RHS) const { + return intersectWithComplement(*RHS); + } + + + // Three argument version of intersectWithComplement. + // Result of RHS1 & ~RHS2 is stored into this bitmap. + void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1, + const SparseBitVector<ElementSize> &RHS2) + { + Elements.clear(); + CurrElementIter = Elements.begin(); + ElementListConstIter Iter1 = RHS1.Elements.begin(); + ElementListConstIter Iter2 = RHS2.Elements.begin(); + + // If RHS1 is empty, we are done + // If RHS2 is empty, we still have to copy RHS1 + if (RHS1.Elements.empty()) + return; + + // Loop through, intersecting as we go, erasing elements when necessary. + while (Iter2 != RHS2.Elements.end()) { + if (Iter1 == RHS1.Elements.end()) + return; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + bool BecameZero = false; + SparseBitVectorElement<ElementSize> *NewElement = + new SparseBitVectorElement<ElementSize>(Iter1->index()); + NewElement->intersectWithComplement(*Iter1, *Iter2, BecameZero); + if (!BecameZero) { + Elements.push_back(NewElement); + } + else + delete NewElement; + ++Iter1; + ++Iter2; + } else { + SparseBitVectorElement<ElementSize> *NewElement = + new SparseBitVectorElement<ElementSize>(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + } + + // copy the remaining elements + while (Iter1 != RHS1.Elements.end()) { + SparseBitVectorElement<ElementSize> *NewElement = + new SparseBitVectorElement<ElementSize>(*Iter1); + Elements.push_back(NewElement); + ++Iter1; + } + + return; + } + + void intersectWithComplement(const SparseBitVector<ElementSize> *RHS1, + const SparseBitVector<ElementSize> *RHS2) { + intersectWithComplement(*RHS1, *RHS2); + } + + bool intersects(const SparseBitVector<ElementSize> *RHS) const { + return intersects(*RHS); + } + + // Return true if we share any bits in common with RHS + bool intersects(const SparseBitVector<ElementSize> &RHS) const { + ElementListConstIter Iter1 = Elements.begin(); + ElementListConstIter Iter2 = RHS.Elements.begin(); + + // Check if both bitmaps are empty. + if (Elements.empty() && RHS.Elements.empty()) + return false; + + // Loop through, intersecting stopping when we hit bits in common. + while (Iter2 != RHS.Elements.end()) { + if (Iter1 == Elements.end()) + return false; + + if (Iter1->index() > Iter2->index()) { + ++Iter2; + } else if (Iter1->index() == Iter2->index()) { + if (Iter1->intersects(*Iter2)) + return true; + ++Iter1; + ++Iter2; + } else { + ++Iter1; + } + } + return false; + } + + // Return true iff all bits set in this SparseBitVector are + // also set in RHS. + bool contains(const SparseBitVector<ElementSize> &RHS) const { + SparseBitVector<ElementSize> Result(*this); + Result &= RHS; + return (Result == RHS); + } + + // Return the first set bit in the bitmap. Return -1 if no bits are set. + int find_first() const { + if (Elements.empty()) + return -1; + const SparseBitVectorElement<ElementSize> &First = *(Elements.begin()); + return (First.index() * ElementSize) + First.find_first(); + } + + // Return true if the SparseBitVector is empty + bool empty() const { + return Elements.empty(); + } + + unsigned count() const { + unsigned BitCount = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) + BitCount += Iter->count(); + + return BitCount; + } + iterator begin() const { + return iterator(this); + } + + iterator end() const { + return iterator(this, true); + } + + // Get a hash value for this bitmap. + uint64_t getHashValue() const { + uint64_t HashVal = 0; + for (ElementListConstIter Iter = Elements.begin(); + Iter != Elements.end(); + ++Iter) { + HashVal ^= Iter->index(); + HashVal ^= Iter->getHashValue(); + } + return HashVal; + } +}; + +// Convenience functions to allow Or and And without dereferencing in the user +// code. + +template <unsigned ElementSize> +inline bool operator |=(SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> *RHS) { + return LHS |= *RHS; +} + +template <unsigned ElementSize> +inline bool operator |=(SparseBitVector<ElementSize> *LHS, + const SparseBitVector<ElementSize> &RHS) { + return LHS->operator|=(RHS); +} + +template <unsigned ElementSize> +inline bool operator &=(SparseBitVector<ElementSize> *LHS, + const SparseBitVector<ElementSize> &RHS) { + return LHS->operator&=(RHS); +} + +template <unsigned ElementSize> +inline bool operator &=(SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> *RHS) { + return LHS &= *RHS; +} + +// Convenience functions for infix union, intersection, difference operators. + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator|(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result(LHS); + Result |= RHS; + return Result; +} + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator&(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result(LHS); + Result &= RHS; + return Result; +} + +template <unsigned ElementSize> +inline SparseBitVector<ElementSize> +operator-(const SparseBitVector<ElementSize> &LHS, + const SparseBitVector<ElementSize> &RHS) { + SparseBitVector<ElementSize> Result; + Result.intersectWithComplement(LHS, RHS); + return Result; +} + + + + +// Dump a SparseBitVector to a stream +template <unsigned ElementSize> +void dump(const SparseBitVector<ElementSize> &LHS, llvm::OStream &out) { + out << "[ "; + + typename SparseBitVector<ElementSize>::iterator bi; + for (bi = LHS.begin(); bi != LHS.end(); ++bi) { + out << *bi << " "; + } + out << " ]\n"; +} +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h new file mode 100644 index 0000000000000..537f86637953b --- /dev/null +++ b/include/llvm/ADT/Statistic.h @@ -0,0 +1,75 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +namespace llvm { + +class Statistic { +public: + const char *Name; + const char *Desc; + unsigned Value : 31; + bool Initialized : 1; + + unsigned getValue() const { return Value; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + + /// construct - This should only be called for non-global statistics. + void construct(const char *name, const char *desc) { + Name = name; Desc = desc; + Value = 0; Initialized = 0; + } + + // Allow use of this class as the value itself. + operator unsigned() const { return Value; } + const Statistic &operator=(unsigned Val) { Value = Val; return init(); } + const Statistic &operator++() { ++Value; return init(); } + unsigned operator++(int) { init(); return Value++; } + const Statistic &operator--() { --Value; return init(); } + unsigned operator--(int) { init(); return Value--; } + const Statistic &operator+=(const unsigned &V) { Value += V; return init(); } + const Statistic &operator-=(const unsigned &V) { Value -= V; return init(); } + const Statistic &operator*=(const unsigned &V) { Value *= V; return init(); } + const Statistic &operator/=(const unsigned &V) { Value /= V; return init(); } + +protected: + Statistic &init() { + if (!Initialized) RegisterStatistic(); + return *this; + } + void RegisterStatistic(); +}; + +// STATISTIC - A macro to make definition of statistics really simple. This +// automatically passes the DEBUG_TYPE of the file into the statistic. +#define STATISTIC(VARNAME, DESC) \ + static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 } + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h new file mode 100644 index 0000000000000..e40e409802d25 --- /dev/null +++ b/include/llvm/ADT/StringExtras.h @@ -0,0 +1,234 @@ +//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/APFloat.h" +#include <cctype> +#include <cstdio> +#include <string> +#include <vector> + +namespace llvm { + +/// hexdigit - Return the (uppercase) hexadecimal character for the +/// given number \arg X (which should be less than 16). +static inline char hexdigit(unsigned X) { + return X < 10 ? '0' + X : 'A' + X - 10; +} + +/// utohex_buffer - Emit the specified number into the buffer specified by +/// BufferEnd, returning a pointer to the start of the string. This can be used +/// like this: (note that the buffer must be large enough to handle any number): +/// char Buffer[40]; +/// printf("0x%s", utohex_buffer(X, Buffer+40)); +/// +/// This should only be used with unsigned types. +/// +template<typename IntTy> +static inline char *utohex_buffer(IntTy X, char *BufferEnd) { + char *BufPtr = BufferEnd; + *--BufPtr = 0; // Null terminate buffer. + if (X == 0) { + *--BufPtr = '0'; // Handle special case. + return BufPtr; + } + + while (X) { + unsigned char Mod = static_cast<unsigned char>(X) & 15; + *--BufPtr = hexdigit(Mod); + X >>= 4; + } + return BufPtr; +} + +static inline std::string utohexstr(uint64_t X) { + char Buffer[40]; + return utohex_buffer(X, Buffer+40); +} + +static inline std::string utostr_32(uint32_t X, bool isNeg = false) { + char Buffer[20]; + char *BufPtr = Buffer+19; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + + return std::string(BufPtr); +} + +static inline std::string utostr(uint64_t X, bool isNeg = false) { + if (X == uint32_t(X)) + return utostr_32(uint32_t(X), isNeg); + + char Buffer[40]; + char *BufPtr = Buffer+39; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr); +} + + +static inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast<uint64_t>(-X), true); + else + return utostr(static_cast<uint64_t>(X)); +} + +static inline std::string itohexstr(int64_t X) { + return utohexstr(static_cast<uint64_t>(X)); +} + +static inline std::string ftostr(double V) { + char Buffer[200]; + sprintf(Buffer, "%20.6e", V); + char *B = Buffer; + while (*B == ' ') ++B; + return B; +} + +static inline std::string ftostr(const APFloat& V) { + if (&V.getSemantics() == &APFloat::IEEEdouble) + return ftostr(V.convertToDouble()); + else if (&V.getSemantics() == &APFloat::IEEEsingle) + return ftostr((double)V.convertToFloat()); + return "<unknown format in ftostr>"; // error +} + +static inline std::string LowercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (isupper(result[i])) + result[i] = char(tolower(result[i])); + return result; +} + +static inline std::string UppercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (islower(result[i])) + result[i] = char(toupper(result[i])); + return result; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const std::string &RHS) { + if (LHS.size() != RHS.size()) return false; + for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i) + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + return true; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const char *RHS) { + for (unsigned i = 0, e = static_cast<unsigned>(LHS.size()); i != e; ++i) { + if (RHS[i] == 0) return false; // RHS too short. + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + } + return RHS[LHS.size()] == 0; // Not too long? +} + +/// StringsEqualNoCase - Return true if the two null-terminated C strings are +/// equal, ignoring + +static inline bool StringsEqualNoCase(const char *LHS, const char *RHS, + unsigned len) { + + for (unsigned i = 0; i < len; ++i) { + if (tolower(LHS[i]) != tolower(RHS[i])) + return false; + + // If RHS[i] == 0 then LHS[i] == 0 or otherwise we would have returned + // at the previous branch as tolower('\0') == '\0'. + if (RHS[i] == 0) + return true; + } + + return true; +} + +/// CStrInCStrNoCase - Portable version of strcasestr. Locates the first +/// occurance of c-string 's2' in string 's1', ignoring case. Returns +/// NULL if 's2' cannot be found. +static inline const char* CStrInCStrNoCase(const char *s1, const char *s2) { + + // Are either strings NULL or empty? + if (!s1 || !s2 || s1[0] == '\0' || s2[0] == '\0') + return 0; + + if (s1 == s2) + return s1; + + const char *I1=s1, *I2=s2; + + while (*I1 != '\0' && *I2 != '\0' ) + if (tolower(*I1) != tolower(*I2)) { // No match. Start over. + ++s1; I1 = s1; I2 = s2; + } + else { // Character match. Advance to the next character. + ++I1; ++I2; + } + + // If we exhausted all of the characters in 's2', then 's2' appears in 's1'. + return *I2 == '\0' ? s1 : 0; +} + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The Source source string is updated in place to remove the returned string +/// and any delimiter prefix from it. +std::string getToken(std::string &Source, + const char *Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(const std::string &Source, + std::vector<std::string> &OutFragments, + const char *Delimiters = " \t\n\v\f\r"); + +/// UnescapeString - Modify the argument string, turning two character sequences +/// like '\\' 'n' into '\n'. This handles: \e \a \b \f \n \r \t \v \' \\ and +/// \num (where num is a 1-3 byte octal value). +void UnescapeString(std::string &Str); + +/// EscapeString - Modify the argument string, turning '\\' and anything that +/// doesn't satisfy std::isprint into an escape sequence. +void EscapeString(std::string &Str); + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h new file mode 100644 index 0000000000000..a15d24eeae251 --- /dev/null +++ b/include/llvm/ADT/StringMap.h @@ -0,0 +1,504 @@ +//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/Support/Allocator.h" +#include <cstring> +#include <string> + +namespace llvm { + template<typename ValueT> + class StringMapConstIterator; + template<typename ValueT> + class StringMapIterator; + template<typename ValueTy> + class StringMapEntry; + +/// StringMapEntryInitializer - This datatype can be partially specialized for +/// various datatypes in a stringmap to allow them to be initialized when an +/// entry is default constructed for the map. +template<typename ValueTy> +class StringMapEntryInitializer { +public: + template <typename InitTy> + static void Initialize(StringMapEntry<ValueTy> &T, InitTy InitVal) { + T.second = InitVal; + } +}; + + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + unsigned StrLen; +public: + explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} + + unsigned getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +public: + /// ItemBucket - The hash table consists of an array of these. If Item is + /// non-null, this is an extant entry, otherwise, it is a hole. + struct ItemBucket { + /// FullHashValue - This remembers the full hash value of the key for + /// easy scanning. + unsigned FullHashValue; + + /// Item - This is a pointer to the actual item object. + StringMapEntryBase *Item; + }; + +protected: + ItemBucket *TheTable; + unsigned NumBuckets; + unsigned NumItems; + unsigned NumTombstones; + unsigned ItemSize; +protected: + explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { + // Initialize the map with zero buckets to allocation. + TheTable = 0; + NumBuckets = 0; + NumItems = 0; + NumTombstones = 0; + } + StringMapImpl(unsigned InitSize, unsigned ItemSize); + void RehashTable(); + + /// ShouldRehash - Return true if the table should be rehashed after a new + /// element was recently inserted. + bool ShouldRehash() const { + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + return NumItems*4 > NumBuckets*3 || + NumBuckets-(NumItems+NumTombstones) < NumBuckets/8; + } + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(const char *KeyStart, const char *KeyEnd); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(const char *KeyStart, const char *KeyEnd) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(const char *KeyStart, const char *KeyEnd); +private: + void init(unsigned Size); +public: + static StringMapEntryBase *getTombstoneVal() { + return (StringMapEntryBase*)-1; + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template<typename ValueTy> +class StringMapEntry : public StringMapEntryBase { +public: + ValueTy second; + + explicit StringMapEntry(unsigned strLen) + : StringMapEntryBase(strLen), second() {} + StringMapEntry(unsigned strLen, const ValueTy &V) + : StringMapEntryBase(strLen), second(V) {} + + const ValueTy &getValue() const { return second; } + ValueTy &getValue() { return second; } + + void setValue(const ValueTy &V) { second = V; } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} + + const char *first() const { return getKeyData(); } + + /// Create - Create a StringMapEntry for the specified key and default + /// construct the value. + template<typename AllocatorTy, typename InitType> + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator, + InitType InitVal) { + unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart); + + // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill + // in. Allocate a new item with space for the string at the end and a null + // terminator. + + unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ + KeyLength+1; + unsigned Alignment = alignof<StringMapEntry>(); + + StringMapEntry *NewItem = + static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); + + // Default construct the value. + new (NewItem) StringMapEntry(KeyLength); + + // Copy the string information. + char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); + memcpy(StrBuffer, KeyStart, KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + + // Initialize the value if the client wants to. + StringMapEntryInitializer<ValueTy>::Initialize(*NewItem, InitVal); + return NewItem; + } + + template<typename AllocatorTy> + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator) { + return Create(KeyStart, KeyEnd, Allocator, 0); + } + + + /// Create - Create a StringMapEntry with normal malloc/free. + template<typename InitType> + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + InitType InitVal) { + MallocAllocator A; + return Create(KeyStart, KeyEnd, A, InitVal); + } + + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { + return Create(KeyStart, KeyEnd, ValueTy()); + } + + /// GetStringMapEntryFromValue - Given a value that is known to be embedded + /// into a StringMapEntry, return the StringMapEntry itself. + static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { + StringMapEntry *EPtr = 0; + char *Ptr = reinterpret_cast<char*>(&V) - + (reinterpret_cast<char*>(&EPtr->second) - + reinterpret_cast<char*>(EPtr)); + return *reinterpret_cast<StringMapEntry*>(Ptr); + } + static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { + return GetStringMapEntryFromValue(const_cast<ValueTy&>(V)); + } + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template<typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~StringMapEntry(); + Allocator.Deallocate(this); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template<typename ValueTy, typename AllocatorTy = MallocAllocator> +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + typedef StringMapEntry<ValueTy> MapEntryTy; +public: + StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {} + explicit StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {} + explicit StringMap(const StringMap &RHS) + : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { + assert(RHS.empty() && + "Copy ctor from non-empty stringmap not implemented yet!"); + } + void operator=(const StringMap &RHS) { + assert(RHS.empty() && + "assignment from non-empty stringmap not implemented yet!"); + clear(); + } + + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + typedef const char* key_type; + typedef ValueTy mapped_type; + typedef StringMapEntry<ValueTy> value_type; + typedef size_t size_type; + + typedef StringMapConstIterator<ValueTy> const_iterator; + typedef StringMapIterator<ValueTy> iterator; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator find(const char *KeyStart, const char *KeyEnd) { + int Bucket = FindKey(KeyStart, KeyEnd); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket); + } + iterator find(const char *Key) { + return find(Key, Key + strlen(Key)); + } + iterator find(const std::string &Key) { + return find(Key.data(), Key.data() + Key.size()); + } + + const_iterator find(const char *KeyStart, const char *KeyEnd) const { + int Bucket = FindKey(KeyStart, KeyEnd); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket); + } + const_iterator find(const char *Key) const { + return find(Key, Key + strlen(Key)); + } + const_iterator find(const std::string &Key) const { + return find(Key.data(), Key.data() + Key.size()); + } + + /// lookup - Return the entry for the specified key, or a default + /// constructed value if no such entry exists. + ValueTy lookup(const char *KeyStart, const char *KeyEnd) const { + const_iterator it = find(KeyStart, KeyEnd); + if (it != end()) + return it->second; + return ValueTy(); + } + ValueTy lookup(const char *Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + return ValueTy(); + } + ValueTy lookup(const std::string &Key) const { + const_iterator it = find(Key); + if (it != end()) + return it->second; + return ValueTy(); + } + + ValueTy& operator[](const char *Key) { + return GetOrCreateValue(Key, Key + strlen(Key)).getValue(); + } + ValueTy& operator[](const std::string &Key) { + return GetOrCreateValue(Key.data(), Key.data() + Key.size()).getValue(); + } + + size_type count(const char *KeyStart, const char *KeyEnd) const { + return find(KeyStart, KeyEnd) == end() ? 0 : 1; + } + size_type count(const char *Key) const { + return count(Key, Key + strlen(Key)); + } + size_type count(const std::string &Key) const { + return count(Key.data(), Key.data() + Key.size()); + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = + LookupBucketFor(KeyValue->getKeyData(), + KeyValue->getKeyData()+KeyValue->getKeyLength()); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + Bucket.Item = KeyValue; + ++NumItems; + + if (ShouldRehash()) + RehashTable(); + return true; + } + + // clear - Empties out the StringMap + void clear() { + if (empty()) return; + + // Zap all values, resetting the keys back to non-present (not tombstone), + // which is safe because we're removing all elements. + for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) { + if (I->Item && I->Item != getTombstoneVal()) { + static_cast<MapEntryTy*>(I->Item)->Destroy(Allocator); + I->Item = 0; + } + } + + NumItems = 0; + } + + /// GetOrCreateValue - Look up the specified key in the table. If a value + /// exists, return it. Otherwise, default construct a value, insert it, and + /// return. + template <typename InitTy> + StringMapEntry<ValueTy> &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd, + InitTy Val) { + unsigned BucketNo = LookupBucketFor(KeyStart, KeyEnd); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return *static_cast<MapEntryTy*>(Bucket.Item); + + MapEntryTy *NewItem = MapEntryTy::Create(KeyStart, KeyEnd, Allocator, Val); + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + ++NumItems; + + // Fill in the bucket for the hash table. The FullHashValue was already + // filled in by LookupBucketFor. + Bucket.Item = NewItem; + + if (ShouldRehash()) + RehashTable(); + return *NewItem; + } + + StringMapEntry<ValueTy> &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd) { + return GetOrCreateValue(KeyStart, KeyEnd, ValueTy()); + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + void erase(iterator I) { + MapEntryTy &V = *I; + remove(&V); + V.Destroy(Allocator); + } + + bool erase(const char *Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } + + bool erase(const std::string &Key) { + iterator I = find(Key); + if (I == end()) return false; + erase(I); + return true; + } + + ~StringMap() { + clear(); + free(TheTable); + } +}; + + +template<typename ValueTy> +class StringMapConstIterator { +protected: + StringMapImpl::ItemBucket *Ptr; +public: + typedef StringMapEntry<ValueTy> value_type; + + explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + const value_type &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); + } + const value_type *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); + } + + bool operator==(const StringMapConstIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const StringMapConstIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline StringMapConstIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + StringMapConstIterator operator++(int) { // Postincrement + StringMapConstIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template<typename ValueTy> +class StringMapIterator : public StringMapConstIterator<ValueTy> { +public: + explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { + } + StringMapEntry<ValueTy> &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); + } + StringMapEntry<ValueTy> *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); + } +}; + +} + +#endif diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h new file mode 100644 index 0000000000000..00048361e86f2 --- /dev/null +++ b/include/llvm/ADT/StringSet.h @@ -0,0 +1,39 @@ +//===--- StringSet.h - The LLVM Compiler Driver -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// StringSet - A set-like wrapper for the StringMap. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGSET_H +#define LLVM_ADT_STRINGSET_H + +#include "llvm/ADT/StringMap.h" +#include <cassert> + +namespace llvm { + + /// StringSet - A wrapper for StringMap that provides set-like + /// functionality. Only insert() and count() methods are used by my + /// code. + template <class AllocatorTy = llvm::MallocAllocator> + class StringSet : public llvm::StringMap<char, AllocatorTy> { + typedef llvm::StringMap<char, AllocatorTy> base; + public: + bool insert(const std::string& InLang) { + assert(!InLang.empty()); + const char* KeyStart = &InLang[0]; + const char* KeyEnd = KeyStart + InLang.size(); + return base::insert(llvm::StringMapEntry<char>:: + Create(KeyStart, KeyEnd, base::getAllocator(), '+')); + } + }; +} + +#endif // LLVM_ADT_STRINGSET_H diff --git a/include/llvm/ADT/Tree.h b/include/llvm/ADT/Tree.h new file mode 100644 index 0000000000000..78f5b4fab97f7 --- /dev/null +++ b/include/llvm/ADT/Tree.h @@ -0,0 +1,62 @@ +//===- llvm/ADT/Tree.h - Generic n-way tree structure -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines a generic N-way tree node structure. The tree structure +// is immutable after creation, but the payload contained within it is not. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TREE_H +#define LLVM_ADT_TREE_H + +#include <vector> + +namespace llvm { + +template<class ConcreteTreeNode, class Payload> +class Tree { + std::vector<ConcreteTreeNode*> Children; // This node's children, if any. + ConcreteTreeNode *Parent; // Parent of this node. + Payload Data; // Data held in this node. + +protected: + void setChildren(const std::vector<ConcreteTreeNode*> &children) { + Children = children; + } +public: + inline Tree(ConcreteTreeNode *parent) : Parent(parent) {} + inline Tree(const std::vector<ConcreteTreeNode*> &children, + ConcreteTreeNode *par) : Children(children), Parent(par) {} + + inline Tree(const std::vector<ConcreteTreeNode*> &children, + ConcreteTreeNode *par, const Payload &data) + : Children(children), Parent(par), Data(data) {} + + // Tree dtor - Free all children + inline ~Tree() { + for (unsigned i = Children.size(); i > 0; --i) + delete Children[i-1]; + } + + // Tree manipulation/walking routines... + inline ConcreteTreeNode *getParent() const { return Parent; } + inline unsigned getNumChildren() const { return Children.size(); } + inline ConcreteTreeNode *getChild(unsigned i) const { + assert(i < Children.size() && "Tree::getChild with index out of range!"); + return Children[i]; + } + + // Payload access... + inline Payload &getTreeData() { return Data; } + inline const Payload &getTreeData() const { return Data; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/Trie.h b/include/llvm/ADT/Trie.h new file mode 100644 index 0000000000000..70f3b4154d399 --- /dev/null +++ b/include/llvm/ADT/Trie.h @@ -0,0 +1,335 @@ +//===- llvm/ADT/Trie.h ---- Generic trie structure --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines a generic trie structure. The trie structure +// is immutable after creation, but the payload contained within it is not. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TRIE_H +#define LLVM_ADT_TRIE_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/DOTGraphTraits.h" + +#include <vector> + +namespace llvm { + +// FIXME: +// - Labels are usually small, maybe it's better to use SmallString +// - Should we use char* during construction? +// - Should we templatize Empty with traits-like interface? + +template<class Payload> +class Trie { + friend class GraphTraits<Trie<Payload> >; + friend class DOTGraphTraits<Trie<Payload> >; +public: + class Node { + friend class Trie; + + public: + typedef std::vector<Node*> NodeVectorType; + typedef typename NodeVectorType::iterator iterator; + typedef typename NodeVectorType::const_iterator const_iterator; + + private: + enum QueryResult { + Same = -3, + StringIsPrefix = -2, + LabelIsPrefix = -1, + DontMatch = 0, + HaveCommonPart + }; + + struct NodeCmp { + bool operator() (Node* N1, Node* N2) { + return (N1->Label[0] < N2->Label[0]); + } + bool operator() (Node* N, char Id) { + return (N->Label[0] < Id); + } + }; + + std::string Label; + Payload Data; + NodeVectorType Children; + + // Do not implement + Node(const Node&); + Node& operator=(const Node&); + + inline void addEdge(Node* N) { + if (Children.empty()) + Children.push_back(N); + else { + iterator I = std::lower_bound(Children.begin(), Children.end(), + N, NodeCmp()); + // FIXME: no dups are allowed + Children.insert(I, N); + } + } + + inline void setEdge(Node* N) { + char Id = N->Label[0]; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + assert(I != Children.end() && "Node does not exists!"); + *I = N; + } + + QueryResult query(const std::string& s) const { + unsigned i, l; + unsigned l1 = s.length(); + unsigned l2 = Label.length(); + + // Find the length of common part + l = std::min(l1, l2); + i = 0; + while ((i < l) && (s[i] == Label[i])) + ++i; + + if (i == l) { // One is prefix of another, find who is who + if (l1 == l2) + return Same; + else if (i == l1) + return StringIsPrefix; + else + return LabelIsPrefix; + } else // s and Label have common (possible empty) part, return its length + return (QueryResult)i; + } + + public: + inline explicit Node(const Payload& data, const std::string& label = ""): + Label(label), Data(data) { } + + inline const Payload& data() const { return Data; } + inline void setData(const Payload& data) { Data = data; } + + inline const std::string& label() const { return Label; } + +#if 0 + inline void dump() { + std::cerr << "Node: " << this << "\n" + << "Label: " << Label << "\n" + << "Children:\n"; + + for (iterator I = Children.begin(), E = Children.end(); I != E; ++I) + std::cerr << (*I)->Label << "\n"; + } +#endif + + inline Node* getEdge(char Id) { + Node* fNode = NULL; + iterator I = std::lower_bound(Children.begin(), Children.end(), + Id, NodeCmp()); + if (I != Children.end() && (*I)->Label[0] == Id) + fNode = *I; + + return fNode; + } + + inline iterator begin() { return Children.begin(); } + inline const_iterator begin() const { return Children.begin(); } + inline iterator end () { return Children.end(); } + inline const_iterator end () const { return Children.end(); } + + inline size_t size () const { return Children.size(); } + inline bool empty() const { return Children.empty(); } + inline const Node* &front() const { return Children.front(); } + inline Node* &front() { return Children.front(); } + inline const Node* &back() const { return Children.back(); } + inline Node* &back() { return Children.back(); } + + }; + +private: + std::vector<Node*> Nodes; + Payload Empty; + + inline Node* addNode(const Payload& data, const std::string label = "") { + Node* N = new Node(data, label); + Nodes.push_back(N); + return N; + } + + inline Node* splitEdge(Node* N, char Id, size_t index) { + Node* eNode = N->getEdge(Id); + assert(eNode && "Node doesn't exist"); + + const std::string &l = eNode->Label; + assert(index > 0 && index < l.length() && "Trying to split too far!"); + std::string l1 = l.substr(0, index); + std::string l2 = l.substr(index); + + Node* nNode = addNode(Empty, l1); + N->setEdge(nNode); + + eNode->Label = l2; + nNode->addEdge(eNode); + + return nNode; + } + + // Do not implement + Trie(const Trie&); + Trie& operator=(const Trie&); + +public: + inline explicit Trie(const Payload& empty):Empty(empty) { + addNode(Empty); + } + inline ~Trie() { + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + delete Nodes[i]; + } + + inline Node* getRoot() const { return Nodes[0]; } + + bool addString(const std::string& s, const Payload& data); + const Payload& lookup(const std::string& s) const; + +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template<class Payload> +bool Trie<Payload>::addString(const std::string& s, const Payload& data) { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + case Node::StringIsPrefix: + // Currently we don't allow to have two strings in the trie one + // being a prefix of another. This should be fixed. + assert(0 && "FIXME!"); + return false; + case Node::DontMatch: + assert(0 && "Impossible!"); + return false; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + nNode = splitEdge(cNode, Id, r); + tNode = addNode(data, s1.substr(r)); + nNode->addEdge(tNode); + } + } else { + tNode = addNode(data, s1); + cNode->addEdge(tNode); + } + } + + return true; +} + +template<class Payload> +const Payload& Trie<Payload>::lookup(const std::string& s) const { + Node* cNode = getRoot(); + Node* tNode = NULL; + std::string s1(s); + + while (tNode == NULL) { + char Id = s1[0]; + if (Node* nNode = cNode->getEdge(Id)) { + typename Node::QueryResult r = nNode->query(s1); + + switch (r) { + case Node::Same: + tNode = nNode; + break; + case Node::StringIsPrefix: + return Empty; + case Node::DontMatch: + assert(0 && "Impossible!"); + return Empty; + case Node::LabelIsPrefix: + s1 = s1.substr(nNode->label().length()); + cNode = nNode; + break; + default: + return Empty; + } + } else + return Empty; + } + + return tNode->data(); +} + +template<class Payload> +struct GraphTraits<Trie<Payload> > { + typedef Trie<Payload> TrieType; + typedef typename TrieType::Node NodeType; + typedef typename NodeType::iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const TrieType& T) { + return T.getRoot(); + } + + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + + typedef typename std::vector<NodeType*>::const_iterator nodes_iterator; + + static inline nodes_iterator nodes_begin(const TrieType& G) { + return G.Nodes.begin(); + } + static inline nodes_iterator nodes_end(const TrieType& G) { + return G.Nodes.end(); + } + +}; + +template<class Payload> +struct DOTGraphTraits<Trie<Payload> > : public DefaultDOTGraphTraits { + typedef typename Trie<Payload>::Node NodeType; + typedef typename GraphTraits<Trie<Payload> >::ChildIteratorType EdgeIter; + + static std::string getGraphName(const Trie<Payload>& T) { + return "Trie"; + } + + static std::string getNodeLabel(NodeType* Node, const Trie<Payload>& T) { + if (T.getRoot() == Node) + return "<Root>"; + else + return Node->label(); + } + + static std::string getEdgeSourceLabel(NodeType* Node, EdgeIter I) { + NodeType* N = *I; + return N->label().substr(0, 1); + } + + static std::string getNodeAttributes(const NodeType* Node, + const Trie<Payload>& T) { + if (Node->data() != T.Empty) + return "color=blue"; + + return ""; + } + +}; + +} // end of llvm namespace + +#endif // LLVM_ADT_TRIE_H diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h new file mode 100644 index 0000000000000..b260f984948ed --- /dev/null +++ b/include/llvm/ADT/Triple.h @@ -0,0 +1,204 @@ +//===-- llvm/ADT/Triple.h - Target triple helper class ----------*- 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_TRIPLE_H +#define LLVM_ADT_TRIPLE_H + +#include <string> + +namespace llvm { + +/// Triple - Helper class for working with target triples. +/// +/// Target triples are strings in the format of: +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM +/// or +/// ARCHITECTURE-VENDOR-OPERATING_SYSTEM-ENVIRONMENT +/// +/// This class is used for clients which want to support arbitrary +/// target triples, but also want to implement certain special +/// behavior for particular targets. This class isolates the mapping +/// from the components of the target triple to well known IDs. +/// +/// See autoconf/config.guess for a glimpse into what they look like +/// in practice. +class Triple { +public: + enum ArchType { + UnknownArch, + + x86, // i?86 + ppc, // powerpc + ppc64, // powerpc64 + x86_64, // amd64, x86_64 + + InvalidArch + }; + enum VendorType { + UnknownVendor, + + Apple, + PC + }; + enum OSType { + UnknownOS, + + Darwin, + DragonFly, + FreeBSD, + Linux + }; + +private: + std::string Data; + + /// The parsed arch type (or InvalidArch if uninitialized). + mutable ArchType Arch; + + /// The parsed vendor type. + mutable VendorType Vendor; + + /// The parsed OS type. + mutable OSType OS; + + bool isInitialized() const { return Arch != InvalidArch; } + void Parse() const; + +public: + /// @name Constructors + /// @{ + + Triple() : Data(""), Arch(InvalidArch) {} + explicit Triple(const char *Str) : Data(Str), Arch(InvalidArch) {} + explicit Triple(const char *ArchStr, const char *VendorStr, const char *OSStr) + : Data(ArchStr), Arch(InvalidArch) { + Data += '-'; + Data += VendorStr; + Data += '-'; + Data += OSStr; + } + + /// @} + /// @name Typed Component Access + /// @{ + + /// getArch - Get the parsed architecture type of this triple. + ArchType getArch() const { + if (!isInitialized()) Parse(); + return Arch; + } + + /// getVendor - Get the parsed vendor type of this triple. + VendorType getVendor() const { + if (!isInitialized()) Parse(); + return Vendor; + } + + /// getOS - Get the parsed operating system type of this triple. + OSType getOS() const { + if (!isInitialized()) Parse(); + return OS; + } + + /// hasEnvironment - Does this triple have the optional environment + /// (fourth) component? + bool hasEnvironment() const { + return getEnvironmentName() != ""; + } + + /// @} + /// @name Direct Component Access + /// @{ + + const std::string &getTriple() const { return Data; } + + // FIXME: Invent a lightweight string representation for these to + // use. + + /// getArchName - Get the architecture (first) component of the + /// triple. + std::string getArchName() const; + + /// getVendorName - Get the vendor (second) component of the triple. + std::string getVendorName() const; + + /// getOSName - Get the operating system (third) component of the + /// triple. + std::string getOSName() const; + + /// getEnvironmentName - Get the optional environment (fourth) + /// component of the triple, or "" if empty. + std::string getEnvironmentName() const; + + /// getOSAndEnvironmentName - Get the operating system and optional + /// environment components as a single string (separated by a '-' + /// if the environment component is present). + std::string getOSAndEnvironmentName() const; + + /// @} + /// @name Mutators + /// @{ + + /// setArch - Set the architecture (first) component of the triple + /// to a known type. + void setArch(ArchType Kind); + + /// setVendor - Set the vendor (second) component of the triple to a + /// known type. + void setVendor(VendorType Kind); + + /// setOS - Set the operating system (third) component of the triple + /// to a known type. + void setOS(OSType Kind); + + /// setTriple - Set all components to the new triple \arg Str. + void setTriple(const std::string &Str); + + /// setArchName - Set the architecture (first) component of the + /// triple by name. + void setArchName(const std::string &Str); + + /// setVendorName - Set the vendor (second) component of the triple + /// by name. + void setVendorName(const std::string &Str); + + /// setOSName - Set the operating system (third) component of the + /// triple by name. + void setOSName(const std::string &Str); + + /// setEnvironmentName - Set the optional environment (fourth) + /// component of the triple by name. + void setEnvironmentName(const std::string &Str); + + /// setOSAndEnvironmentName - Set the operating system and optional + /// environment components with a single string. + void setOSAndEnvironmentName(const std::string &Str); + + /// @} + /// @name Static helpers for IDs. + /// @{ + + /// getArchTypeName - Get the canonical name for the \arg Kind + /// architecture. + static const char *getArchTypeName(ArchType Kind); + + /// getVendorTypeName - Get the canonical name for the \arg Kind + /// vendor. + static const char *getVendorTypeName(VendorType Kind); + + /// getOSTypeName - Get the canonical name for the \arg Kind vendor. + static const char *getOSTypeName(OSType Kind); + + /// @} +}; + +} // End llvm namespace + + +#endif diff --git a/include/llvm/ADT/UniqueVector.h b/include/llvm/ADT/UniqueVector.h new file mode 100644 index 0000000000000..2d02d1ce166fa --- /dev/null +++ b/include/llvm/ADT/UniqueVector.h @@ -0,0 +1,89 @@ +//===-- llvm/ADT/UniqueVector.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_UNIQUEVECTOR_H +#define LLVM_ADT_UNIQUEVECTOR_H + +#include <cassert> +#include <map> +#include <vector> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// UniqueVector - This class produces a sequential ID number (base 1) for each +/// unique entry that is added. T is the type of entries in the vector. This +/// class should have an implementation of operator== and of operator<. +/// Entries can be fetched using operator[] with the entry ID. +template<class T> class UniqueVector { +private: + // Map - Used to handle the correspondence of entry to ID. + std::map<T, unsigned> Map; + + // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. + // + std::vector<T> Vector; + +public: + /// insert - Append entry to the vector if it doesn't already exist. Returns + /// the entry's index + 1 to be used as a unique ID. + unsigned insert(const T &Entry) { + // Check if the entry is already in the map. + unsigned &Val = Map[Entry]; + + // See if entry exists, if so return prior ID. + if (Val) return Val; + + // Compute ID for entry. + Val = static_cast<unsigned>(Vector.size()) + 1; + + // Insert in vector. + Vector.push_back(Entry); + return Val; + } + + /// idFor - return the ID for an existing entry. Returns 0 if the entry is + /// not found. + unsigned idFor(const T &Entry) const { + // Search for entry in the map. + typename std::map<T, unsigned>::const_iterator MI = Map.find(Entry); + + // See if entry exists, if so return ID. + if (MI != Map.end()) return MI->second; + + // No luck. + return 0; + } + + /// operator[] - Returns a reference to the entry with the specified ID. + /// + const T &operator[](unsigned ID) const { + assert(ID-1 < size() && "ID is 0 or out of range!"); + return Vector[ID - 1]; + } + + /// size - Returns the number of entries in the vector. + /// + size_t size() const { return Vector.size(); } + + /// empty - Returns true if the vector is empty. + /// + bool empty() const { return Vector.empty(); } + + /// reset - Clears all the entries. + /// + void reset() { + Map.clear(); + Vector.resize(0, 0); + } +}; + +} // End of namespace llvm + +#endif // LLVM_ADT_UNIQUEVECTOR_H diff --git a/include/llvm/ADT/VectorExtras.h b/include/llvm/ADT/VectorExtras.h new file mode 100644 index 0000000000000..e05f585996f9a --- /dev/null +++ b/include/llvm/ADT/VectorExtras.h @@ -0,0 +1,41 @@ +//===-- llvm/ADT/VectorExtras.h - Helpers for std::vector -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains helper functions which are useful for working with the +// std::vector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VECTOREXTRAS_H +#define LLVM_ADT_VECTOREXTRAS_H + +#include <cstdarg> +#include <vector> + +namespace llvm { + +/// make_vector - Helper function which is useful for building temporary vectors +/// to pass into type construction of CallInst ctors. This turns a null +/// terminated list of pointers (or other value types) into a real live vector. +/// +template<typename T> +inline std::vector<T> make_vector(T A, ...) { + va_list Args; + va_start(Args, A); + std::vector<T> Result; + Result.push_back(A); + while (T Val = va_arg(Args, T)) + Result.push_back(Val); + va_end(Args); + return Result; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h new file mode 100644 index 0000000000000..9eb70055284af --- /dev/null +++ b/include/llvm/ADT/ilist.h @@ -0,0 +1,709 @@ +//==-- llvm/ADT/ilist.h - Intrusive Linked List Template ---------*- 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 classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist_traits trait class is used to gain access to the next and previous +// fields of the node type that the list is instantiated with. If it is not +// specialized, the list defaults to using the getPrev(), getNext() method calls +// to get the next and previous pointers. +// +// The ilist class itself, should be a plug in replacement for list, assuming +// that the nodes contain next/prev pointers. This list replacement does not +// provide a constant time size() method, so be careful to use empty() when you +// really want to know if it's empty. +// +// The ilist class is implemented by allocating a 'tail' node when the list is +// created (using ilist_traits<>::createSentinel()). This tail node is +// absolutely required because the user must be able to compute end()-1. Because +// of this, users of the direct next/prev links will see an extra link on the +// end of the list, which should be ignored. +// +// Requirements for a user of this list: +// +// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize +// ilist_traits to provide an alternate way of getting and setting next and +// prev links. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_H +#define LLVM_ADT_ILIST_H + +#include "llvm/ADT/iterator.h" +#include <cassert> + +namespace llvm { + +template<typename NodeTy, typename Traits> class iplist; +template<typename NodeTy> class ilist_iterator; + +/// ilist_nextprev_traits - A fragment for template traits for intrusive list +/// that provides default next/prev implementations for common operations. +/// +template<typename NodeTy> +struct ilist_nextprev_traits { + static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } + static NodeTy *getNext(NodeTy *N) { return N->getNext(); } + static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } + static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } + + static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } + static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } +}; + +template<typename NodeTy> +struct ilist_traits; + +/// ilist_sentinel_traits - A fragment for template traits for intrusive list +/// that provides default sentinel implementations for common operations. +/// +/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation +/// strategy. The sentinel is stored in the prev field of ilist's Head. +/// +template<typename NodeTy> +struct ilist_sentinel_traits { + /// createSentinel - create the dynamic sentinel + static NodeTy *createSentinel() { return new NodeTy(); } + + /// destroySentinel - deallocate the dynamic sentinel + static void destroySentinel(NodeTy *N) { delete N; } + + /// provideInitialHead - when constructing an ilist, provide a starting + /// value for its Head + /// @return null node to indicate that it needs to be allocated later + static NodeTy *provideInitialHead() { return 0; } + + /// ensureHead - make sure that Head is either already + /// initialized or assigned a fresh sentinel + /// @return the sentinel + static NodeTy *ensureHead(NodeTy *&Head) { + if (!Head) { + Head = ilist_traits<NodeTy>::createSentinel(); + ilist_traits<NodeTy>::noteHead(Head, Head); + ilist_traits<NodeTy>::setNext(Head, 0); + return Head; + } + return ilist_traits<NodeTy>::getPrev(Head); + } + + /// noteHead - stash the sentinel into its default location + static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) { + ilist_traits<NodeTy>::setPrev(NewHead, Sentinel); + } +}; + +/// ilist_node_traits - A fragment for template traits for intrusive list +/// that provides default node related operations. +/// +template<typename NodeTy> +struct ilist_node_traits { + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + static void deleteNode(NodeTy *V) { delete V; } + + void addNodeToList(NodeTy *) {} + void removeNodeFromList(NodeTy *) {} + void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, + ilist_iterator<NodeTy> /*first*/, + ilist_iterator<NodeTy> /*last*/) {} +}; + +/// ilist_default_traits - Default template traits for intrusive list. +/// By inheriting from this, you can easily use default implementations +/// for all common operations. +/// +template<typename NodeTy> +struct ilist_default_traits : ilist_nextprev_traits<NodeTy>, + ilist_sentinel_traits<NodeTy>, + ilist_node_traits<NodeTy> { +}; + +// Template traits for intrusive list. By specializing this template class, you +// can change what next/prev fields are used to store the links... +template<typename NodeTy> +struct ilist_traits : ilist_default_traits<NodeTy> {}; + +// Const traits are the same as nonconst traits... +template<typename Ty> +struct ilist_traits<const Ty> : public ilist_traits<Ty> {}; + +//===----------------------------------------------------------------------===// +// ilist_iterator<Node> - Iterator for intrusive list. +// +template<typename NodeTy> +class ilist_iterator + : public bidirectional_iterator<NodeTy, ptrdiff_t> { + +public: + typedef ilist_traits<NodeTy> Traits; + typedef bidirectional_iterator<NodeTy, ptrdiff_t> super; + + typedef typename super::value_type value_type; + typedef typename super::difference_type difference_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; +private: + pointer NodePtr; + + // ilist_iterator is not a random-access iterator, but it has an + // implicit conversion to pointer-type, which is. Declare (but + // don't define) these functions as private to help catch + // accidental misuse. + void operator[](difference_type) const; + void operator+(difference_type) const; + void operator-(difference_type) const; + void operator+=(difference_type) const; + void operator-=(difference_type) const; + template<class T> void operator<(T) const; + template<class T> void operator<=(T) const; + template<class T> void operator>(T) const; + template<class T> void operator>=(T) const; + template<class T> void operator-(T) const; +public: + + ilist_iterator(pointer NP) : NodePtr(NP) {} + ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(0) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template<class node_ty> + ilist_iterator(const ilist_iterator<node_ty> &RHS) + : NodePtr(RHS.getNodePtrUnchecked()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template<class node_ty> + const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) { + NodePtr = RHS.getNodePtrUnchecked(); + return *this; + } + + // Accessors... + operator pointer() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return NodePtr; + } + + reference operator*() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return *NodePtr; + } + pointer operator->() const { return &operator*(); } + + // Comparison operators + bool operator==(const ilist_iterator &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const ilist_iterator &RHS) const { + return NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { // predecrement - Back up + NodePtr = Traits::getPrev(NodePtr); + assert(NodePtr && "--'d off the beginning of an ilist!"); + return *this; + } + ilist_iterator &operator++() { // preincrement - Advance + NodePtr = Traits::getNext(NodePtr); + assert(NodePtr && "++'d off the end of an ilist!"); + return *this; + } + ilist_iterator operator--(int) { // postdecrement operators... + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { // postincrement operators... + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + // Internal interface, do not use... + pointer getNodePtrUnchecked() const { return NodePtr; } +}; + +// do not implement. this is to catch errors when people try to use +// them as random access iterators +template<typename T> +void operator-(int, ilist_iterator<T>); +template<typename T> +void operator-(ilist_iterator<T>,int); + +template<typename T> +void operator+(int, ilist_iterator<T>); +template<typename T> +void operator+(ilist_iterator<T>,int); + +// operator!=/operator== - Allow mixed comparisons without dereferencing +// the iterator, which could very likely be pointing to end(). +template<typename T> +bool operator!=(const T* LHS, const ilist_iterator<const T> &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator==(const T* LHS, const ilist_iterator<const T> &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator!=(T* LHS, const ilist_iterator<T> &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator==(T* LHS, const ilist_iterator<T> &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} + + +// Allow ilist_iterators to convert into pointers to a node automatically when +// used by the dyn_cast, cast, isa mechanisms... + +template<typename From> struct simplify_type; + +template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; +template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; + + +//===----------------------------------------------------------------------===// +// +/// iplist - The subset of list functionality that can safely be used on nodes +/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// holds the next/prev pointers. The only state of the list itself is a single +/// pointer to the head of the list. +/// +/// This list can be in one of three interesting states: +/// 1. The list may be completely unconstructed. In this case, the head +/// pointer is null. When in this form, any query for an iterator (e.g. +/// begin() or end()) causes the list to transparently change to state #2. +/// 2. The list may be empty, but contain a sentinel for the end iterator. This +/// sentinel is created by the Traits::createSentinel method and is a link +/// in the list. When the list is empty, the pointer in the iplist points +/// to the sentinel. Once the sentinel is constructed, it +/// is not destroyed until the list is. +/// 3. The list may contain actual objects in it, which are stored as a doubly +/// linked list of nodes. One invariant of the list is that the predecessor +/// of the first node in the list always points to the last node in the list, +/// and the successor pointer for the sentinel (which always stays at the +/// end of the list) is always null. +/// +template<typename NodeTy, typename Traits=ilist_traits<NodeTy> > +class iplist : public Traits { + mutable NodeTy *Head; + + // Use the prev node pointer of 'head' as the tail pointer. This is really a + // circularly linked list where we snip the 'next' link from the sentinel node + // back to the first node in the list (to preserve assertions about going off + // the end of the list). + NodeTy *getTail() { return this->ensureHead(Head); } + const NodeTy *getTail() const { return this->ensureHead(Head); } + void setTail(NodeTy *N) const { this->noteHead(Head, N); } + + /// CreateLazySentinel - This method verifies whether the sentinel for the + /// list has been created and lazily makes it if not. + void CreateLazySentinel() const { + this->Traits::ensureHead(Head); + } + + static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } + static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } + + // No fundamental reason why iplist can't by copyable, but the default + // copy/copy-assign won't do. + iplist(const iplist &); // do not implement + void operator=(const iplist &); // do not implement + +public: + typedef NodeTy *pointer; + typedef const NodeTy *const_pointer; + typedef NodeTy &reference; + typedef const NodeTy &const_reference; + typedef NodeTy value_type; + typedef ilist_iterator<NodeTy> iterator; + typedef ilist_iterator<const NodeTy> const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + iplist() : Head(this->Traits::provideInitialHead()) {} + ~iplist() { + if (!Head) return; + clear(); + Traits::destroySentinel(getTail()); + } + + // Iterator creation methods. + iterator begin() { + CreateLazySentinel(); + return iterator(Head); + } + const_iterator begin() const { + CreateLazySentinel(); + return const_iterator(Head); + } + iterator end() { + CreateLazySentinel(); + return iterator(getTail()); + } + const_iterator end() const { + CreateLazySentinel(); + return const_iterator(getTail()); + } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + bool empty() const { return Head == 0 || Head == getTail(); } + + // Front and back accessor functions... + reference front() { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + const_reference front() const { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + reference back() { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + const_reference back() const { + assert(!empty() && "Called back() on empty list!"); + return *this->getPrev(getTail()); + } + + void swap(iplist &RHS) { + assert(0 && "Swap does not use list traits callback correctly yet!"); + std::swap(Head, RHS.Head); + } + + iterator insert(iterator where, NodeTy *New) { + NodeTy *CurNode = where.getNodePtrUnchecked(); + NodeTy *PrevNode = this->getPrev(CurNode); + this->setNext(New, CurNode); + this->setPrev(New, PrevNode); + + if (CurNode != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, New); + else + Head = New; + this->setPrev(CurNode, New); + + this->addNodeToList(New); // Notify traits that we added a node... + return New; + } + + iterator insertAfter(iterator where, NodeTy *New) { + if (empty()) + return insert(begin(), New); + else + return insert(++where, New); + } + + NodeTy *remove(iterator &IT) { + assert(IT != end() && "Cannot remove end of list!"); + NodeTy *Node = &*IT; + NodeTy *NextNode = this->getNext(Node); + NodeTy *PrevNode = this->getPrev(Node); + + if (Node != Head) // Is PrevNode off the beginning of the list? + this->setNext(PrevNode, NextNode); + else + Head = NextNode; + this->setPrev(NextNode, PrevNode); + IT = NextNode; + this->removeNodeFromList(Node); // Notify traits that we removed a node... + + // Set the next/prev pointers of the current node to null. This isn't + // strictly required, but this catches errors where a node is removed from + // an ilist (and potentially deleted) with iterators still pointing at it. + // When those iterators are incremented or decremented, they will assert on + // the null next/prev pointer instead of "usually working". + this->setNext(Node, 0); + this->setPrev(Node, 0); + return Node; + } + + NodeTy *remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + this->deleteNode(remove(where)); + return where; + } + + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist &L2, iterator first, iterator last) { + assert(first != last && "Should be checked by callers"); + + if (position != last) { + // Note: we have to be careful about the case when we move the first node + // in the list. This node is the list sentinel node and we can't move it. + NodeTy *ThisSentinel = getTail(); + setTail(0); + NodeTy *L2Sentinel = L2.getTail(); + L2.setTail(0); + + // Remove [first, last) from its old position. + NodeTy *First = &*first, *Prev = getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); + if (Prev) + this->setNext(Prev, Next); + else + L2.Head = Next; + this->setPrev(Next, Prev); + + // Splice [first, last) into its new position. + NodeTy *PosNext = position.getNodePtrUnchecked(); + NodeTy *PosPrev = getPrev(PosNext); + + // Fix head of list... + if (PosPrev) + this->setNext(PosPrev, First); + else + Head = First; + this->setPrev(First, PosPrev); + + // Fix end of list... + this->setNext(Last, PosNext); + this->setPrev(PosNext, Last); + + transferNodesFromList(L2, First, PosNext); + + // Now that everything is set, restore the pointers to the list sentinels. + L2.setTail(L2Sentinel); + setTail(ThisSentinel); + } + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + size_type size() const { + if (Head == 0) return 0; // Don't require construction of sentinel if empty. + return std::distance(begin(), end()); + } + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { if (Head) erase(begin(), end()); } + + // Front and back inserters... + void push_front(NodeTy *val) { insert(begin(), val); } + void push_back(NodeTy *val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + + + + //===----------------------------------------------------------------------=== + // High-Level Functionality that shouldn't really be here, but is part of list + // + + // These two functions are actually called remove/remove_if in list<>, but + // they actually do the job of erase, rename them accordingly. + // + void erase(const NodeTy &val) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (*I == val) erase(I); + I = next; + } + } + template<class Pr1> void erase_if(Pr1 pred) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (pred(*I)) erase(I); + I = next; + } + } + + template<class Pr2> void unique(Pr2 pred) { + if (empty()) return; + for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { + if (pred(*I)) + erase(Next); + else + I = Next; + Next = I; + } + } + void unique() { unique(op_equal); } + + template<class Pr3> void merge(iplist &right, Pr3 pred) { + iterator first1 = begin(), last1 = end(); + iterator first2 = right.begin(), last2 = right.end(); + while (first1 != last1 && first2 != last2) + if (pred(*first2, *first1)) { + iterator next = first2; + transfer(first1, right, first2, ++next); + first2 = next; + } else { + ++first1; + } + if (first2 != last2) transfer(last1, right, first2, last2); + } + void merge(iplist &right) { return merge(right, op_less); } + + template<class Pr3> void sort(Pr3 pred); + void sort() { sort(op_less); } + void reverse(); +}; + + +template<typename NodeTy> +struct ilist : public iplist<NodeTy> { + typedef typename iplist<NodeTy>::size_type size_type; + typedef typename iplist<NodeTy>::iterator iterator; + + ilist() {} + ilist(const ilist &right) { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, NodeTy()); + } + ilist(size_type count, const NodeTy &val) { + insert(this->begin(), count, val); + } + template<class InIt> ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + // bring hidden functions into scope + using iplist<NodeTy>::insert; + using iplist<NodeTy>::push_front; + using iplist<NodeTy>::push_back; + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const NodeTy &val) { + return insert(where, createNode(val)); + } + + + // Front and back inserters... + void push_front(const NodeTy &val) { insert(this->begin(), val); } + void push_back(const NodeTy &val) { insert(this->end(), val); } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + void insert(iterator where, size_type count, const NodeTy &val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const NodeTy &val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template<class InIt> void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, NodeTy val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, NodeTy()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template<class Ty> + void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif // LLVM_ADT_ILIST_H diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h new file mode 100644 index 0000000000000..dae7475ffa012 --- /dev/null +++ b/include/llvm/ADT/ilist_node.h @@ -0,0 +1,47 @@ +//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ilist_node class template, which is a convenient +// base class for creating classes that can be used with ilists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H + +namespace llvm { + +template<typename NodeTy> +struct ilist_nextprev_traits; + +template<typename NodeTy> +struct ilist_traits; + +/// ilist_node - Base class that provides next/prev services for nodes +/// that use ilist_nextprev_traits or ilist_default_traits. +/// +template<typename NodeTy> +class ilist_node { +private: + friend struct ilist_nextprev_traits<NodeTy>; + friend struct ilist_traits<NodeTy>; + NodeTy *Prev, *Next; + NodeTy *getPrev() { return Prev; } + NodeTy *getNext() { return Next; } + const NodeTy *getPrev() const { return Prev; } + const NodeTy *getNext() const { return Next; } + void setPrev(NodeTy *N) { Prev = N; } + void setNext(NodeTy *N) { Next = N; } +protected: + ilist_node() : Prev(0), Next(0) {} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/iterator.cmake b/include/llvm/ADT/iterator.cmake new file mode 100644 index 0000000000000..55df8ce2643e5 --- /dev/null +++ b/include/llvm/ADT/iterator.cmake @@ -0,0 +1,79 @@ +//===-- llvm/ADT/iterator - Portable wrapper around <iterator> --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious <iterator> header file. +// In GCC 2.95.3, the file defines a bidirectional_iterator class (and other +// friends), instead of the standard iterator class. In GCC 3.1, the +// bidirectional_iterator class got moved out and the new, standards compliant, +// iterator<> class was added. Because there is nothing that we can do to get +// correct behavior on both compilers, we have this header with #ifdef's. Gross +// huh? +// +// By #includ'ing this file, you get the contents of <iterator> plus the +// following classes in the global namespace: +// +// 1. bidirectional_iterator +// 2. forward_iterator +// +// The #if directives' expressions are filled in by Autoconf. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR +#define LLVM_ADT_ITERATOR + +#include <iterator> + +#undef HAVE_BI_ITERATOR +#undef HAVE_STD_ITERATOR +#undef HAVE_FWD_ITERATOR + +// defined by Kevin +#define HAVE_STD_ITERATOR 1 + +#ifdef _MSC_VER +# define HAVE_BI_ITERATOR 0 +# define HAVE_STD_ITERATOR 1 +# define HAVE_FWD_ITERATOR 0 +#endif + +#if !HAVE_BI_ITERATOR +# if HAVE_STD_ITERATOR +/// If the bidirectional iterator is not defined, we attempt to define it in +/// terms of the C++ standard iterator. Otherwise, we import it with a "using" +/// statement. +/// +template<class Ty, class PtrDiffTy> +struct bidirectional_iterator + : public std::iterator<std::bidirectional_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define bidirectional iterator!" +# endif +#else +using std::bidirectional_iterator; +#endif + +#if !HAVE_FWD_ITERATOR +# if HAVE_STD_ITERATOR +/// If the forward iterator is not defined, attempt to define it in terms of +/// the C++ standard iterator. Otherwise, we import it with a "using" statement. +/// +template<class Ty, class PtrDiffTy> +struct forward_iterator + : public std::iterator<std::forward_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define forward iterator!" +# endif +#else +using std::forward_iterator; +#endif + +#endif diff --git a/include/llvm/ADT/iterator.h.in b/include/llvm/ADT/iterator.h.in new file mode 100644 index 0000000000000..dce74625118b3 --- /dev/null +++ b/include/llvm/ADT/iterator.h.in @@ -0,0 +1,76 @@ +//==-- llvm/ADT/iterator.h - Portable wrapper around <iterator> --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious <iterator> header file. +// In GCC 2.95.3, the file defines a bidirectional_iterator class (and other +// friends), instead of the standard iterator class. In GCC 3.1, the +// bidirectional_iterator class got moved out and the new, standards compliant, +// iterator<> class was added. Because there is nothing that we can do to get +// correct behavior on both compilers, we have this header with #ifdef's. Gross +// huh? +// +// By #includ'ing this file, you get the contents of <iterator> plus the +// following classes in the global namespace: +// +// 1. bidirectional_iterator +// 2. forward_iterator +// +// The #if directives' expressions are filled in by Autoconf. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_H +#define LLVM_ADT_ITERATOR_H + +#include <iterator> + +#undef HAVE_BI_ITERATOR +#undef HAVE_STD_ITERATOR +#undef HAVE_FWD_ITERATOR + +#ifdef _MSC_VER +# define HAVE_BI_ITERATOR 0 +# define HAVE_STD_ITERATOR 1 +# define HAVE_FWD_ITERATOR 0 +#endif + +#if !HAVE_BI_ITERATOR +# if HAVE_STD_ITERATOR +/// If the bidirectional iterator is not defined, we attempt to define it in +/// terms of the C++ standard iterator. Otherwise, we import it with a "using" +/// statement. +/// +template<class Ty, class PtrDiffTy> +struct bidirectional_iterator + : public std::iterator<std::bidirectional_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define bidirectional iterator!" +# endif +#else +using std::bidirectional_iterator; +#endif + +#if !HAVE_FWD_ITERATOR +# if HAVE_STD_ITERATOR +/// If the forward iterator is not defined, attempt to define it in terms of +/// the C++ standard iterator. Otherwise, we import it with a "using" statement. +/// +template<class Ty, class PtrDiffTy> +struct forward_iterator + : public std::iterator<std::forward_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define forward iterator!" +# endif +#else +using std::forward_iterator; +#endif + +#endif // LLVM_ADT_ITERATOR_H |