initial
This commit is contained in:
466
thirdparty/clang/include/llvm/ADT/APFloat.h
vendored
Normal file
466
thirdparty/clang/include/llvm/ADT/APFloat.h
vendored
Normal file
@@ -0,0 +1,466 @@
|
||||
//== 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_ADT_APFLOAT_H
|
||||
#define LLVM_ADT_APFLOAT_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;
|
||||
class APSInt;
|
||||
class StringRef;
|
||||
|
||||
/* 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 IEEEhalf;
|
||||
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
|
||||
};
|
||||
|
||||
enum uninitializedTag {
|
||||
uninitialized
|
||||
};
|
||||
|
||||
// Constructors.
|
||||
APFloat(const fltSemantics &); // Default construct to 0.0
|
||||
APFloat(const fltSemantics &, StringRef);
|
||||
APFloat(const fltSemantics &, integerPart);
|
||||
APFloat(const fltSemantics &, fltCategory, bool negative);
|
||||
APFloat(const fltSemantics &, uninitializedTag);
|
||||
APFloat(const fltSemantics &, const APInt &);
|
||||
explicit APFloat(double d);
|
||||
explicit APFloat(float f);
|
||||
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) {
|
||||
if (type) {
|
||||
APInt fill(64, type);
|
||||
return getQNaN(Sem, Negative, &fill);
|
||||
} else {
|
||||
return getQNaN(Sem, Negative, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// getQNan - Factory for QNaN values.
|
||||
static APFloat getQNaN(const fltSemantics &Sem,
|
||||
bool Negative = false,
|
||||
const APInt *payload = 0) {
|
||||
return makeNaN(Sem, false, Negative, payload);
|
||||
}
|
||||
|
||||
/// getSNan - Factory for SNaN values.
|
||||
static APFloat getSNaN(const fltSemantics &Sem,
|
||||
bool Negative = false,
|
||||
const APInt *payload = 0) {
|
||||
return makeNaN(Sem, true, Negative, payload);
|
||||
}
|
||||
|
||||
/// getLargest - Returns the largest finite number in the given
|
||||
/// semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getLargest(const fltSemantics &Sem, bool Negative = false);
|
||||
|
||||
/// getSmallest - Returns the smallest (by magnitude) finite number
|
||||
/// in the given semantics. Might be denormalized, which implies a
|
||||
/// relative loss of precision.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false);
|
||||
|
||||
/// getSmallestNormalized - Returns the smallest (by magnitude)
|
||||
/// normalized finite number in the given semantics.
|
||||
///
|
||||
/// \param Negative - True iff the number should be negative
|
||||
static APFloat getSmallestNormalized(const fltSemantics &Sem,
|
||||
bool Negative = false);
|
||||
|
||||
/// getAllOnesValue - Returns a float which is bitcasted from
|
||||
/// an all one value int.
|
||||
///
|
||||
/// \param BitWidth - Select float type
|
||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
||||
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
|
||||
|
||||
/// Profile - Used to insert APFloat objects, or objects that contain
|
||||
/// APFloat objects, into FoldingSets.
|
||||
void Profile(FoldingSetNodeID& NID) const;
|
||||
|
||||
/// @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);
|
||||
opStatus roundToIntegral(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 convertToInteger(APSInt&, 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(StringRef, 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 LLVM_DELETED_FUNCTION;
|
||||
|
||||
/* 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 isNormal() const { return category == fcNormal; }
|
||||
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(); }
|
||||
bool isDenormal() const;
|
||||
|
||||
APFloat& operator=(const APFloat &);
|
||||
|
||||
/// \brief Overload to compute a hash code for an APFloat value.
|
||||
///
|
||||
/// Note that the use of hash codes for floating point values is in general
|
||||
/// frought with peril. Equality is hard to define for these values. For
|
||||
/// example, should negative and positive zero hash to different codes? Are
|
||||
/// they equal or not? This hash value implementation specifically
|
||||
/// emphasizes producing different codes for different inputs in order to
|
||||
/// be used in canonicalization and memoization. As such, equality is
|
||||
/// bitwiseIsEqual, and 0 != -0.
|
||||
friend hash_code hash_value(const APFloat &Arg);
|
||||
|
||||
/// Converts this value into a decimal string.
|
||||
///
|
||||
/// \param FormatPrecision The maximum number of digits of
|
||||
/// precision to output. If there are fewer digits available,
|
||||
/// zero padding will not be used unless the value is
|
||||
/// integral and small enough to be expressed in
|
||||
/// FormatPrecision digits. 0 means to use the natural
|
||||
/// precision of the number.
|
||||
/// \param FormatMaxPadding The maximum number of zeros to
|
||||
/// consider inserting before falling back to scientific
|
||||
/// notation. 0 means to always use scientific notation.
|
||||
///
|
||||
/// Number Precision MaxPadding Result
|
||||
/// ------ --------- ---------- ------
|
||||
/// 1.01E+4 5 2 10100
|
||||
/// 1.01E+4 4 2 1.01E+4
|
||||
/// 1.01E+4 5 1 1.01E+4
|
||||
/// 1.01E-2 5 2 0.0101
|
||||
/// 1.01E-2 4 2 0.0101
|
||||
/// 1.01E-2 4 1 1.01E-2
|
||||
void toString(SmallVectorImpl<char> &Str,
|
||||
unsigned FormatPrecision = 0,
|
||||
unsigned FormatMaxPadding = 3) const;
|
||||
|
||||
/// getExactInverse - If this value has an exact multiplicative inverse,
|
||||
/// store it in inv and return true.
|
||||
bool getExactInverse(APFloat *inv) 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. */
|
||||
static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
|
||||
const APInt *fill);
|
||||
void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 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(StringRef, roundingMode);
|
||||
opStatus convertFromDecimalString(StringRef, roundingMode);
|
||||
char *convertNormalToHexString(char *, unsigned int, bool,
|
||||
roundingMode) const;
|
||||
opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
|
||||
int, roundingMode);
|
||||
|
||||
APInt convertHalfAPFloatToAPInt() const;
|
||||
APInt convertFloatAPFloatToAPInt() const;
|
||||
APInt convertDoubleAPFloatToAPInt() const;
|
||||
APInt convertQuadrupleAPFloatToAPInt() const;
|
||||
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
||||
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
|
||||
void initFromAPInt(const fltSemantics *Sem, const APInt& api);
|
||||
void initFromHalfAPInt(const APInt& api);
|
||||
void initFromFloatAPInt(const APInt& api);
|
||||
void initFromDoubleAPInt(const APInt& api);
|
||||
void initFromQuadrupleAPInt(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;
|
||||
};
|
||||
|
||||
// See friend declaration above. This additional declaration is required in
|
||||
// order to compile LLVM with IBM xlC compiler.
|
||||
hash_code hash_value(const APFloat &Arg);
|
||||
} /* namespace llvm */
|
||||
|
||||
#endif /* LLVM_ADT_APFLOAT_H */
|
||||
1767
thirdparty/clang/include/llvm/ADT/APInt.h
vendored
Normal file
1767
thirdparty/clang/include/llvm/ADT/APInt.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
312
thirdparty/clang/include/llvm/ADT/APSInt.h
vendored
Normal file
312
thirdparty/clang/include/llvm/ADT/APSInt.h
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
//===-- 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_ADT_APSINT_H
|
||||
#define LLVM_ADT_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() : IsUnsigned(false) {}
|
||||
|
||||
/// 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 trunc(uint32_t width) const {
|
||||
return APSInt(APInt::trunc(width), IsUnsigned);
|
||||
}
|
||||
|
||||
APSInt extend(uint32_t width) const {
|
||||
if (IsUnsigned)
|
||||
return APSInt(zext(width), IsUnsigned);
|
||||
else
|
||||
return APSInt(sext(width), IsUnsigned);
|
||||
}
|
||||
|
||||
APSInt extOrTrunc(uint32_t width) const {
|
||||
if (IsUnsigned)
|
||||
return APSInt(zextOrTrunc(width), IsUnsigned);
|
||||
else
|
||||
return APSInt(sextOrTrunc(width), IsUnsigned);
|
||||
}
|
||||
|
||||
const APSInt &operator%=(const APSInt &RHS) {
|
||||
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);
|
||||
}
|
||||
inline bool operator==(const APSInt& RHS) const {
|
||||
assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!");
|
||||
return eq(RHS);
|
||||
}
|
||||
inline bool operator==(int64_t RHS) const {
|
||||
return isSameValue(*this, APSInt(APInt(64, RHS), true));
|
||||
}
|
||||
inline bool operator!=(const APSInt& RHS) const {
|
||||
return !((*this) == RHS);
|
||||
}
|
||||
inline bool operator!=(int64_t RHS) const {
|
||||
return !((*this) == RHS);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
/// \brief Determine if two APSInts have the same value, zero- or
|
||||
/// sign-extending as needed.
|
||||
static bool isSameValue(const APSInt &I1, const APSInt &I2) {
|
||||
if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
|
||||
return I1 == I2;
|
||||
|
||||
// Check for a bit-width mismatch.
|
||||
if (I1.getBitWidth() > I2.getBitWidth())
|
||||
return isSameValue(I1, I2.extend(I1.getBitWidth()));
|
||||
else if (I2.getBitWidth() > I1.getBitWidth())
|
||||
return isSameValue(I1.extend(I2.getBitWidth()), I2);
|
||||
|
||||
// We have a signedness mismatch. Turn the signed value into an unsigned
|
||||
// value.
|
||||
if (I1.isSigned()) {
|
||||
if (I1.isNegative())
|
||||
return false;
|
||||
|
||||
return APSInt(I1, true) == I2;
|
||||
}
|
||||
|
||||
if (I2.isNegative())
|
||||
return false;
|
||||
|
||||
return I1 == APSInt(I2, true);
|
||||
}
|
||||
|
||||
/// Profile - Used to insert APSInt objects, or objects that contain APSInt
|
||||
/// objects, into FoldingSets.
|
||||
void Profile(FoldingSetNodeID& ID) const;
|
||||
};
|
||||
|
||||
inline bool operator==(int64_t V1, const APSInt& V2) {
|
||||
return V2 == V1;
|
||||
}
|
||||
inline bool operator!=(int64_t V1, const APSInt& V2) {
|
||||
return V2 != V1;
|
||||
}
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const APSInt &I) {
|
||||
I.print(OS, I.isSigned());
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
310
thirdparty/clang/include/llvm/ADT/ArrayRef.h
vendored
Normal file
310
thirdparty/clang/include/llvm/ADT/ArrayRef.h
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_ARRAYREF_H
|
||||
#define LLVM_ADT_ARRAYREF_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// ArrayRef - Represent a constant reference to an array (0 or more elements
|
||||
/// consecutively in memory), i.e. a start pointer and a length. It allows
|
||||
/// various APIs to take consecutive elements easily and conveniently.
|
||||
///
|
||||
/// This class does not own the underlying data, it is expected to be used in
|
||||
/// situations where the data resides in some other buffer, whose lifetime
|
||||
/// extends past that of the ArrayRef. For this reason, it is not in general
|
||||
/// safe to store an ArrayRef.
|
||||
///
|
||||
/// This is intended to be trivially copyable, so it should be passed by
|
||||
/// value.
|
||||
template<typename T>
|
||||
class ArrayRef {
|
||||
public:
|
||||
typedef const T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef size_t size_type;
|
||||
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
|
||||
private:
|
||||
/// The start of the array, in an external buffer.
|
||||
const T *Data;
|
||||
|
||||
/// The number of elements.
|
||||
size_type Length;
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
/// Construct an empty ArrayRef.
|
||||
/*implicit*/ ArrayRef() : Data(0), Length(0) {}
|
||||
|
||||
/// Construct an ArrayRef from a single element.
|
||||
/*implicit*/ ArrayRef(const T &OneElt)
|
||||
: Data(&OneElt), Length(1) {}
|
||||
|
||||
/// Construct an ArrayRef from a pointer and length.
|
||||
/*implicit*/ ArrayRef(const T *data, size_t length)
|
||||
: Data(data), Length(length) {}
|
||||
|
||||
/// Construct an ArrayRef from a range.
|
||||
ArrayRef(const T *begin, const T *end)
|
||||
: Data(begin), Length(end - begin) {}
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector. This is templated in order to
|
||||
/// avoid instantiating SmallVectorTemplateCommon<T> whenever we
|
||||
/// copy-construct an ArrayRef.
|
||||
template<typename U>
|
||||
/*implicit*/ ArrayRef(const SmallVectorTemplateCommon<T, U> &Vec)
|
||||
: Data(Vec.data()), Length(Vec.size()) {
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a std::vector.
|
||||
template<typename A>
|
||||
/*implicit*/ ArrayRef(const std::vector<T, A> &Vec)
|
||||
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
|
||||
|
||||
/// Construct an ArrayRef from a C array.
|
||||
template <size_t N>
|
||||
/*implicit*/ ArrayRef(const T (&Arr)[N])
|
||||
: Data(Arr), Length(N) {}
|
||||
|
||||
/// @}
|
||||
/// @name Simple Operations
|
||||
/// @{
|
||||
|
||||
iterator begin() const { return Data; }
|
||||
iterator end() const { return Data + Length; }
|
||||
|
||||
reverse_iterator rbegin() const { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() const { return reverse_iterator(begin()); }
|
||||
|
||||
/// empty - Check if the array is empty.
|
||||
bool empty() const { return Length == 0; }
|
||||
|
||||
const T *data() const { return Data; }
|
||||
|
||||
/// size - Get the array size.
|
||||
size_t size() const { return Length; }
|
||||
|
||||
/// front - Get the first element.
|
||||
const T &front() const {
|
||||
assert(!empty());
|
||||
return Data[0];
|
||||
}
|
||||
|
||||
/// back - Get the last element.
|
||||
const T &back() const {
|
||||
assert(!empty());
|
||||
return Data[Length-1];
|
||||
}
|
||||
|
||||
/// equals - Check for element-wise equality.
|
||||
bool equals(ArrayRef RHS) const {
|
||||
if (Length != RHS.Length)
|
||||
return false;
|
||||
for (size_type i = 0; i != Length; i++)
|
||||
if (Data[i] != RHS.Data[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// slice(n) - Chop off the first N elements of the array.
|
||||
ArrayRef<T> slice(unsigned N) const {
|
||||
assert(N <= size() && "Invalid specifier");
|
||||
return ArrayRef<T>(data()+N, size()-N);
|
||||
}
|
||||
|
||||
/// slice(n, m) - Chop off the first N elements of the array, and keep M
|
||||
/// elements in the array.
|
||||
ArrayRef<T> slice(unsigned N, unsigned M) const {
|
||||
assert(N+M <= size() && "Invalid specifier");
|
||||
return ArrayRef<T>(data()+N, M);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
const T &operator[](size_t Index) const {
|
||||
assert(Index < Length && "Invalid index!");
|
||||
return Data[Index];
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Expensive Operations
|
||||
/// @{
|
||||
std::vector<T> vec() const {
|
||||
return std::vector<T>(Data, Data+Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Conversion operators
|
||||
/// @{
|
||||
operator std::vector<T>() const {
|
||||
return std::vector<T>(Data, Data+Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// MutableArrayRef - Represent a mutable reference to an array (0 or more
|
||||
/// elements consecutively in memory), i.e. a start pointer and a length. It
|
||||
/// allows various APIs to take and modify consecutive elements easily and
|
||||
/// conveniently.
|
||||
///
|
||||
/// This class does not own the underlying data, it is expected to be used in
|
||||
/// situations where the data resides in some other buffer, whose lifetime
|
||||
/// extends past that of the MutableArrayRef. For this reason, it is not in
|
||||
/// general safe to store a MutableArrayRef.
|
||||
///
|
||||
/// This is intended to be trivially copyable, so it should be passed by
|
||||
/// value.
|
||||
template<typename T>
|
||||
class MutableArrayRef : public ArrayRef<T> {
|
||||
public:
|
||||
typedef T *iterator;
|
||||
|
||||
/// Construct an empty ArrayRef.
|
||||
/*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
|
||||
|
||||
/// Construct an MutableArrayRef from a single element.
|
||||
/*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a pointer and length.
|
||||
/*implicit*/ MutableArrayRef(T *data, size_t length)
|
||||
: ArrayRef<T>(data, length) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a range.
|
||||
MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a SmallVector.
|
||||
/*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec)
|
||||
: ArrayRef<T>(Vec) {}
|
||||
|
||||
/// Construct a MutableArrayRef from a std::vector.
|
||||
/*implicit*/ MutableArrayRef(std::vector<T> &Vec)
|
||||
: ArrayRef<T>(Vec) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a C array.
|
||||
template <size_t N>
|
||||
/*implicit*/ MutableArrayRef(T (&Arr)[N])
|
||||
: ArrayRef<T>(Arr) {}
|
||||
|
||||
T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
|
||||
|
||||
iterator begin() const { return data(); }
|
||||
iterator end() const { return data() + this->size(); }
|
||||
|
||||
/// front - Get the first element.
|
||||
T &front() const {
|
||||
assert(!this->empty());
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
/// back - Get the last element.
|
||||
T &back() const {
|
||||
assert(!this->empty());
|
||||
return data()[this->size()-1];
|
||||
}
|
||||
|
||||
/// slice(n) - Chop off the first N elements of the array.
|
||||
MutableArrayRef<T> slice(unsigned N) const {
|
||||
assert(N <= this->size() && "Invalid specifier");
|
||||
return MutableArrayRef<T>(data()+N, this->size()-N);
|
||||
}
|
||||
|
||||
/// slice(n, m) - Chop off the first N elements of the array, and keep M
|
||||
/// elements in the array.
|
||||
MutableArrayRef<T> slice(unsigned N, unsigned M) const {
|
||||
assert(N+M <= this->size() && "Invalid specifier");
|
||||
return MutableArrayRef<T>(data()+N, M);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
T &operator[](size_t Index) const {
|
||||
assert(Index < this->size() && "Invalid index!");
|
||||
return data()[Index];
|
||||
}
|
||||
};
|
||||
|
||||
/// @name ArrayRef Convenience constructors
|
||||
/// @{
|
||||
|
||||
/// Construct an ArrayRef from a single element.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T &OneElt) {
|
||||
return OneElt;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a pointer and length.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T *data, size_t length) {
|
||||
return ArrayRef<T>(data, length);
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a range.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
|
||||
return ArrayRef<T>(begin, end);
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector.
|
||||
template <typename T>
|
||||
ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector.
|
||||
template <typename T, unsigned N>
|
||||
ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a std::vector.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a C array.
|
||||
template<typename T, size_t N>
|
||||
ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
|
||||
return ArrayRef<T>(Arr);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name ArrayRef Comparison Operators
|
||||
/// @{
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
||||
return LHS.equals(RHS);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
// ArrayRefs can be treated like a POD type.
|
||||
template <typename T> struct isPodLike;
|
||||
template <typename T> struct isPodLike<ArrayRef<T> > {
|
||||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
589
thirdparty/clang/include/llvm/ADT/BitVector.h
vendored
Normal file
589
thirdparty/clang/include/llvm/ADT/BitVector.h
vendored
Normal file
@@ -0,0 +1,589 @@
|
||||
//===- 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/Compiler.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
|
||||
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=(reference t) {
|
||||
*this = bool(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
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 = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
|
||||
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 = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
|
||||
std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
BitVector(BitVector &&RHS)
|
||||
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
|
||||
RHS.Bits = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
~BitVector() {
|
||||
std::free(Bits);
|
||||
}
|
||||
|
||||
/// empty - Tests whether there are no bits in this bitvector.
|
||||
bool empty() const { return Size == 0; }
|
||||
|
||||
/// 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
|
||||
llvm_unreachable("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;
|
||||
}
|
||||
|
||||
/// all - Returns true if all bits are set.
|
||||
bool all() const {
|
||||
// TODO: Optimize this.
|
||||
return count() == size();
|
||||
}
|
||||
|
||||
/// none - Returns true if none of the bits are set.
|
||||
bool none() const {
|
||||
return !any();
|
||||
}
|
||||
|
||||
/// 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]);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
llvm_unreachable("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 &= ~0UL << BitPos;
|
||||
|
||||
if (Copy != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
|
||||
llvm_unreachable("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]);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
llvm_unreachable("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;
|
||||
}
|
||||
|
||||
/// set - Efficiently set a range of bits in [I, E)
|
||||
BitVector &set(unsigned I, unsigned E) {
|
||||
assert(I <= E && "Attempted to set backwards range!");
|
||||
assert(E <= size() && "Attempted to set out-of-bounds range!");
|
||||
|
||||
if (I == E) return *this;
|
||||
|
||||
if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
|
||||
BitWord EMask = 1UL << (E % BITWORD_SIZE);
|
||||
BitWord IMask = 1UL << (I % BITWORD_SIZE);
|
||||
BitWord Mask = EMask - IMask;
|
||||
Bits[I / BITWORD_SIZE] |= Mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
|
||||
Bits[I / BITWORD_SIZE] |= PrefixMask;
|
||||
I = RoundUpToAlignment(I, BITWORD_SIZE);
|
||||
|
||||
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
|
||||
Bits[I / BITWORD_SIZE] = ~0UL;
|
||||
|
||||
BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
|
||||
Bits[I / BITWORD_SIZE] |= PostfixMask;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// reset - Efficiently reset a range of bits in [I, E)
|
||||
BitVector &reset(unsigned I, unsigned E) {
|
||||
assert(I <= E && "Attempted to reset backwards range!");
|
||||
assert(E <= size() && "Attempted to reset out-of-bounds range!");
|
||||
|
||||
if (I == E) return *this;
|
||||
|
||||
if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
|
||||
BitWord EMask = 1UL << (E % BITWORD_SIZE);
|
||||
BitWord IMask = 1UL << (I % BITWORD_SIZE);
|
||||
BitWord Mask = EMask - IMask;
|
||||
Bits[I / BITWORD_SIZE] &= ~Mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
|
||||
Bits[I / BITWORD_SIZE] &= ~PrefixMask;
|
||||
I = RoundUpToAlignment(I, BITWORD_SIZE);
|
||||
|
||||
for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
|
||||
Bits[I / BITWORD_SIZE] = 0UL;
|
||||
|
||||
BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
|
||||
Bits[I / BITWORD_SIZE] &= ~PostfixMask;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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];
|
||||
}
|
||||
|
||||
/// Test if any common bits are set.
|
||||
bool anyCommon(const BitVector &RHS) const {
|
||||
unsigned ThisWords = NumBitWords(size());
|
||||
unsigned RHSWords = NumBitWords(RHS.size());
|
||||
for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i)
|
||||
if (Bits[i] & RHS.Bits[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
|
||||
BitVector &reset(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];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// test - Check if (This - RHS) is zero.
|
||||
/// This is the same as reset(RHS) and any().
|
||||
bool test(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]) != 0)
|
||||
return true;
|
||||
|
||||
for (; i != ThisWords ; ++i)
|
||||
if (Bits[i] != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BitVector &operator|=(const BitVector &RHS) {
|
||||
if (size() < RHS.size())
|
||||
resize(RHS.size());
|
||||
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
|
||||
Bits[i] |= RHS.Bits[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitVector &operator^=(const BitVector &RHS) {
|
||||
if (size() < RHS.size())
|
||||
resize(RHS.size());
|
||||
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++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) {
|
||||
if (Size)
|
||||
std::memcpy(Bits, RHS.Bits, RHSWords * sizeof(BitWord));
|
||||
clear_unused_bits();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Grow the bitvector to have enough elements.
|
||||
Capacity = RHSWords;
|
||||
BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
|
||||
std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
|
||||
|
||||
// Destroy the old bits.
|
||||
std::free(Bits);
|
||||
Bits = NewBits;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
const BitVector &operator=(BitVector &&RHS) {
|
||||
if (this == &RHS) return *this;
|
||||
|
||||
std::free(Bits);
|
||||
Bits = RHS.Bits;
|
||||
Size = RHS.Size;
|
||||
Capacity = RHS.Capacity;
|
||||
|
||||
RHS.Bits = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void swap(BitVector &RHS) {
|
||||
std::swap(Bits, RHS.Bits);
|
||||
std::swap(Size, RHS.Size);
|
||||
std::swap(Capacity, RHS.Capacity);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Portable bit mask operations.
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// These methods all operate on arrays of uint32_t, each holding 32 bits. The
|
||||
// fixed word size makes it easier to work with literal bit vector constants
|
||||
// in portable code.
|
||||
//
|
||||
// The LSB in each word is the lowest numbered bit. The size of a portable
|
||||
// bit mask is always a whole multiple of 32 bits. If no bit mask size is
|
||||
// given, the bit mask is assumed to cover the entire BitVector.
|
||||
|
||||
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
|
||||
/// This computes "*this |= Mask".
|
||||
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<true, false>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsInMask - Clear any bits in this vector that are set in Mask.
|
||||
/// Don't resize. This computes "*this &= ~Mask".
|
||||
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<false, false>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this |= ~Mask".
|
||||
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<true, true>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this &= Mask".
|
||||
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<false, true>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
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) {
|
||||
BitWord ExtraBitMask = ~0UL << ExtraBits;
|
||||
if (t)
|
||||
Bits[UsedWords-1] |= ExtraBitMask;
|
||||
else
|
||||
Bits[UsedWords-1] &= ~ExtraBitMask;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the unused bits in the high words.
|
||||
void clear_unused_bits() {
|
||||
set_unused_bits(false);
|
||||
}
|
||||
|
||||
void grow(unsigned NewSize) {
|
||||
Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
|
||||
Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord));
|
||||
|
||||
clear_unused_bits();
|
||||
}
|
||||
|
||||
void init_words(BitWord *B, unsigned NumWords, bool t) {
|
||||
memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
|
||||
}
|
||||
|
||||
template<bool AddBits, bool InvertMask>
|
||||
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
|
||||
assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size.");
|
||||
MaskWords = std::min(MaskWords, (size() + 31) / 32);
|
||||
const unsigned Scale = BITWORD_SIZE / 32;
|
||||
unsigned i;
|
||||
for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) {
|
||||
BitWord BW = Bits[i];
|
||||
// This inner loop should unroll completely when BITWORD_SIZE > 32.
|
||||
for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
|
||||
uint32_t M = *Mask++;
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) BW |= BitWord(M) << b;
|
||||
else BW &= ~(BitWord(M) << b);
|
||||
}
|
||||
Bits[i] = BW;
|
||||
}
|
||||
for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
|
||||
uint32_t M = *Mask++;
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) Bits[i] |= BitWord(M) << b;
|
||||
else Bits[i] &= ~(BitWord(M) << b);
|
||||
}
|
||||
if (AddBits)
|
||||
clear_unused_bits();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
namespace std {
|
||||
/// Implement std::swap in terms of BitVector swap.
|
||||
inline void
|
||||
swap(llvm::BitVector &LHS, llvm::BitVector &RHS) {
|
||||
LHS.swap(RHS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
77
thirdparty/clang/include/llvm/ADT/DAGDeltaAlgorithm.h
vendored
Normal file
77
thirdparty/clang/include/llvm/ADT/DAGDeltaAlgorithm.h
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
//===--- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ----*- 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_DAGDELTAALGORITHM_H
|
||||
#define LLVM_ADT_DAGDELTAALGORITHM_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// DAGDeltaAlgorithm - Implements a "delta debugging" algorithm for minimizing
|
||||
/// directed acyclic graphs using a predicate function.
|
||||
///
|
||||
/// The result of the algorithm is a subset of the input change set which is
|
||||
/// guaranteed to satisfy the predicate, assuming that the input set did. For
|
||||
/// well formed predicates, the result set is guaranteed to be such that
|
||||
/// removing any single element not required by the dependencies on the other
|
||||
/// elements would falsify the predicate.
|
||||
///
|
||||
/// The DAG should be used to represent dependencies in the changes which are
|
||||
/// likely to hold across the predicate function. That is, for a particular
|
||||
/// changeset S and predicate P:
|
||||
///
|
||||
/// P(S) => P(S union pred(S))
|
||||
///
|
||||
/// The minization algorithm uses this dependency information to attempt to
|
||||
/// eagerly prune large subsets of changes. As with \see DeltaAlgorithm, the DAG
|
||||
/// is not required to satisfy this property, but the algorithm will run
|
||||
/// substantially fewer tests with appropriate dependencies. \see DeltaAlgorithm
|
||||
/// for more information on the properties which the predicate function itself
|
||||
/// should satisfy.
|
||||
class DAGDeltaAlgorithm {
|
||||
virtual void anchor();
|
||||
public:
|
||||
typedef unsigned change_ty;
|
||||
typedef std::pair<change_ty, change_ty> edge_ty;
|
||||
|
||||
// FIXME: Use a decent data structure.
|
||||
typedef std::set<change_ty> changeset_ty;
|
||||
typedef std::vector<changeset_ty> changesetlist_ty;
|
||||
|
||||
public:
|
||||
virtual ~DAGDeltaAlgorithm() {}
|
||||
|
||||
/// Run - Minimize the DAG formed by the \p Changes vertices and the
|
||||
/// \p Dependencies edges by executing \see ExecuteOneTest() on subsets of
|
||||
/// changes and returning the smallest set which still satisfies the test
|
||||
/// predicate and the input \p Dependencies.
|
||||
///
|
||||
/// \param Changes The list of changes.
|
||||
///
|
||||
/// \param Dependencies The list of dependencies amongst changes. For each
|
||||
/// (x,y) in \p Dependencies, both x and y must be in \p Changes. The
|
||||
/// minimization algorithm guarantees that for each tested changed set S,
|
||||
/// \f$ x \in S \f$ implies \f$ y \in S \f$. It is an error to have cyclic
|
||||
/// dependencies.
|
||||
changeset_ty Run(const changeset_ty &Changes,
|
||||
const std::vector<edge_ty> &Dependencies);
|
||||
|
||||
/// UpdatedSearchState - Callback used when the search state changes.
|
||||
virtual void UpdatedSearchState(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets,
|
||||
const changeset_ty &Required) {}
|
||||
|
||||
/// ExecuteOneTest - Execute a single test predicate on the change set \p S.
|
||||
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
91
thirdparty/clang/include/llvm/ADT/DeltaAlgorithm.h
vendored
Normal file
91
thirdparty/clang/include/llvm/ADT/DeltaAlgorithm.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
//===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- 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_DELTAALGORITHM_H
|
||||
#define LLVM_ADT_DELTAALGORITHM_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// DeltaAlgorithm - Implements the delta debugging algorithm (A. Zeller '99)
|
||||
/// for minimizing arbitrary sets using a predicate function.
|
||||
///
|
||||
/// The result of the algorithm is a subset of the input change set which is
|
||||
/// guaranteed to satisfy the predicate, assuming that the input set did. For
|
||||
/// well formed predicates, the result set is guaranteed to be such that
|
||||
/// removing any single element would falsify the predicate.
|
||||
///
|
||||
/// For best results the predicate function *should* (but need not) satisfy
|
||||
/// certain properties, in particular:
|
||||
/// (1) The predicate should return false on an empty set and true on the full
|
||||
/// set.
|
||||
/// (2) If the predicate returns true for a set of changes, it should return
|
||||
/// true for all supersets of that set.
|
||||
///
|
||||
/// It is not an error to provide a predicate that does not satisfy these
|
||||
/// requirements, and the algorithm will generally produce reasonable
|
||||
/// results. However, it may run substantially more tests than with a good
|
||||
/// predicate.
|
||||
class DeltaAlgorithm {
|
||||
public:
|
||||
typedef unsigned change_ty;
|
||||
// FIXME: Use a decent data structure.
|
||||
typedef std::set<change_ty> changeset_ty;
|
||||
typedef std::vector<changeset_ty> changesetlist_ty;
|
||||
|
||||
private:
|
||||
/// Cache of failed test results. Successful test results are never cached
|
||||
/// since we always reduce following a success.
|
||||
std::set<changeset_ty> FailedTestsCache;
|
||||
|
||||
/// GetTestResult - Get the test result for the \p Changes from the
|
||||
/// cache, executing the test if necessary.
|
||||
///
|
||||
/// \param Changes - The change set to test.
|
||||
/// \return - The test result.
|
||||
bool GetTestResult(const changeset_ty &Changes);
|
||||
|
||||
/// Split - Partition a set of changes \p S into one or two subsets.
|
||||
void Split(const changeset_ty &S, changesetlist_ty &Res);
|
||||
|
||||
/// Delta - Minimize a set of \p Changes which has been partioned into
|
||||
/// smaller sets, by attempting to remove individual subsets.
|
||||
changeset_ty Delta(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets);
|
||||
|
||||
/// Search - Search for a subset (or subsets) in \p Sets which can be
|
||||
/// removed from \p Changes while still satisfying the predicate.
|
||||
///
|
||||
/// \param Res - On success, a subset of Changes which satisfies the
|
||||
/// predicate.
|
||||
/// \return - True on success.
|
||||
bool Search(const changeset_ty &Changes, const changesetlist_ty &Sets,
|
||||
changeset_ty &Res);
|
||||
|
||||
protected:
|
||||
/// UpdatedSearchState - Callback used when the search state changes.
|
||||
virtual void UpdatedSearchState(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets) {}
|
||||
|
||||
/// ExecuteOneTest - Execute a single test predicate on the change set \p S.
|
||||
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
|
||||
|
||||
public:
|
||||
virtual ~DeltaAlgorithm();
|
||||
|
||||
/// Run - Minimize the set \p Changes by executing \see ExecuteOneTest() on
|
||||
/// subsets of changes and returning the smallest set which still satisfies
|
||||
/// the test predicate.
|
||||
changeset_ty Run(const changeset_ty &Changes);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
1057
thirdparty/clang/include/llvm/ADT/DenseMap.h
vendored
Normal file
1057
thirdparty/clang/include/llvm/ADT/DenseMap.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
168
thirdparty/clang/include/llvm/ADT/DenseMapInfo.h
vendored
Normal file
168
thirdparty/clang/include/llvm/ADT/DenseMapInfo.h
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
//===- llvm/ADT/DenseMapInfo.h - Type traits for DenseMap -------*- 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 DenseMapInfo traits for DenseMap.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_DENSEMAPINFO_H
|
||||
#define LLVM_ADT_DENSEMAPINFO_H
|
||||
|
||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for all pointers.
|
||||
template<typename T>
|
||||
struct DenseMapInfo<T*> {
|
||||
static inline T* getEmptyKey() {
|
||||
uintptr_t Val = static_cast<uintptr_t>(-1);
|
||||
Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
|
||||
return reinterpret_cast<T*>(Val);
|
||||
}
|
||||
static inline T* getTombstoneKey() {
|
||||
uintptr_t Val = static_cast<uintptr_t>(-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; }
|
||||
};
|
||||
|
||||
// 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 * 37U; }
|
||||
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 ~0U; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
|
||||
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 ~0UL; }
|
||||
static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
|
||||
static unsigned getHashValue(const unsigned long& Val) {
|
||||
return (unsigned)(Val * 37UL);
|
||||
}
|
||||
static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for unsigned long longs.
|
||||
template<> struct DenseMapInfo<unsigned long long> {
|
||||
static inline unsigned long long getEmptyKey() { return ~0ULL; }
|
||||
static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
|
||||
static unsigned getHashValue(const unsigned long long& Val) {
|
||||
return (unsigned)(Val * 37ULL);
|
||||
}
|
||||
static bool isEqual(const unsigned long long& LHS,
|
||||
const unsigned long long& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for ints.
|
||||
template<> struct DenseMapInfo<int> {
|
||||
static inline int getEmptyKey() { return 0x7fffffff; }
|
||||
static inline int getTombstoneKey() { return -0x7fffffff - 1; }
|
||||
static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
|
||||
static bool isEqual(const int& LHS, const int& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for longs.
|
||||
template<> struct DenseMapInfo<long> {
|
||||
static inline long getEmptyKey() {
|
||||
return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
|
||||
}
|
||||
static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
|
||||
static unsigned getHashValue(const long& Val) {
|
||||
return (unsigned)(Val * 37UL);
|
||||
}
|
||||
static bool isEqual(const long& LHS, const long& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for long longs.
|
||||
template<> struct DenseMapInfo<long long> {
|
||||
static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
|
||||
static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
|
||||
static unsigned getHashValue(const long long& Val) {
|
||||
return (unsigned)(Val * 37ULL);
|
||||
}
|
||||
static bool isEqual(const long long& LHS,
|
||||
const long 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::getTombstoneKey());
|
||||
}
|
||||
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 FirstInfo::isEqual(LHS.first, RHS.first) &&
|
||||
SecondInfo::isEqual(LHS.second, RHS.second);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
131
thirdparty/clang/include/llvm/ADT/DenseSet.h
vendored
Normal file
131
thirdparty/clang/include/llvm/ADT/DenseSet.h
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
//===- 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 = 0) : TheMap(NumInitBuckets) {}
|
||||
|
||||
bool empty() const { return TheMap.empty(); }
|
||||
unsigned size() const { return TheMap.size(); }
|
||||
size_t getMemorySize() const { return TheMap.getMemorySize(); }
|
||||
|
||||
/// Grow the DenseSet so that it has at least Size buckets. Will not shrink
|
||||
/// the Size of the set.
|
||||
void resize(size_t Size) { TheMap.resize(Size); }
|
||||
|
||||
void clear() {
|
||||
TheMap.clear();
|
||||
}
|
||||
|
||||
bool count(const ValueT &V) const {
|
||||
return TheMap.count(V);
|
||||
}
|
||||
|
||||
bool erase(const ValueT &V) {
|
||||
return TheMap.erase(V);
|
||||
}
|
||||
|
||||
void swap(DenseSet& RHS) {
|
||||
TheMap.swap(RHS.TheMap);
|
||||
}
|
||||
|
||||
DenseSet &operator=(const DenseSet &RHS) {
|
||||
TheMap = RHS.TheMap;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
|
||||
class Iterator {
|
||||
typename MapTy::iterator I;
|
||||
friend class DenseSet;
|
||||
public:
|
||||
typedef typename MapTy::iterator::difference_type difference_type;
|
||||
typedef ValueT value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type &reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
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;
|
||||
friend class DenseSet;
|
||||
public:
|
||||
typedef typename MapTy::const_iterator::difference_type difference_type;
|
||||
typedef ValueT value_type;
|
||||
typedef value_type *pointer;
|
||||
typedef value_type &reference;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
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()); }
|
||||
|
||||
iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); }
|
||||
void erase(Iterator I) { return TheMap.erase(I.I); }
|
||||
void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
|
||||
|
||||
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
|
||||
268
thirdparty/clang/include/llvm/ADT/DepthFirstIterator.h
vendored
Normal file
268
thirdparty/clang/include/llvm/ADT/DepthFirstIterator.h
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
//===- 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/PointerIntPair.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 std::iterator<std::forward_iterator_tag,
|
||||
typename GT::NodeType, ptrdiff_t>,
|
||||
public df_iterator_storage<SetType, ExtStorage> {
|
||||
typedef std::iterator<std::forward_iterator_tag,
|
||||
typename GT::NodeType, ptrdiff_t> super;
|
||||
|
||||
typedef typename GT::NodeType NodeType;
|
||||
typedef typename GT::ChildIteratorType ChildItTy;
|
||||
typedef PointerIntPair<NodeType*, 1> PointerIntTy;
|
||||
|
||||
// VisitStack - Used to maintain the ordering. Top = current block
|
||||
// First element is node pointer, second is the 'next child' to visit
|
||||
// if the int in PointerIntTy is 0, the 'next child' to visit is invalid
|
||||
std::vector<std::pair<PointerIntTy, ChildItTy> > VisitStack;
|
||||
private:
|
||||
inline df_iterator(NodeType *Node) {
|
||||
this->Visited.insert(Node);
|
||||
VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
|
||||
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)) {
|
||||
VisitStack.push_back(std::make_pair(PointerIntTy(Node, 0),
|
||||
GT::child_begin(Node)));
|
||||
this->Visited.insert(Node);
|
||||
}
|
||||
}
|
||||
inline df_iterator(SetType &S)
|
||||
: df_iterator_storage<SetType, ExtStorage>(S) {
|
||||
// End is when stack is empty
|
||||
}
|
||||
|
||||
inline void toNext() {
|
||||
do {
|
||||
std::pair<PointerIntTy, ChildItTy> &Top = VisitStack.back();
|
||||
NodeType *Node = Top.first.getPointer();
|
||||
ChildItTy &It = Top.second;
|
||||
if (!Top.first.getInt()) {
|
||||
// now retrieve the real begin of the children before we dive in
|
||||
It = GT::child_begin(Node);
|
||||
Top.first.setInt(1);
|
||||
}
|
||||
|
||||
while (It != GT::child_end(Node)) {
|
||||
NodeType *Next = *It++;
|
||||
// Has our next sibling been visited?
|
||||
if (Next && !this->Visited.count(Next)) {
|
||||
// No, do it now.
|
||||
this->Visited.insert(Next);
|
||||
VisitStack.push_back(std::make_pair(PointerIntTy(Next, 0),
|
||||
GT::child_begin(Next)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Oops, ran out of successors... go up a level on the stack.
|
||||
VisitStack.pop_back();
|
||||
} while (!VisitStack.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 == x.VisitStack;
|
||||
}
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
return VisitStack.back().first.getPointer();
|
||||
}
|
||||
|
||||
// This is a nonstandard operator-> that dereferences the pointer an extra
|
||||
// time... so that you can actually call methods ON the Node, because
|
||||
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
|
||||
//
|
||||
inline NodeType *operator->() const { return operator*(); }
|
||||
|
||||
inline _Self& operator++() { // Preincrement
|
||||
toNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// skips all children of the current node and traverses to next node
|
||||
//
|
||||
inline _Self& skipChildren() {
|
||||
VisitStack.pop_back();
|
||||
if (!VisitStack.empty())
|
||||
toNext();
|
||||
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;
|
||||
}
|
||||
|
||||
/// getPathLength - Return the length of the path from the entry node to the
|
||||
/// current node, counting both nodes.
|
||||
unsigned getPathLength() const { return VisitStack.size(); }
|
||||
|
||||
/// getPath - Return the n'th node in the path from the entry node to the
|
||||
/// current node.
|
||||
NodeType *getPath(unsigned n) const {
|
||||
return VisitStack[n].first.getPointer();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
283
thirdparty/clang/include/llvm/ADT/EquivalenceClasses.h
vendored
Normal file
283
thirdparty/clang/include/llvm/ADT/EquivalenceClasses.h
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
//===-- 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/Support/DataTypes.h"
|
||||
#include <cassert>
|
||||
#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:
|
||||
///
|
||||
/// \code
|
||||
/// 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.
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// 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) {
|
||||
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(ECValue(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 std::iterator<std::forward_iterator_tag,
|
||||
const ElemTy, ptrdiff_t> {
|
||||
typedef std::iterator<std::forward_iterator_tag,
|
||||
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
|
||||
794
thirdparty/clang/include/llvm/ADT/FoldingSet.h
vendored
Normal file
794
thirdparty/clang/include/llvm/ADT/FoldingSet.h
vendored
Normal file
@@ -0,0 +1,794 @@
|
||||
//===-- 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/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class APFloat;
|
||||
class APInt;
|
||||
class BumpPtrAllocator;
|
||||
|
||||
/// 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) const {
|
||||
/// 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);
|
||||
|
||||
/// InsertNode - Insert the specified node into the folding set, knowing that
|
||||
/// it is not already in the folding set.
|
||||
void InsertNode(Node *N) {
|
||||
Node *Inserted = GetOrInsertNode(N);
|
||||
(void)Inserted;
|
||||
assert(Inserted == N && "Node already inserted!");
|
||||
}
|
||||
|
||||
/// 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(Node *N, FoldingSetNodeID &ID) const = 0;
|
||||
/// NodeEquals - Instantiations of the FoldingSet template implement
|
||||
/// this function to compare the given node with the given ID.
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const=0;
|
||||
/// ComputeNodeHash - Instantiations of the FoldingSet template implement
|
||||
/// this function to compute a hash value for the given node.
|
||||
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template<typename T> struct FoldingSetTrait;
|
||||
|
||||
/// DefaultFoldingSetTrait - This class provides default implementations
|
||||
/// for FoldingSetTrait implementations.
|
||||
///
|
||||
template<typename T> struct DefaultFoldingSetTrait {
|
||||
static void Profile(const T &X, FoldingSetNodeID &ID) {
|
||||
X.Profile(ID);
|
||||
}
|
||||
static void Profile(T &X, FoldingSetNodeID &ID) {
|
||||
X.Profile(ID);
|
||||
}
|
||||
|
||||
// Equals - Test if the profile for X would match ID, using TempID
|
||||
// to compute a temporary ID if necessary. The default implementation
|
||||
// just calls Profile and does a regular comparison. Implementations
|
||||
// can override this to provide more efficient implementations.
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID);
|
||||
|
||||
// ComputeHash - Compute a hash value for X, using TempID to
|
||||
// compute a temporary ID if necessary. The default implementation
|
||||
// just calls Profile and does a regular hash computation.
|
||||
// Implementations can override this to provide more efficient
|
||||
// implementations.
|
||||
static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID);
|
||||
};
|
||||
|
||||
/// 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 class, one can add objects
|
||||
/// to FoldingSets that were not originally designed to have that behavior.
|
||||
template<typename T> struct FoldingSetTrait
|
||||
: public DefaultFoldingSetTrait<T> {};
|
||||
|
||||
template<typename T, typename Ctx> struct ContextualFoldingSetTrait;
|
||||
|
||||
/// DefaultContextualFoldingSetTrait - Like DefaultFoldingSetTrait, but
|
||||
/// for ContextualFoldingSets.
|
||||
template<typename T, typename Ctx>
|
||||
struct DefaultContextualFoldingSetTrait {
|
||||
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
|
||||
X.Profile(ID, Context);
|
||||
}
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID, Ctx Context);
|
||||
static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
|
||||
Ctx Context);
|
||||
};
|
||||
|
||||
/// ContextualFoldingSetTrait - Like FoldingSetTrait, but for
|
||||
/// ContextualFoldingSets.
|
||||
template<typename T, typename Ctx> struct ContextualFoldingSetTrait
|
||||
: public DefaultContextualFoldingSetTrait<T, Ctx> {};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// FoldingSetNodeIDRef - This class describes a reference to an interned
|
||||
/// FoldingSetNodeID, which can be a useful to store node id data rather
|
||||
/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
|
||||
/// is often much larger than necessary, and the possibility of heap
|
||||
/// allocation means it requires a non-trivial destructor call.
|
||||
class FoldingSetNodeIDRef {
|
||||
const unsigned *Data;
|
||||
size_t Size;
|
||||
public:
|
||||
FoldingSetNodeIDRef() : Data(0), Size(0) {}
|
||||
FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
|
||||
|
||||
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
|
||||
/// used to lookup the node in the FoldingSetImpl.
|
||||
unsigned ComputeHash() const;
|
||||
|
||||
bool operator==(FoldingSetNodeIDRef) const;
|
||||
|
||||
/// Used to compare the "ordering" of two nodes as defined by the
|
||||
/// profiled bits and their ordering defined by memcmp().
|
||||
bool operator<(FoldingSetNodeIDRef) const;
|
||||
|
||||
const unsigned *getData() const { return Data; }
|
||||
size_t getSize() const { return Size; }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// 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() {}
|
||||
|
||||
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
|
||||
: Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
|
||||
|
||||
/// 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(StringRef String);
|
||||
void AddNodeID(const FoldingSetNodeID &ID);
|
||||
|
||||
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;
|
||||
bool operator==(const FoldingSetNodeIDRef RHS) const;
|
||||
|
||||
/// Used to compare the "ordering" of two nodes as defined by the
|
||||
/// profiled bits and their ordering defined by memcmp().
|
||||
bool operator<(const FoldingSetNodeID &RHS) const;
|
||||
bool operator<(const FoldingSetNodeIDRef RHS) const;
|
||||
|
||||
/// Intern - Copy this node's data to a memory region allocated from the
|
||||
/// given allocator and return a FoldingSetNodeIDRef describing the
|
||||
/// interned data.
|
||||
FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) 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;
|
||||
|
||||
// Definitions of FoldingSetTrait and ContextualFoldingSetTrait functions, which
|
||||
// require the definition of FoldingSetNodeID.
|
||||
template<typename T>
|
||||
inline bool
|
||||
DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
|
||||
unsigned IDHash, FoldingSetNodeID &TempID) {
|
||||
FoldingSetTrait<T>::Profile(X, TempID);
|
||||
return TempID == ID;
|
||||
}
|
||||
template<typename T>
|
||||
inline unsigned
|
||||
DefaultFoldingSetTrait<T>::ComputeHash(T &X, FoldingSetNodeID &TempID) {
|
||||
FoldingSetTrait<T>::Profile(X, TempID);
|
||||
return TempID.ComputeHash();
|
||||
}
|
||||
template<typename T, typename Ctx>
|
||||
inline bool
|
||||
DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
|
||||
const FoldingSetNodeID &ID,
|
||||
unsigned IDHash,
|
||||
FoldingSetNodeID &TempID,
|
||||
Ctx Context) {
|
||||
ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
|
||||
return TempID == ID;
|
||||
}
|
||||
template<typename T, typename Ctx>
|
||||
inline unsigned
|
||||
DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
|
||||
FoldingSetNodeID &TempID,
|
||||
Ctx Context) {
|
||||
ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
|
||||
return TempID.ComputeHash();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// 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(Node *N, FoldingSetNodeID &ID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
FoldingSetTrait<T>::Profile(*TN, ID);
|
||||
}
|
||||
/// NodeEquals - Instantiations may optionally provide a way to compare a
|
||||
/// node with a specified ID.
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
|
||||
}
|
||||
/// ComputeNodeHash - Instantiations may optionally provide a way to compute a
|
||||
/// hash value directly from a node.
|
||||
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// ContextualFoldingSet - This template class is a further refinement
|
||||
/// of FoldingSet which provides a context argument when calling
|
||||
/// Profile on its nodes. Currently, that argument is fixed at
|
||||
/// initialization time.
|
||||
///
|
||||
/// T must be a subclass of FoldingSetNode and implement a Profile
|
||||
/// function with signature
|
||||
/// void Profile(llvm::FoldingSetNodeID &, Ctx);
|
||||
template <class T, class Ctx>
|
||||
class ContextualFoldingSet : public FoldingSetImpl {
|
||||
// Unfortunately, this can't derive from FoldingSet<T> because the
|
||||
// construction vtable for FoldingSet<T> requires
|
||||
// FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
|
||||
// requires a single-argument T::Profile().
|
||||
|
||||
private:
|
||||
Ctx Context;
|
||||
|
||||
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
|
||||
/// way to convert nodes into a unique specifier.
|
||||
virtual void GetNodeProfile(FoldingSetImpl::Node *N,
|
||||
FoldingSetNodeID &ID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
|
||||
}
|
||||
virtual bool NodeEquals(FoldingSetImpl::Node *N,
|
||||
const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
|
||||
Context);
|
||||
}
|
||||
virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
|
||||
: FoldingSetImpl(Log2InitSize), Context(Context)
|
||||
{}
|
||||
|
||||
Ctx getContext() const { return Context; }
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// FoldingSetVectorIterator - This implements an iterator for
|
||||
/// FoldingSetVector. It is only necessary because FoldingSetIterator provides
|
||||
/// a value_type of T, while the vector in FoldingSetVector exposes
|
||||
/// a value_type of T*. Fortunately, FoldingSetIterator doesn't expose very
|
||||
/// much besides operator* and operator->, so we just wrap the inner vector
|
||||
/// iterator and perform the extra dereference.
|
||||
template <class T, class VectorIteratorT>
|
||||
class FoldingSetVectorIterator {
|
||||
// Provide a typedef to workaround the lack of correct injected class name
|
||||
// support in older GCCs.
|
||||
typedef FoldingSetVectorIterator<T, VectorIteratorT> SelfT;
|
||||
|
||||
VectorIteratorT Iterator;
|
||||
|
||||
public:
|
||||
FoldingSetVectorIterator(VectorIteratorT I) : Iterator(I) {}
|
||||
|
||||
bool operator==(const SelfT &RHS) const {
|
||||
return Iterator == RHS.Iterator;
|
||||
}
|
||||
bool operator!=(const SelfT &RHS) const {
|
||||
return Iterator != RHS.Iterator;
|
||||
}
|
||||
|
||||
T &operator*() const { return **Iterator; }
|
||||
|
||||
T *operator->() const { return *Iterator; }
|
||||
|
||||
inline SelfT &operator++() {
|
||||
++Iterator;
|
||||
return *this;
|
||||
}
|
||||
SelfT operator++(int) {
|
||||
SelfT tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// FoldingSetVector - This template class combines a FoldingSet and a vector
|
||||
/// to provide the interface of FoldingSet but with deterministic iteration
|
||||
/// order based on the insertion order. T must be a subclass of FoldingSetNode
|
||||
/// and implement a Profile function.
|
||||
template <class T, class VectorT = SmallVector<T*, 8> >
|
||||
class FoldingSetVector {
|
||||
FoldingSet<T> Set;
|
||||
VectorT Vector;
|
||||
|
||||
public:
|
||||
explicit FoldingSetVector(unsigned Log2InitSize = 6)
|
||||
: Set(Log2InitSize) {
|
||||
}
|
||||
|
||||
typedef FoldingSetVectorIterator<T, typename VectorT::iterator> iterator;
|
||||
iterator begin() { return Vector.begin(); }
|
||||
iterator end() { return Vector.end(); }
|
||||
|
||||
typedef FoldingSetVectorIterator<const T, typename VectorT::const_iterator>
|
||||
const_iterator;
|
||||
const_iterator begin() const { return Vector.begin(); }
|
||||
const_iterator end() const { return Vector.end(); }
|
||||
|
||||
/// clear - Remove all nodes from the folding set.
|
||||
void clear() { Set.clear(); Vector.clear(); }
|
||||
|
||||
/// 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 Set.FindNodeOrInsertPos(ID, InsertPos);
|
||||
}
|
||||
|
||||
/// 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(T *N) {
|
||||
T *Result = Set.GetOrInsertNode(N);
|
||||
if (Result == N) Vector.push_back(N);
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// 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(T *N, void *InsertPos) {
|
||||
Set.InsertNode(N, InsertPos);
|
||||
Vector.push_back(N);
|
||||
}
|
||||
|
||||
/// InsertNode - Insert the specified node into the folding set, knowing that
|
||||
/// it is not already in the folding set.
|
||||
void InsertNode(T *N) {
|
||||
Set.InsertNode(N);
|
||||
Vector.push_back(N);
|
||||
}
|
||||
|
||||
/// size - Returns the number of nodes in the folding set.
|
||||
unsigned size() const { return Set.size(); }
|
||||
|
||||
/// empty - Returns true if there are no nodes in the folding set.
|
||||
bool empty() const { return Set.empty(); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// 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; }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// FastFoldingSetNode - This is a subclass of FoldingSetNode which stores
|
||||
/// a FoldingSetNodeID value rather than requiring the node to recompute it
|
||||
/// each time it is needed. This trades space for speed (which can be
|
||||
/// significant if the ID is long), and it also permits nodes to drop
|
||||
/// information that would otherwise only be required for recomputing an ID.
|
||||
class FastFoldingSetNode : public FoldingSetNode {
|
||||
FoldingSetNodeID FastID;
|
||||
protected:
|
||||
explicit FastFoldingSetNode(const FoldingSetNodeID &ID) : FastID(ID) {}
|
||||
public:
|
||||
void Profile(FoldingSetNodeID &ID) const {
|
||||
ID.AddNodeID(FastID);
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Partial specializations of FoldingSetTrait.
|
||||
|
||||
template<typename T> struct FoldingSetTrait<T*> {
|
||||
static inline void Profile(T *X, FoldingSetNodeID &ID) {
|
||||
ID.AddPointer(X);
|
||||
}
|
||||
};
|
||||
} // End of namespace llvm.
|
||||
|
||||
#endif
|
||||
106
thirdparty/clang/include/llvm/ADT/GraphTraits.h
vendored
Normal file
106
thirdparty/clang/include/llvm/ADT/GraphTraits.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//===-- 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(const 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
|
||||
|
||||
// static unsigned size (GraphType *G)
|
||||
// Return total number of 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
|
||||
765
thirdparty/clang/include/llvm/ADT/Hashing.h
vendored
Normal file
765
thirdparty/clang/include/llvm/ADT/Hashing.h
vendored
Normal file
@@ -0,0 +1,765 @@
|
||||
//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- 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 newly proposed standard C++ interfaces for hashing
|
||||
// arbitrary data and building hash functions for user-defined types. This
|
||||
// interface was originally proposed in N3333[1] and is currently under review
|
||||
// for inclusion in a future TR and/or standard.
|
||||
//
|
||||
// The primary interfaces provide are comprised of one type and three functions:
|
||||
//
|
||||
// -- 'hash_code' class is an opaque type representing the hash code for some
|
||||
// data. It is the intended product of hashing, and can be used to implement
|
||||
// hash tables, checksumming, and other common uses of hashes. It is not an
|
||||
// integer type (although it can be converted to one) because it is risky
|
||||
// to assume much about the internals of a hash_code. In particular, each
|
||||
// execution of the program has a high probability of producing a different
|
||||
// hash_code for a given input. Thus their values are not stable to save or
|
||||
// persist, and should only be used during the execution for the
|
||||
// construction of hashing datastructures.
|
||||
//
|
||||
// -- 'hash_value' is a function designed to be overloaded for each
|
||||
// user-defined type which wishes to be used within a hashing context. It
|
||||
// should be overloaded within the user-defined type's namespace and found
|
||||
// via ADL. Overloads for primitive types are provided by this library.
|
||||
//
|
||||
// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid
|
||||
// programmers in easily and intuitively combining a set of data into
|
||||
// a single hash_code for their object. They should only logically be used
|
||||
// within the implementation of a 'hash_value' routine or similar context.
|
||||
//
|
||||
// Note that 'hash_combine_range' contains very special logic for hashing
|
||||
// a contiguous array of integers or pointers. This logic is *extremely* fast,
|
||||
// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were
|
||||
// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys
|
||||
// under 32-bytes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_HASHING_H
|
||||
#define LLVM_ADT_HASHING_H
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/SwapByteOrder.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
// Allow detecting C++11 feature availability when building with Clang without
|
||||
// breaking other compilers.
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief An opaque object representing a hash code.
|
||||
///
|
||||
/// This object represents the result of hashing some entity. It is intended to
|
||||
/// be used to implement hashtables or other hashing-based data structures.
|
||||
/// While it wraps and exposes a numeric value, this value should not be
|
||||
/// trusted to be stable or predictable across processes or executions.
|
||||
///
|
||||
/// In order to obtain the hash_code for an object 'x':
|
||||
/// \code
|
||||
/// using llvm::hash_value;
|
||||
/// llvm::hash_code code = hash_value(x);
|
||||
/// \endcode
|
||||
class hash_code {
|
||||
size_t value;
|
||||
|
||||
public:
|
||||
/// \brief Default construct a hash_code.
|
||||
/// Note that this leaves the value uninitialized.
|
||||
hash_code() {}
|
||||
|
||||
/// \brief Form a hash code directly from a numerical value.
|
||||
hash_code(size_t value) : value(value) {}
|
||||
|
||||
/// \brief Convert the hash code to its numerical value for use.
|
||||
/*explicit*/ operator size_t() const { return value; }
|
||||
|
||||
friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
friend bool operator!=(const hash_code &lhs, const hash_code &rhs) {
|
||||
return lhs.value != rhs.value;
|
||||
}
|
||||
|
||||
/// \brief Allow a hash_code to be directly run through hash_value.
|
||||
friend size_t hash_value(const hash_code &code) { return code.value; }
|
||||
};
|
||||
|
||||
/// \brief Compute a hash_code for any integer value.
|
||||
///
|
||||
/// Note that this function is intended to compute the same hash_code for
|
||||
/// a particular value without regard to the pre-promotion type. This is in
|
||||
/// contrast to hash_combine which may produce different hash_codes for
|
||||
/// differing argument types even if they would implicit promote to a common
|
||||
/// type without changing the value.
|
||||
template <typename T>
|
||||
typename enable_if<is_integral_or_enum<T>, hash_code>::type hash_value(T value);
|
||||
|
||||
/// \brief Compute a hash_code for a pointer's address.
|
||||
///
|
||||
/// N.B.: This hashes the *address*. Not the value and not the type.
|
||||
template <typename T> hash_code hash_value(const T *ptr);
|
||||
|
||||
/// \brief Compute a hash_code for a pair of objects.
|
||||
template <typename T, typename U>
|
||||
hash_code hash_value(const std::pair<T, U> &arg);
|
||||
|
||||
/// \brief Compute a hash_code for a standard string.
|
||||
template <typename T>
|
||||
hash_code hash_value(const std::basic_string<T> &arg);
|
||||
|
||||
|
||||
/// \brief Override the execution seed with a fixed value.
|
||||
///
|
||||
/// This hashing library uses a per-execution seed designed to change on each
|
||||
/// run with high probability in order to ensure that the hash codes are not
|
||||
/// attackable and to ensure that output which is intended to be stable does
|
||||
/// not rely on the particulars of the hash codes produced.
|
||||
///
|
||||
/// That said, there are use cases where it is important to be able to
|
||||
/// reproduce *exactly* a specific behavior. To that end, we provide a function
|
||||
/// which will forcibly set the seed to a fixed value. This must be done at the
|
||||
/// start of the program, before any hashes are computed. Also, it cannot be
|
||||
/// undone. This makes it thread-hostile and very hard to use outside of
|
||||
/// immediately on start of a simple program designed for reproducible
|
||||
/// behavior.
|
||||
void set_fixed_execution_hash_seed(size_t fixed_value);
|
||||
|
||||
|
||||
// All of the implementation details of actually computing the various hash
|
||||
// code values are held within this namespace. These routines are included in
|
||||
// the header file mainly to allow inlining and constant propagation.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
inline uint64_t fetch64(const char *p) {
|
||||
uint64_t result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
if (sys::IsBigEndianHost)
|
||||
return sys::SwapByteOrder(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint32_t fetch32(const char *p) {
|
||||
uint32_t result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
if (sys::IsBigEndianHost)
|
||||
return sys::SwapByteOrder(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Some primes between 2^63 and 2^64 for various uses.
|
||||
static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
|
||||
static const uint64_t k1 = 0xb492b66fbe98f273ULL;
|
||||
static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
|
||||
static const uint64_t k3 = 0xc949d7c7509e6557ULL;
|
||||
|
||||
/// \brief Bitwise right rotate.
|
||||
/// Normally this will compile to a single instruction, especially if the
|
||||
/// shift is a manifest constant.
|
||||
inline uint64_t rotate(uint64_t val, size_t shift) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
inline uint64_t shift_mix(uint64_t val) {
|
||||
return val ^ (val >> 47);
|
||||
}
|
||||
|
||||
inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64_t a = (low ^ high) * kMul;
|
||||
a ^= (a >> 47);
|
||||
uint64_t b = (high ^ a) * kMul;
|
||||
b ^= (b >> 47);
|
||||
b *= kMul;
|
||||
return b;
|
||||
}
|
||||
|
||||
inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint8_t a = s[0];
|
||||
uint8_t b = s[len >> 1];
|
||||
uint8_t c = s[len - 1];
|
||||
uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
|
||||
uint32_t z = len + (static_cast<uint32_t>(c) << 2);
|
||||
return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
|
||||
}
|
||||
|
||||
inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch32(s);
|
||||
return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4));
|
||||
}
|
||||
|
||||
inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch64(s);
|
||||
uint64_t b = fetch64(s + len - 8);
|
||||
return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b;
|
||||
}
|
||||
|
||||
inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch64(s) * k1;
|
||||
uint64_t b = fetch64(s + 8);
|
||||
uint64_t c = fetch64(s + len - 8) * k2;
|
||||
uint64_t d = fetch64(s + len - 16) * k0;
|
||||
return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d,
|
||||
a + rotate(b ^ k3, 20) - c + len + seed);
|
||||
}
|
||||
|
||||
inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t z = fetch64(s + 24);
|
||||
uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
|
||||
uint64_t b = rotate(a + z, 52);
|
||||
uint64_t c = rotate(a, 37);
|
||||
a += fetch64(s + 8);
|
||||
c += rotate(a, 7);
|
||||
a += fetch64(s + 16);
|
||||
uint64_t vf = a + z;
|
||||
uint64_t vs = b + rotate(a, 31) + c;
|
||||
a = fetch64(s + 16) + fetch64(s + len - 32);
|
||||
z = fetch64(s + len - 8);
|
||||
b = rotate(a + z, 52);
|
||||
c = rotate(a, 37);
|
||||
a += fetch64(s + len - 24);
|
||||
c += rotate(a, 7);
|
||||
a += fetch64(s + len - 16);
|
||||
uint64_t wf = a + z;
|
||||
uint64_t ws = b + rotate(a, 31) + c;
|
||||
uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
|
||||
return shift_mix((seed ^ (r * k0)) + vs) * k2;
|
||||
}
|
||||
|
||||
inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
|
||||
if (length >= 4 && length <= 8)
|
||||
return hash_4to8_bytes(s, length, seed);
|
||||
if (length > 8 && length <= 16)
|
||||
return hash_9to16_bytes(s, length, seed);
|
||||
if (length > 16 && length <= 32)
|
||||
return hash_17to32_bytes(s, length, seed);
|
||||
if (length > 32)
|
||||
return hash_33to64_bytes(s, length, seed);
|
||||
if (length != 0)
|
||||
return hash_1to3_bytes(s, length, seed);
|
||||
|
||||
return k2 ^ seed;
|
||||
}
|
||||
|
||||
/// \brief The intermediate state used during hashing.
|
||||
/// Currently, the algorithm for computing hash codes is based on CityHash and
|
||||
/// keeps 56 bytes of arbitrary state.
|
||||
struct hash_state {
|
||||
uint64_t h0, h1, h2, h3, h4, h5, h6;
|
||||
uint64_t seed;
|
||||
|
||||
/// \brief Create a new hash_state structure and initialize it based on the
|
||||
/// seed and the first 64-byte chunk.
|
||||
/// This effectively performs the initial mix.
|
||||
static hash_state create(const char *s, uint64_t seed) {
|
||||
hash_state state = {
|
||||
0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
|
||||
seed * k1, shift_mix(seed), 0, seed };
|
||||
state.h6 = hash_16_bytes(state.h4, state.h5);
|
||||
state.mix(s);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a'
|
||||
/// and 'b', including whatever is already in 'a' and 'b'.
|
||||
static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) {
|
||||
a += fetch64(s);
|
||||
uint64_t c = fetch64(s + 24);
|
||||
b = rotate(b + a + c, 21);
|
||||
uint64_t d = a;
|
||||
a += fetch64(s + 8) + fetch64(s + 16);
|
||||
b += rotate(a, 44) + d;
|
||||
a += c;
|
||||
}
|
||||
|
||||
/// \brief Mix in a 64-byte buffer of data.
|
||||
/// We mix all 64 bytes even when the chunk length is smaller, but we
|
||||
/// record the actual length.
|
||||
void mix(const char *s) {
|
||||
h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
|
||||
h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1;
|
||||
h0 ^= h6;
|
||||
h1 += h3 + fetch64(s + 40);
|
||||
h2 = rotate(h2 + h5, 33) * k1;
|
||||
h3 = h4 * k1;
|
||||
h4 = h0 + h5;
|
||||
mix_32_bytes(s, h3, h4);
|
||||
h5 = h2 + h6;
|
||||
h6 = h1 + fetch64(s + 16);
|
||||
mix_32_bytes(s + 32, h5, h6);
|
||||
std::swap(h2, h0);
|
||||
}
|
||||
|
||||
/// \brief Compute the final 64-bit hash code value based on the current
|
||||
/// state and the length of bytes hashed.
|
||||
uint64_t finalize(size_t length) {
|
||||
return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2,
|
||||
hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief A global, fixed seed-override variable.
|
||||
///
|
||||
/// This variable can be set using the \see llvm::set_fixed_execution_seed
|
||||
/// function. See that function for details. Do not, under any circumstances,
|
||||
/// set or read this variable.
|
||||
extern size_t fixed_seed_override;
|
||||
|
||||
inline size_t get_execution_seed() {
|
||||
// FIXME: This needs to be a per-execution seed. This is just a placeholder
|
||||
// implementation. Switching to a per-execution seed is likely to flush out
|
||||
// instability bugs and so will happen as its own commit.
|
||||
//
|
||||
// However, if there is a fixed seed override set the first time this is
|
||||
// called, return that instead of the per-execution seed.
|
||||
const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
|
||||
static size_t seed = fixed_seed_override ? fixed_seed_override
|
||||
: (size_t)seed_prime;
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Trait to indicate whether a type's bits can be hashed directly.
|
||||
///
|
||||
/// A type trait which is true if we want to combine values for hashing by
|
||||
/// reading the underlying data. It is false if values of this type must
|
||||
/// first be passed to hash_value, and the resulting hash_codes combined.
|
||||
//
|
||||
// FIXME: We want to replace is_integral_or_enum and is_pointer here with
|
||||
// a predicate which asserts that comparing the underlying storage of two
|
||||
// values of the type for equality is equivalent to comparing the two values
|
||||
// for equality. For all the platforms we care about, this holds for integers
|
||||
// and pointers, but there are platforms where it doesn't and we would like to
|
||||
// support user-defined types which happen to satisfy this property.
|
||||
template <typename T> struct is_hashable_data
|
||||
: integral_constant<bool, ((is_integral_or_enum<T>::value ||
|
||||
is_pointer<T>::value) &&
|
||||
64 % sizeof(T) == 0)> {};
|
||||
|
||||
// Special case std::pair to detect when both types are viable and when there
|
||||
// is no alignment-derived padding in the pair. This is a bit of a lie because
|
||||
// std::pair isn't truly POD, but it's close enough in all reasonable
|
||||
// implementations for our use case of hashing the underlying data.
|
||||
template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
|
||||
: integral_constant<bool, (is_hashable_data<T>::value &&
|
||||
is_hashable_data<U>::value &&
|
||||
(sizeof(T) + sizeof(U)) ==
|
||||
sizeof(std::pair<T, U>))> {};
|
||||
|
||||
/// \brief Helper to get the hashable data representation for a type.
|
||||
/// This variant is enabled when the type itself can be used.
|
||||
template <typename T>
|
||||
typename enable_if<is_hashable_data<T>, T>::type
|
||||
get_hashable_data(const T &value) {
|
||||
return value;
|
||||
}
|
||||
/// \brief Helper to get the hashable data representation for a type.
|
||||
/// This variant is enabled when we must first call hash_value and use the
|
||||
/// result as our data.
|
||||
template <typename T>
|
||||
typename enable_if_c<!is_hashable_data<T>::value, size_t>::type
|
||||
get_hashable_data(const T &value) {
|
||||
using ::llvm::hash_value;
|
||||
return hash_value(value);
|
||||
}
|
||||
|
||||
/// \brief Helper to store data from a value into a buffer and advance the
|
||||
/// pointer into that buffer.
|
||||
///
|
||||
/// This routine first checks whether there is enough space in the provided
|
||||
/// buffer, and if not immediately returns false. If there is space, it
|
||||
/// copies the underlying bytes of value into the buffer, advances the
|
||||
/// buffer_ptr past the copied bytes, and returns true.
|
||||
template <typename T>
|
||||
bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
|
||||
size_t offset = 0) {
|
||||
size_t store_size = sizeof(value) - offset;
|
||||
if (buffer_ptr + store_size > buffer_end)
|
||||
return false;
|
||||
const char *value_data = reinterpret_cast<const char *>(&value);
|
||||
memcpy(buffer_ptr, value_data + offset, store_size);
|
||||
buffer_ptr += store_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Implement the combining of integral values into a hash_code.
|
||||
///
|
||||
/// This overload is selected when the value type of the iterator is
|
||||
/// integral. Rather than computing a hash_code for each object and then
|
||||
/// combining them, this (as an optimization) directly combines the integers.
|
||||
template <typename InputIteratorT>
|
||||
hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
|
||||
const size_t seed = get_execution_seed();
|
||||
char buffer[64], *buffer_ptr = buffer;
|
||||
char *const buffer_end = buffer_ptr + array_lengthof(buffer);
|
||||
while (first != last && store_and_advance(buffer_ptr, buffer_end,
|
||||
get_hashable_data(*first)))
|
||||
++first;
|
||||
if (first == last)
|
||||
return hash_short(buffer, buffer_ptr - buffer, seed);
|
||||
assert(buffer_ptr == buffer_end);
|
||||
|
||||
hash_state state = state.create(buffer, seed);
|
||||
size_t length = 64;
|
||||
while (first != last) {
|
||||
// Fill up the buffer. We don't clear it, which re-mixes the last round
|
||||
// when only a partial 64-byte chunk is left.
|
||||
buffer_ptr = buffer;
|
||||
while (first != last && store_and_advance(buffer_ptr, buffer_end,
|
||||
get_hashable_data(*first)))
|
||||
++first;
|
||||
|
||||
// Rotate the buffer if we did a partial fill in order to simulate doing
|
||||
// a mix of the last 64-bytes. That is how the algorithm works when we
|
||||
// have a contiguous byte sequence, and we want to emulate that here.
|
||||
std::rotate(buffer, buffer_ptr, buffer_end);
|
||||
|
||||
// Mix this chunk into the current state.
|
||||
state.mix(buffer);
|
||||
length += buffer_ptr - buffer;
|
||||
};
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
|
||||
/// \brief Implement the combining of integral values into a hash_code.
|
||||
///
|
||||
/// This overload is selected when the value type of the iterator is integral
|
||||
/// and when the input iterator is actually a pointer. Rather than computing
|
||||
/// a hash_code for each object and then combining them, this (as an
|
||||
/// optimization) directly combines the integers. Also, because the integers
|
||||
/// are stored in contiguous memory, this routine avoids copying each value
|
||||
/// and directly reads from the underlying memory.
|
||||
template <typename ValueT>
|
||||
typename enable_if<is_hashable_data<ValueT>, hash_code>::type
|
||||
hash_combine_range_impl(ValueT *first, ValueT *last) {
|
||||
const size_t seed = get_execution_seed();
|
||||
const char *s_begin = reinterpret_cast<const char *>(first);
|
||||
const char *s_end = reinterpret_cast<const char *>(last);
|
||||
const size_t length = std::distance(s_begin, s_end);
|
||||
if (length <= 64)
|
||||
return hash_short(s_begin, length, seed);
|
||||
|
||||
const char *s_aligned_end = s_begin + (length & ~63);
|
||||
hash_state state = state.create(s_begin, seed);
|
||||
s_begin += 64;
|
||||
while (s_begin != s_aligned_end) {
|
||||
state.mix(s_begin);
|
||||
s_begin += 64;
|
||||
}
|
||||
if (length & 63)
|
||||
state.mix(s_end - 64);
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
|
||||
/// \brief Compute a hash_code for a sequence of values.
|
||||
///
|
||||
/// This hashes a sequence of values. It produces the same hash_code as
|
||||
/// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences
|
||||
/// and is significantly faster given pointers and types which can be hashed as
|
||||
/// a sequence of bytes.
|
||||
template <typename InputIteratorT>
|
||||
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
|
||||
return ::llvm::hashing::detail::hash_combine_range_impl(first, last);
|
||||
}
|
||||
|
||||
|
||||
// Implementation details for hash_combine.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
/// \brief Helper class to manage the recursive combining of hash_combine
|
||||
/// arguments.
|
||||
///
|
||||
/// This class exists to manage the state and various calls involved in the
|
||||
/// recursive combining of arguments used in hash_combine. It is particularly
|
||||
/// useful at minimizing the code in the recursive calls to ease the pain
|
||||
/// caused by a lack of variadic functions.
|
||||
struct hash_combine_recursive_helper {
|
||||
char buffer[64];
|
||||
hash_state state;
|
||||
const size_t seed;
|
||||
|
||||
public:
|
||||
/// \brief Construct a recursive hash combining helper.
|
||||
///
|
||||
/// This sets up the state for a recursive hash combine, including getting
|
||||
/// the seed and buffer setup.
|
||||
hash_combine_recursive_helper()
|
||||
: seed(get_execution_seed()) {}
|
||||
|
||||
/// \brief Combine one chunk of data into the current in-flight hash.
|
||||
///
|
||||
/// This merges one chunk of data into the hash. First it tries to buffer
|
||||
/// the data. If the buffer is full, it hashes the buffer into its
|
||||
/// hash_state, empties it, and then merges the new chunk in. This also
|
||||
/// handles cases where the data straddles the end of the buffer.
|
||||
template <typename T>
|
||||
char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
|
||||
if (!store_and_advance(buffer_ptr, buffer_end, data)) {
|
||||
// Check for skew which prevents the buffer from being packed, and do
|
||||
// a partial store into the buffer to fill it. This is only a concern
|
||||
// with the variadic combine because that formation can have varying
|
||||
// argument types.
|
||||
size_t partial_store_size = buffer_end - buffer_ptr;
|
||||
memcpy(buffer_ptr, &data, partial_store_size);
|
||||
|
||||
// If the store fails, our buffer is full and ready to hash. We have to
|
||||
// either initialize the hash state (on the first full buffer) or mix
|
||||
// this buffer into the existing hash state. Length tracks the *hashed*
|
||||
// length, not the buffered length.
|
||||
if (length == 0) {
|
||||
state = state.create(buffer, seed);
|
||||
length = 64;
|
||||
} else {
|
||||
// Mix this chunk into the current state and bump length up by 64.
|
||||
state.mix(buffer);
|
||||
length += 64;
|
||||
}
|
||||
// Reset the buffer_ptr to the head of the buffer for the next chunk of
|
||||
// data.
|
||||
buffer_ptr = buffer;
|
||||
|
||||
// Try again to store into the buffer -- this cannot fail as we only
|
||||
// store types smaller than the buffer.
|
||||
if (!store_and_advance(buffer_ptr, buffer_end, data,
|
||||
partial_store_size))
|
||||
abort();
|
||||
}
|
||||
return buffer_ptr;
|
||||
}
|
||||
|
||||
#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
|
||||
|
||||
/// \brief Recursive, variadic combining method.
|
||||
///
|
||||
/// This function recurses through each argument, combining that argument
|
||||
/// into a single hash.
|
||||
template <typename T, typename ...Ts>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T &arg, const Ts &...args) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
|
||||
|
||||
// Recurse to the next argument.
|
||||
return combine(length, buffer_ptr, buffer_end, args...);
|
||||
}
|
||||
|
||||
#else
|
||||
// Manually expanded recursive combining methods. See variadic above for
|
||||
// documentation.
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2);
|
||||
}
|
||||
template <typename T1>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief Base case for recursive, variadic combining.
|
||||
///
|
||||
/// The base case when combining arguments recursively is reached when all
|
||||
/// arguments have been handled. It flushes the remaining buffer and
|
||||
/// constructs a hash_code.
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
|
||||
// Check whether the entire set of values fit in the buffer. If so, we'll
|
||||
// use the optimized short hashing routine and skip state entirely.
|
||||
if (length == 0)
|
||||
return hash_short(buffer, buffer_ptr - buffer, seed);
|
||||
|
||||
// Mix the final buffer, rotating it if we did a partial fill in order to
|
||||
// simulate doing a mix of the last 64-bytes. That is how the algorithm
|
||||
// works when we have a contiguous byte sequence, and we want to emulate
|
||||
// that here.
|
||||
std::rotate(buffer, buffer_ptr, buffer_end);
|
||||
|
||||
// Mix this chunk into the current state.
|
||||
state.mix(buffer);
|
||||
length += buffer_ptr - buffer;
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
|
||||
#if __has_feature(__cxx_variadic_templates__)
|
||||
|
||||
/// \brief Combine values into a single hash_code.
|
||||
///
|
||||
/// This routine accepts a varying number of arguments of any type. It will
|
||||
/// attempt to combine them into a single hash_code. For user-defined types it
|
||||
/// attempts to call a \see hash_value overload (via ADL) for the type. For
|
||||
/// integer and pointer types it directly combines their data into the
|
||||
/// resulting hash_code.
|
||||
///
|
||||
/// The result is suitable for returning from a user's hash_value
|
||||
/// *implementation* for their user-defined type. Consumers of a type should
|
||||
/// *not* call this routine, they should instead call 'hash_value'.
|
||||
template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
|
||||
// Recursively hash each argument using a helper class.
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// What follows are manually exploded overloads for each argument width. See
|
||||
// the above variadic definition for documentation and specification.
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2);
|
||||
}
|
||||
template <typename T1>
|
||||
hash_code hash_combine(const T1 &arg1) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Implementation details for implementations of hash_value overloads provided
|
||||
// here.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
/// \brief Helper to hash the value of a single integer.
|
||||
///
|
||||
/// Overloads for smaller integer types are not provided to ensure consistent
|
||||
/// behavior in the presence of integral promotions. Essentially,
|
||||
/// "hash_value('4')" and "hash_value('0' + 4)" should be the same.
|
||||
inline hash_code hash_integer_value(uint64_t value) {
|
||||
// Similar to hash_4to8_bytes but using a seed instead of length.
|
||||
const uint64_t seed = get_execution_seed();
|
||||
const char *s = reinterpret_cast<const char *>(&value);
|
||||
const uint64_t a = fetch32(s);
|
||||
return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T>
|
||||
typename enable_if<is_integral_or_enum<T>, hash_code>::type
|
||||
hash_value(T value) {
|
||||
return ::llvm::hashing::detail::hash_integer_value(value);
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T> hash_code hash_value(const T *ptr) {
|
||||
return ::llvm::hashing::detail::hash_integer_value(
|
||||
reinterpret_cast<uintptr_t>(ptr));
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T, typename U>
|
||||
hash_code hash_value(const std::pair<T, U> &arg) {
|
||||
return hash_combine(arg.first, arg.second);
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T>
|
||||
hash_code hash_value(const std::basic_string<T> &arg) {
|
||||
return hash_combine_range(arg.begin(), arg.end());
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
248
thirdparty/clang/include/llvm/ADT/ImmutableIntervalMap.h
vendored
Normal file
248
thirdparty/clang/include/llvm/ADT/ImmutableIntervalMap.h
vendored
Normal file
@@ -0,0 +1,248 @@
|
||||
//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the ImmutableIntervalMap class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H
|
||||
#define LLVM_ADT_IMMUTABLEINTERVALMAP_H
|
||||
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Interval {
|
||||
private:
|
||||
int64_t Start;
|
||||
int64_t End;
|
||||
|
||||
public:
|
||||
Interval(int64_t S, int64_t E) : Start(S), End(E) {}
|
||||
|
||||
int64_t getStart() const { return Start; }
|
||||
int64_t getEnd() const { return End; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ImutIntervalInfo {
|
||||
typedef const std::pair<Interval, T> value_type;
|
||||
typedef const value_type &value_type_ref;
|
||||
typedef const Interval key_type;
|
||||
typedef const Interval &key_type_ref;
|
||||
typedef const T data_type;
|
||||
typedef const T &data_type_ref;
|
||||
|
||||
static key_type_ref KeyOfValue(value_type_ref V) {
|
||||
return V.first;
|
||||
}
|
||||
|
||||
static data_type_ref DataOfValue(value_type_ref V) {
|
||||
return V.second;
|
||||
}
|
||||
|
||||
static bool isEqual(key_type_ref L, key_type_ref R) {
|
||||
return L.getStart() == R.getStart() && L.getEnd() == R.getEnd();
|
||||
}
|
||||
|
||||
static bool isDataEqual(data_type_ref L, data_type_ref R) {
|
||||
return ImutContainerInfo<T>::isEqual(L,R);
|
||||
}
|
||||
|
||||
static bool isLess(key_type_ref L, key_type_ref R) {
|
||||
// Assume L and R does not overlap.
|
||||
if (L.getStart() < R.getStart()) {
|
||||
assert(L.getEnd() < R.getStart());
|
||||
return true;
|
||||
} else if (L.getStart() == R.getStart()) {
|
||||
assert(L.getEnd() == R.getEnd());
|
||||
return false;
|
||||
} else {
|
||||
assert(L.getStart() > R.getEnd());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isContainedIn(key_type_ref K, key_type_ref L) {
|
||||
if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Profile(FoldingSetNodeID &ID, value_type_ref V) {
|
||||
ID.AddInteger(V.first.getStart());
|
||||
ID.AddInteger(V.first.getEnd());
|
||||
ImutProfileInfo<T>::Profile(ID, V.second);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ImutInfo>
|
||||
class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
|
||||
typedef ImutAVLTree<ImutInfo> TreeTy;
|
||||
typedef typename ImutInfo::value_type value_type;
|
||||
typedef typename ImutInfo::value_type_ref value_type_ref;
|
||||
typedef typename ImutInfo::key_type key_type;
|
||||
typedef typename ImutInfo::key_type_ref key_type_ref;
|
||||
typedef typename ImutInfo::data_type data_type;
|
||||
typedef typename ImutInfo::data_type_ref data_type_ref;
|
||||
|
||||
public:
|
||||
ImutIntervalAVLFactory(BumpPtrAllocator &Alloc)
|
||||
: ImutAVLFactory<ImutInfo>(Alloc) {}
|
||||
|
||||
TreeTy *Add(TreeTy *T, value_type_ref V) {
|
||||
T = add_internal(V,T);
|
||||
this->MarkImmutable(T);
|
||||
return T;
|
||||
}
|
||||
|
||||
TreeTy *Find(TreeTy *T, key_type_ref K) {
|
||||
if (!T)
|
||||
return NULL;
|
||||
|
||||
key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T));
|
||||
|
||||
if (ImutInfo::isContainedIn(K, CurrentKey))
|
||||
return T;
|
||||
else if (ImutInfo::isLess(K, CurrentKey))
|
||||
return Find(this->getLeft(T), K);
|
||||
else
|
||||
return Find(this->getRight(T), K);
|
||||
}
|
||||
|
||||
private:
|
||||
TreeTy *add_internal(value_type_ref V, TreeTy *T) {
|
||||
key_type_ref K = ImutInfo::KeyOfValue(V);
|
||||
T = removeAllOverlaps(T, K);
|
||||
if (this->isEmpty(T))
|
||||
return this->CreateNode(NULL, V, NULL);
|
||||
|
||||
assert(!T->isMutable());
|
||||
|
||||
key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
|
||||
|
||||
if (ImutInfo::isLess(K, KCurrent))
|
||||
return this->Balance(add_internal(V, this->Left(T)), this->Value(T),
|
||||
this->Right(T));
|
||||
else
|
||||
return this->Balance(this->Left(T), this->Value(T),
|
||||
add_internal(V, this->Right(T)));
|
||||
}
|
||||
|
||||
// Remove all overlaps from T.
|
||||
TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) {
|
||||
bool Changed;
|
||||
do {
|
||||
Changed = false;
|
||||
T = removeOverlap(T, K, Changed);
|
||||
this->markImmutable(T);
|
||||
} while (Changed);
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
// Remove one overlap from T.
|
||||
TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) {
|
||||
if (!T)
|
||||
return NULL;
|
||||
Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T));
|
||||
|
||||
// If current key does not overlap the inserted key.
|
||||
if (CurrentK.getStart() > K.getEnd())
|
||||
return this->Balance(removeOverlap(this->Left(T), K, Changed),
|
||||
this->Value(T), this->Right(T));
|
||||
else if (CurrentK.getEnd() < K.getStart())
|
||||
return this->Balance(this->Left(T), this->Value(T),
|
||||
removeOverlap(this->Right(T), K, Changed));
|
||||
|
||||
// Current key overlaps with the inserted key.
|
||||
// Remove the current key.
|
||||
Changed = true;
|
||||
data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T));
|
||||
T = this->Remove_internal(CurrentK, T);
|
||||
// Add back the unoverlapped part of the current key.
|
||||
if (CurrentK.getStart() < K.getStart()) {
|
||||
if (CurrentK.getEnd() <= K.getEnd()) {
|
||||
Interval NewK(CurrentK.getStart(), K.getStart()-1);
|
||||
return add_internal(std::make_pair(NewK, OldData), T);
|
||||
} else {
|
||||
Interval NewK1(CurrentK.getStart(), K.getStart()-1);
|
||||
T = add_internal(std::make_pair(NewK1, OldData), T);
|
||||
|
||||
Interval NewK2(K.getEnd()+1, CurrentK.getEnd());
|
||||
return add_internal(std::make_pair(NewK2, OldData), T);
|
||||
}
|
||||
} else {
|
||||
if (CurrentK.getEnd() > K.getEnd()) {
|
||||
Interval NewK(K.getEnd()+1, CurrentK.getEnd());
|
||||
return add_internal(std::make_pair(NewK, OldData), T);
|
||||
} else
|
||||
return T;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals
|
||||
/// in the map are guaranteed to be disjoint.
|
||||
template <typename ValT>
|
||||
class ImmutableIntervalMap
|
||||
: public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > {
|
||||
|
||||
typedef typename ImutIntervalInfo<ValT>::value_type value_type;
|
||||
typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref;
|
||||
typedef typename ImutIntervalInfo<ValT>::key_type key_type;
|
||||
typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref;
|
||||
typedef typename ImutIntervalInfo<ValT>::data_type data_type;
|
||||
typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref;
|
||||
typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy;
|
||||
|
||||
public:
|
||||
explicit ImmutableIntervalMap(TreeTy *R)
|
||||
: ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {}
|
||||
|
||||
class Factory {
|
||||
ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F;
|
||||
|
||||
public:
|
||||
Factory(BumpPtrAllocator& Alloc) : F(Alloc) {}
|
||||
|
||||
ImmutableIntervalMap getEmptyMap() {
|
||||
return ImmutableIntervalMap(F.getEmptyTree());
|
||||
}
|
||||
|
||||
ImmutableIntervalMap add(ImmutableIntervalMap Old,
|
||||
key_type_ref K, data_type_ref D) {
|
||||
TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D));
|
||||
return ImmutableIntervalMap(F.getCanonicalTree(T));
|
||||
}
|
||||
|
||||
ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) {
|
||||
TreeTy *T = F.remove(Old.Root, K);
|
||||
return ImmutableIntervalMap(F.getCanonicalTree(T));
|
||||
}
|
||||
|
||||
data_type *lookup(ImmutableIntervalMap M, key_type_ref K) {
|
||||
TreeTy *T = F.Find(M.getRoot(), K);
|
||||
if (T)
|
||||
return &T->getValue().second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// For ImmutableIntervalMap, the lookup operation has to be done by the
|
||||
// factory.
|
||||
data_type* lookup(key_type_ref K) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
229
thirdparty/clang/include/llvm/ADT/ImmutableList.h
vendored
Normal file
229
thirdparty/clang/include/llvm/ADT/ImmutableList.h
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
//==--- 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_IMMUTABLELIST_H
|
||||
#define LLVM_ADT_IMMUTABLELIST_H
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Allocator.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>;
|
||||
|
||||
void operator=(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
|
||||
ImmutableListImpl(const ImmutableListImpl&) LLVM_DELETED_FUNCTION;
|
||||
|
||||
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; }
|
||||
|
||||
bool contains(const T& V) const {
|
||||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||
if (*I == V)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template <typename T>
|
||||
struct isPodLike<ImmutableList<T> > { static const bool value = true; };
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
438
thirdparty/clang/include/llvm/ADT/ImmutableMap.h
vendored
Normal file
438
thirdparty/clang/include/llvm/ADT/ImmutableMap.h
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
//===--- 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_IMMUTABLEMAP_H
|
||||
#define LLVM_ADT_IMMUTABLEMAP_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;
|
||||
|
||||
protected:
|
||||
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)) {
|
||||
if (Root) { Root->retain(); }
|
||||
}
|
||||
ImmutableMap(const ImmutableMap &X) : Root(X.Root) {
|
||||
if (Root) { Root->retain(); }
|
||||
}
|
||||
ImmutableMap &operator=(const ImmutableMap &X) {
|
||||
if (Root != X.Root) {
|
||||
if (X.Root) { X.Root->retain(); }
|
||||
if (Root) { Root->release(); }
|
||||
Root = X.Root;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~ImmutableMap() {
|
||||
if (Root) { Root->release(); }
|
||||
}
|
||||
|
||||
class Factory {
|
||||
typename TreeTy::Factory F;
|
||||
const bool Canonicalize;
|
||||
|
||||
public:
|
||||
Factory(bool canonicalize = true)
|
||||
: Canonicalize(canonicalize) {}
|
||||
|
||||
Factory(BumpPtrAllocator& Alloc, bool canonicalize = true)
|
||||
: F(Alloc), Canonicalize(canonicalize) {}
|
||||
|
||||
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
|
||||
|
||||
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
|
||||
TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D));
|
||||
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
|
||||
}
|
||||
|
||||
ImmutableMap remove(ImmutableMap Old, key_type_ref K) {
|
||||
TreeTy *T = F.remove(Old.Root,K);
|
||||
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
|
||||
}
|
||||
|
||||
typename TreeTy::Factory *getTreeFactory() const {
|
||||
return const_cast<typename TreeTy::Factory *>(&F);
|
||||
}
|
||||
|
||||
private:
|
||||
Factory(const Factory& RHS) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const Factory& RHS) LLVM_DELETED_FUNCTION;
|
||||
};
|
||||
|
||||
bool contains(key_type_ref K) const {
|
||||
return Root ? Root->contains(K) : false;
|
||||
}
|
||||
|
||||
bool operator==(const ImmutableMap &RHS) const {
|
||||
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
|
||||
}
|
||||
|
||||
bool operator!=(const ImmutableMap &RHS) const {
|
||||
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
|
||||
}
|
||||
|
||||
TreeTy *getRoot() const {
|
||||
if (Root) { Root->retain(); }
|
||||
return Root;
|
||||
}
|
||||
|
||||
TreeTy *getRootWithoutRetain() const {
|
||||
return Root;
|
||||
}
|
||||
|
||||
void manualRetain() {
|
||||
if (Root) Root->retain();
|
||||
}
|
||||
|
||||
void manualRelease() {
|
||||
if (Root) Root->release();
|
||||
}
|
||||
|
||||
bool isEmpty() const { return !Root; }
|
||||
|
||||
//===--------------------------------------------------===//
|
||||
// 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:
|
||||
typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type value_type;
|
||||
typedef typename ImmutableMap<KeyT,ValT,ValInfo>::value_type_ref reference;
|
||||
typedef typename iterator::value_type *pointer;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
typename iterator::reference operator*() const { return itr->getValue(); }
|
||||
typename iterator::pointer operator->() const { return &itr->getValue(); }
|
||||
|
||||
key_type_ref getKey() const { return itr->getValue().first; }
|
||||
data_type_ref getData() const { return itr->getValue().second; }
|
||||
|
||||
iterator& operator++() { ++itr; return *this; }
|
||||
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
|
||||
iterator& operator--() { --itr; return *this; }
|
||||
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
|
||||
|
||||
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
|
||||
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
|
||||
};
|
||||
|
||||
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.
|
||||
//===--------------------------------------------------===//
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: This will possibly become the new implementation of ImmutableMap some day.
|
||||
template <typename KeyT, typename ValT,
|
||||
typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
|
||||
class ImmutableMapRef {
|
||||
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;
|
||||
typedef typename TreeTy::Factory FactoryTy;
|
||||
|
||||
protected:
|
||||
TreeTy *Root;
|
||||
FactoryTy *Factory;
|
||||
|
||||
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 ImmutableMapRef(const TreeTy* R, FactoryTy *F)
|
||||
: Root(const_cast<TreeTy*>(R)),
|
||||
Factory(F) {
|
||||
if (Root) { Root->retain(); }
|
||||
}
|
||||
|
||||
explicit ImmutableMapRef(const ImmutableMap<KeyT, ValT> &X,
|
||||
typename ImmutableMap<KeyT, ValT>::Factory &F)
|
||||
: Root(X.getRootWithoutRetain()),
|
||||
Factory(F.getTreeFactory()) {
|
||||
if (Root) { Root->retain(); }
|
||||
}
|
||||
|
||||
ImmutableMapRef(const ImmutableMapRef &X)
|
||||
: Root(X.Root),
|
||||
Factory(X.Factory) {
|
||||
if (Root) { Root->retain(); }
|
||||
}
|
||||
|
||||
ImmutableMapRef &operator=(const ImmutableMapRef &X) {
|
||||
if (Root != X.Root) {
|
||||
if (X.Root)
|
||||
X.Root->retain();
|
||||
|
||||
if (Root)
|
||||
Root->release();
|
||||
|
||||
Root = X.Root;
|
||||
Factory = X.Factory;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ImmutableMapRef() {
|
||||
if (Root)
|
||||
Root->release();
|
||||
}
|
||||
|
||||
static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
|
||||
return ImmutableMapRef(0, F);
|
||||
}
|
||||
|
||||
void manualRetain() {
|
||||
if (Root) Root->retain();
|
||||
}
|
||||
|
||||
void manualRelease() {
|
||||
if (Root) Root->release();
|
||||
}
|
||||
|
||||
ImmutableMapRef add(key_type_ref K, data_type_ref D) const {
|
||||
TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D));
|
||||
return ImmutableMapRef(NewT, Factory);
|
||||
}
|
||||
|
||||
ImmutableMapRef remove(key_type_ref K) const {
|
||||
TreeTy *NewT = Factory->remove(Root, K);
|
||||
return ImmutableMapRef(NewT, Factory);
|
||||
}
|
||||
|
||||
bool contains(key_type_ref K) const {
|
||||
return Root ? Root->contains(K) : false;
|
||||
}
|
||||
|
||||
ImmutableMap<KeyT, ValT> asImmutableMap() const {
|
||||
return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root));
|
||||
}
|
||||
|
||||
bool operator==(const ImmutableMapRef &RHS) const {
|
||||
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
|
||||
}
|
||||
|
||||
bool operator!=(const ImmutableMapRef &RHS) const {
|
||||
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
|
||||
}
|
||||
|
||||
bool isEmpty() const { return !Root; }
|
||||
|
||||
//===--------------------------------------------------===//
|
||||
// For testing.
|
||||
//===--------------------------------------------------===//
|
||||
|
||||
void verify() const { if (Root) Root->verify(); }
|
||||
|
||||
//===--------------------------------------------------===//
|
||||
// Iterators.
|
||||
//===--------------------------------------------------===//
|
||||
|
||||
class iterator {
|
||||
typename TreeTy::iterator itr;
|
||||
|
||||
iterator() {}
|
||||
iterator(TreeTy* t) : itr(t) {}
|
||||
friend class ImmutableMapRef;
|
||||
|
||||
public:
|
||||
value_type_ref operator*() const { return itr->getValue(); }
|
||||
value_type* operator->() const { return &itr->getValue(); }
|
||||
|
||||
key_type_ref getKey() const { return itr->getValue().first; }
|
||||
data_type_ref getData() const { return itr->getValue().second; }
|
||||
|
||||
|
||||
iterator& operator++() { ++itr; return *this; }
|
||||
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
|
||||
iterator& operator--() { --itr; return *this; }
|
||||
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
|
||||
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
|
||||
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
|
||||
};
|
||||
|
||||
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.
|
||||
//===--------------------------------------------------===//
|
||||
|
||||
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
|
||||
|
||||
static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) {
|
||||
ID.AddPointer(M.Root);
|
||||
}
|
||||
|
||||
inline void Profile(FoldingSetNodeID& ID) const {
|
||||
return Profile(ID, *this);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
1232
thirdparty/clang/include/llvm/ADT/ImmutableSet.h
vendored
Normal file
1232
thirdparty/clang/include/llvm/ADT/ImmutableSet.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
77
thirdparty/clang/include/llvm/ADT/InMemoryStruct.h
vendored
Normal file
77
thirdparty/clang/include/llvm/ADT/InMemoryStruct.h
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_INMEMORYSTRUCT_H
|
||||
#define LLVM_ADT_INMEMORYSTRUCT_H
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Helper object for abstracting access to an in-memory structure which
|
||||
/// may require some kind of temporary storage.
|
||||
///
|
||||
/// This class is designed to be used for accessing file data structures which
|
||||
/// in the common case can be accessed from a direct pointer to a memory mapped
|
||||
/// object, but which in some cases may require indirect access to a temporary
|
||||
/// structure (which, for example, may have undergone endianness translation).
|
||||
template<typename T>
|
||||
class InMemoryStruct {
|
||||
typedef T value_type;
|
||||
typedef value_type &reference;
|
||||
typedef value_type *pointer;
|
||||
typedef const value_type &const_reference;
|
||||
typedef const value_type *const_pointer;
|
||||
|
||||
/// \brief The smart pointer target.
|
||||
value_type *Target;
|
||||
|
||||
/// \brief A temporary object which can be used as a target of the smart
|
||||
/// pointer.
|
||||
value_type Contents;
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
InMemoryStruct() : Target(0) {}
|
||||
InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {}
|
||||
InMemoryStruct(pointer Value) : Target(Value) {}
|
||||
InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; }
|
||||
|
||||
void operator=(const InMemoryStruct<T> &Value) {
|
||||
if (Value.Target != &Value.Contents) {
|
||||
Target = Value.Target;
|
||||
} else {
|
||||
Target = &Contents;
|
||||
Contents = Value.Contents;
|
||||
}
|
||||
}
|
||||
|
||||
const_reference operator*() const {
|
||||
assert(Target && "Cannot dereference null pointer");
|
||||
return *Target;
|
||||
}
|
||||
reference operator*() {
|
||||
assert(Target && "Cannot dereference null pointer");
|
||||
return *Target;
|
||||
}
|
||||
|
||||
const_pointer operator->() const {
|
||||
return Target;
|
||||
}
|
||||
pointer operator->() {
|
||||
return Target;
|
||||
}
|
||||
|
||||
operator bool() const { return Target != 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
82
thirdparty/clang/include/llvm/ADT/IndexedMap.h
vendored
Normal file
82
thirdparty/clang/include/llvm/ADT/IndexedMap.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
//===- 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 "llvm/ADT/STLExtras.h"
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename T, typename ToIndexT = llvm::identity<unsigned> >
|
||||
class IndexedMap {
|
||||
typedef typename ToIndexT::argument_type IndexT;
|
||||
typedef std::vector<T> StorageT;
|
||||
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 reserve(typename StorageT::size_type s) {
|
||||
storage_.reserve(s);
|
||||
}
|
||||
|
||||
void resize(typename StorageT::size_type s) {
|
||||
storage_.resize(s, nullVal_);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
storage_.clear();
|
||||
}
|
||||
|
||||
void grow(IndexT n) {
|
||||
unsigned NewSize = toIndex_(n) + 1;
|
||||
if (NewSize > storage_.size())
|
||||
resize(NewSize);
|
||||
}
|
||||
|
||||
bool inBounds(IndexT n) const {
|
||||
return toIndex_(n) < storage_.size();
|
||||
}
|
||||
|
||||
typename StorageT::size_type size() const {
|
||||
return storage_.size();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
88
thirdparty/clang/include/llvm/ADT/IntEqClasses.h
vendored
Normal file
88
thirdparty/clang/include/llvm/ADT/IntEqClasses.h
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
//===-- llvm/ADT/IntEqClasses.h - Equiv. Classes of Integers ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Equivalence classes for small integers. This is a mapping of the integers
|
||||
// 0 .. N-1 into M equivalence classes numbered 0 .. M-1.
|
||||
//
|
||||
// Initially each integer has its own equivalence class. Classes are joined by
|
||||
// passing a representative member of each class to join().
|
||||
//
|
||||
// Once the classes are built, compress() will number them 0 .. M-1 and prevent
|
||||
// further changes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_INTEQCLASSES_H
|
||||
#define LLVM_ADT_INTEQCLASSES_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class IntEqClasses {
|
||||
/// EC - When uncompressed, map each integer to a smaller member of its
|
||||
/// equivalence class. The class leader is the smallest member and maps to
|
||||
/// itself.
|
||||
///
|
||||
/// When compressed, EC[i] is the equivalence class of i.
|
||||
SmallVector<unsigned, 8> EC;
|
||||
|
||||
/// NumClasses - The number of equivalence classes when compressed, or 0 when
|
||||
/// uncompressed.
|
||||
unsigned NumClasses;
|
||||
|
||||
public:
|
||||
/// IntEqClasses - Create an equivalence class mapping for 0 .. N-1.
|
||||
IntEqClasses(unsigned N = 0) : NumClasses(0) { grow(N); }
|
||||
|
||||
/// grow - Increase capacity to hold 0 .. N-1, putting new integers in unique
|
||||
/// equivalence classes.
|
||||
/// This requires an uncompressed map.
|
||||
void grow(unsigned N);
|
||||
|
||||
/// clear - Clear all classes so that grow() will assign a unique class to
|
||||
/// every integer.
|
||||
void clear() {
|
||||
EC.clear();
|
||||
NumClasses = 0;
|
||||
}
|
||||
|
||||
/// join - Join the equivalence classes of a and b. After joining classes,
|
||||
/// findLeader(a) == findLeader(b).
|
||||
/// This requires an uncompressed map.
|
||||
void join(unsigned a, unsigned b);
|
||||
|
||||
/// findLeader - Compute the leader of a's equivalence class. This is the
|
||||
/// smallest member of the class.
|
||||
/// This requires an uncompressed map.
|
||||
unsigned findLeader(unsigned a) const;
|
||||
|
||||
/// compress - Compress equivalence classes by numbering them 0 .. M.
|
||||
/// This makes the equivalence class map immutable.
|
||||
void compress();
|
||||
|
||||
/// getNumClasses - Return the number of equivalence classes after compress()
|
||||
/// was called.
|
||||
unsigned getNumClasses() const { return NumClasses; }
|
||||
|
||||
/// operator[] - Return a's equivalence class number, 0 .. getNumClasses()-1.
|
||||
/// This requires a compressed map.
|
||||
unsigned operator[](unsigned a) const {
|
||||
assert(NumClasses && "operator[] called before compress()");
|
||||
return EC[a];
|
||||
}
|
||||
|
||||
/// uncompress - Change back to the uncompressed representation that allows
|
||||
/// editing.
|
||||
void uncompress();
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
2166
thirdparty/clang/include/llvm/ADT/IntervalMap.h
vendored
Normal file
2166
thirdparty/clang/include/llvm/ADT/IntervalMap.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
243
thirdparty/clang/include/llvm/ADT/IntrusiveRefCntPtr.h
vendored
Normal file
243
thirdparty/clang/include/llvm/ADT/IntrusiveRefCntPtr.h
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
//== 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_INTRUSIVEREFCNTPTR_H
|
||||
#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
|
||||
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <memory>
|
||||
|
||||
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 IntrusiveRefCntPtr "smart pointers" (see below)
|
||||
/// which automatically handle the management of reference counts.
|
||||
/// Objects that subclass RefCountedBase should not be allocated on
|
||||
/// the stack, as invoking "delete" (which is called when the
|
||||
/// reference count hits 0) on such objects is an error.
|
||||
//===----------------------------------------------------------------------===//
|
||||
template <class Derived>
|
||||
class RefCountedBase {
|
||||
mutable unsigned ref_cnt;
|
||||
|
||||
public:
|
||||
RefCountedBase() : ref_cnt(0) {}
|
||||
RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
|
||||
|
||||
void Retain() const { ++ref_cnt; }
|
||||
void Release() const {
|
||||
assert (ref_cnt > 0 && "Reference count is already zero.");
|
||||
if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// RefCountedBaseVPTR - A class that has the same function as
|
||||
/// RefCountedBase, but with a virtual destructor. Should be used
|
||||
/// instead of RefCountedBase for classes that already have virtual
|
||||
/// methods to enforce dynamic allocation via 'new'. Classes that
|
||||
/// inherit from RefCountedBaseVPTR can't be allocated on stack -
|
||||
/// attempting to do this will produce a compile error.
|
||||
//===----------------------------------------------------------------------===//
|
||||
class RefCountedBaseVPTR {
|
||||
mutable unsigned ref_cnt;
|
||||
virtual void anchor();
|
||||
|
||||
protected:
|
||||
RefCountedBaseVPTR() : ref_cnt(0) {}
|
||||
RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
|
||||
|
||||
virtual ~RefCountedBaseVPTR() {}
|
||||
|
||||
void Retain() const { ++ref_cnt; }
|
||||
void Release() const {
|
||||
assert (ref_cnt > 0 && "Reference count is already zero.");
|
||||
if (--ref_cnt == 0) delete this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
friend struct IntrusiveRefCntPtrInfo;
|
||||
};
|
||||
|
||||
|
||||
template <typename T> struct IntrusiveRefCntPtrInfo {
|
||||
static void retain(T *obj) { obj->Retain(); }
|
||||
static void release(T *obj) { obj->Release(); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// 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) {}
|
||||
|
||||
IntrusiveRefCntPtr(T* obj) : Obj(obj) {
|
||||
retain();
|
||||
}
|
||||
|
||||
IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
|
||||
retain();
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
|
||||
S.Obj = 0;
|
||||
}
|
||||
|
||||
template <class X>
|
||||
IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) {
|
||||
S.Obj = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X>
|
||||
IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
|
||||
: Obj(S.getPtr()) {
|
||||
retain();
|
||||
}
|
||||
|
||||
IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
|
||||
swap(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;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
release();
|
||||
Obj = 0;
|
||||
}
|
||||
|
||||
void resetWithoutRelease() {
|
||||
Obj = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
|
||||
void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
|
||||
};
|
||||
|
||||
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(IntrusiveRefCntPtr<T>& Val) {
|
||||
return Val.getPtr();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
|
||||
typedef /*const*/ T* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
|
||||
return Val.getPtr();
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H
|
||||
132
thirdparty/clang/include/llvm/ADT/MapVector.h
vendored
Normal file
132
thirdparty/clang/include/llvm/ADT/MapVector.h
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
//===- llvm/ADT/MapVector.h - Map with deterministic value order *- 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 map that provides insertion order iteration. The
|
||||
// interface is purposefully minimal. The key is assumed to be cheap to copy
|
||||
// and 2 copies are kept, one for indexing in a DenseMap, one for iteration in
|
||||
// a std::vector.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_MAPVECTOR_H
|
||||
#define LLVM_ADT_MAPVECTOR_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// This class implements a map that also provides access to all stored values
|
||||
/// in a deterministic order. The values are kept in a std::vector and the
|
||||
/// mapping is done with DenseMap from Keys to indexes in that vector.
|
||||
template<typename KeyT, typename ValueT,
|
||||
typename MapType = llvm::DenseMap<KeyT, unsigned>,
|
||||
typename VectorType = std::vector<std::pair<KeyT, ValueT> > >
|
||||
class MapVector {
|
||||
typedef typename VectorType::size_type SizeType;
|
||||
|
||||
MapType Map;
|
||||
VectorType Vector;
|
||||
|
||||
public:
|
||||
typedef typename VectorType::iterator iterator;
|
||||
typedef typename VectorType::const_iterator const_iterator;
|
||||
|
||||
SizeType size() const {
|
||||
return Vector.size();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return Vector.begin();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return Vector.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return Vector.end();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return Vector.end();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return Vector.empty();
|
||||
}
|
||||
|
||||
std::pair<KeyT, ValueT> &front() { return Vector.front(); }
|
||||
const std::pair<KeyT, ValueT> &front() const { return Vector.front(); }
|
||||
std::pair<KeyT, ValueT> &back() { return Vector.back(); }
|
||||
const std::pair<KeyT, ValueT> &back() const { return Vector.back(); }
|
||||
|
||||
void clear() {
|
||||
Map.clear();
|
||||
Vector.clear();
|
||||
}
|
||||
|
||||
ValueT &operator[](const KeyT &Key) {
|
||||
std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
|
||||
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
|
||||
unsigned &I = Result.first->second;
|
||||
if (Result.second) {
|
||||
Vector.push_back(std::make_pair(Key, ValueT()));
|
||||
I = Vector.size() - 1;
|
||||
}
|
||||
return Vector[I].second;
|
||||
}
|
||||
|
||||
ValueT lookup(const KeyT &Key) const {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
|
||||
std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
|
||||
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
|
||||
unsigned &I = Result.first->second;
|
||||
if (Result.second) {
|
||||
Vector.push_back(std::make_pair(KV.first, KV.second));
|
||||
I = Vector.size() - 1;
|
||||
return std::make_pair(llvm::prior(end()), true);
|
||||
}
|
||||
return std::make_pair(begin() + I, false);
|
||||
}
|
||||
|
||||
unsigned count(const KeyT &Key) const {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
return Pos == Map.end()? 0 : 1;
|
||||
}
|
||||
|
||||
iterator find(const KeyT &Key) {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
return Pos == Map.end()? Vector.end() :
|
||||
(Vector.begin() + Pos->second);
|
||||
}
|
||||
|
||||
const_iterator find(const KeyT &Key) const {
|
||||
typename MapType::const_iterator Pos = Map.find(Key);
|
||||
return Pos == Map.end()? Vector.end() :
|
||||
(Vector.begin() + Pos->second);
|
||||
}
|
||||
|
||||
/// \brief Remove the last element from the vector.
|
||||
void pop_back() {
|
||||
typename MapType::iterator Pos = Map.find(Vector.back().first);
|
||||
Map.erase(Pos);
|
||||
Vector.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
27
thirdparty/clang/include/llvm/ADT/None.h
vendored
Normal file
27
thirdparty/clang/include/llvm/ADT/None.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- None.h - Simple null value for implicit construction ------*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides None, an enumerator for use in implicit constructors
|
||||
// of various (usually templated) types to make such construction more
|
||||
// terse.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_NONE_H
|
||||
#define LLVM_ADT_NONE_H
|
||||
|
||||
namespace llvm {
|
||||
/// \brief A simple null object to allow implicit construction of Optional<T>
|
||||
/// and similar types without having to spell out the specialization's name.
|
||||
enum NoneType {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
52
thirdparty/clang/include/llvm/ADT/NullablePtr.h
vendored
Normal file
52
thirdparty/clang/include/llvm/ADT/NullablePtr.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
//===- llvm/ADT/NullablePtr.h - A pointer that allows null ------*- 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 NullablePtr class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_NULLABLEPTR_H
|
||||
#define LLVM_ADT_NULLABLEPTR_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace llvm {
|
||||
/// NullablePtr pointer wrapper - NullablePtr is used for APIs where a
|
||||
/// potentially-null pointer gets passed around that must be explicitly handled
|
||||
/// in lots of places. By putting a wrapper around the null pointer, it makes
|
||||
/// it more likely that the null pointer case will be handled correctly.
|
||||
template<class T>
|
||||
class NullablePtr {
|
||||
T *Ptr;
|
||||
public:
|
||||
NullablePtr(T *P = 0) : Ptr(P) {}
|
||||
|
||||
bool isNull() const { return Ptr == 0; }
|
||||
bool isNonNull() const { return Ptr != 0; }
|
||||
|
||||
/// get - Return the pointer if it is non-null.
|
||||
const T *get() const {
|
||||
assert(Ptr && "Pointer wasn't checked for null!");
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
/// get - Return the pointer if it is non-null.
|
||||
T *get() {
|
||||
assert(Ptr && "Pointer wasn't checked for null!");
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
T *getPtrOrNull() { return Ptr; }
|
||||
const T *getPtrOrNull() const { return Ptr; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
193
thirdparty/clang/include/llvm/ADT/Optional.h
vendored
Normal file
193
thirdparty/clang/include/llvm/ADT/Optional.h
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
//===-- Optional.h - Simple variant for passing optional values ---*- 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 Optional, a template class modeled in the spirit of
|
||||
// OCaml's 'opt' variant. The idea is to strongly type whether or not
|
||||
// a value can be optional.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_OPTIONAL_H
|
||||
#define LLVM_ADT_OPTIONAL_H
|
||||
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/AlignOf.h"
|
||||
#include <cassert>
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename T>
|
||||
class Optional {
|
||||
AlignedCharArrayUnion<T> storage;
|
||||
bool hasVal;
|
||||
public:
|
||||
Optional(NoneType) : hasVal(false) {}
|
||||
explicit Optional() : hasVal(false) {}
|
||||
Optional(const T &y) : hasVal(true) {
|
||||
new (storage.buffer) T(y);
|
||||
}
|
||||
Optional(const Optional &O) : hasVal(O.hasVal) {
|
||||
if (hasVal)
|
||||
new (storage.buffer) T(*O);
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
Optional(T &&y) : hasVal(true) {
|
||||
new (storage.buffer) T(std::forward<T>(y));
|
||||
}
|
||||
Optional(Optional<T> &&O) : hasVal(O) {
|
||||
if (O) {
|
||||
new (storage.buffer) T(std::move(*O));
|
||||
O.reset();
|
||||
}
|
||||
}
|
||||
Optional &operator=(T &&y) {
|
||||
if (hasVal)
|
||||
**this = std::move(y);
|
||||
else {
|
||||
new (storage.buffer) T(std::move(y));
|
||||
hasVal = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Optional &operator=(Optional &&O) {
|
||||
if (!O)
|
||||
reset();
|
||||
else {
|
||||
*this = std::move(*O);
|
||||
O.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline Optional create(const T* y) {
|
||||
return y ? Optional(*y) : Optional();
|
||||
}
|
||||
|
||||
// FIXME: these assignments (& the equivalent const T&/const Optional& ctors)
|
||||
// could be made more efficient by passing by value, possibly unifying them
|
||||
// with the rvalue versions above - but this could place a different set of
|
||||
// requirements (notably: the existence of a default ctor) when implemented
|
||||
// in that way. Careful SFINAE to avoid such pitfalls would be required.
|
||||
Optional &operator=(const T &y) {
|
||||
if (hasVal)
|
||||
**this = y;
|
||||
else {
|
||||
new (storage.buffer) T(y);
|
||||
hasVal = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Optional &operator=(const Optional &O) {
|
||||
if (!O)
|
||||
reset();
|
||||
else
|
||||
*this = *O;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (hasVal) {
|
||||
(**this).~T();
|
||||
hasVal = false;
|
||||
}
|
||||
}
|
||||
|
||||
~Optional() {
|
||||
reset();
|
||||
}
|
||||
|
||||
const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
|
||||
T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
|
||||
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
T& getValue() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
|
||||
LLVM_EXPLICIT operator bool() const { return hasVal; }
|
||||
bool hasValue() const { return hasVal; }
|
||||
const T* operator->() const { return getPointer(); }
|
||||
T* operator->() { return getPointer(); }
|
||||
const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCE_THIS
|
||||
T&& getValue() && { assert(hasVal); return std::move(*getPointer()); }
|
||||
T&& operator*() && { assert(hasVal); return std::move(*getPointer()); }
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template <typename T> struct isPodLike<Optional<T> > {
|
||||
// An Optional<T> is pod-like if T is.
|
||||
static const bool value = isPodLike<T>::value;
|
||||
};
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator==(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator!=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator<(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator<=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator>=(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
/// \brief Poison comparison between two \c Optional objects. Clients needs to
|
||||
/// explicitly compare the underlying values and account for empty \c Optional
|
||||
/// objects.
|
||||
///
|
||||
/// This routine will never be defined. It returns \c void to help diagnose
|
||||
/// errors at compile time.
|
||||
template<typename T, typename U>
|
||||
void operator>(const Optional<T> &X, const Optional<U> &Y);
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
152
thirdparty/clang/include/llvm/ADT/OwningPtr.h
vendored
Normal file
152
thirdparty/clang/include/llvm/ADT/OwningPtr.h
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
//===- 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_OWNINGPTR_H
|
||||
#define LLVM_ADT_OWNINGPTR_H
|
||||
|
||||
#include "llvm/Support/Compiler.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 &) LLVM_DELETED_FUNCTION;
|
||||
OwningPtr &operator=(OwningPtr const &) LLVM_DELETED_FUNCTION;
|
||||
T *Ptr;
|
||||
public:
|
||||
explicit OwningPtr(T *P = 0) : Ptr(P) {}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
OwningPtr(OwningPtr &&Other) : Ptr(Other.take()) {}
|
||||
|
||||
OwningPtr &operator=(OwningPtr &&Other) {
|
||||
reset(Other.take());
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
~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 &) LLVM_DELETED_FUNCTION;
|
||||
OwningArrayPtr &operator=(OwningArrayPtr const &) LLVM_DELETED_FUNCTION;
|
||||
T *Ptr;
|
||||
public:
|
||||
explicit OwningArrayPtr(T *P = 0) : Ptr(P) {}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
OwningArrayPtr(OwningArrayPtr &&Other) : Ptr(Other.take()) {}
|
||||
|
||||
OwningArrayPtr &operator=(OwningArrayPtr &&Other) {
|
||||
reset(Other.take());
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
~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
|
||||
159
thirdparty/clang/include/llvm/ADT/PackedVector.h
vendored
Normal file
159
thirdparty/clang/include/llvm/ADT/PackedVector.h
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
//===- llvm/ADT/PackedVector.h - Packed values 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 implements the PackedVector class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_PACKEDVECTOR_H
|
||||
#define LLVM_ADT_PACKEDVECTOR_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include <limits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned>
|
||||
class PackedVectorBase;
|
||||
|
||||
// This won't be necessary if we can specialize members without specializing
|
||||
// the parent template.
|
||||
template <typename T, unsigned BitNum, typename BitVectorTy>
|
||||
class PackedVectorBase<T, BitNum, BitVectorTy, false> {
|
||||
protected:
|
||||
static T getValue(const BitVectorTy &Bits, unsigned Idx) {
|
||||
T val = T();
|
||||
for (unsigned i = 0; i != BitNum; ++i)
|
||||
val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
|
||||
return val;
|
||||
}
|
||||
|
||||
static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
|
||||
assert((val >> BitNum) == 0 && "value is too big");
|
||||
for (unsigned i = 0; i != BitNum; ++i)
|
||||
Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, unsigned BitNum, typename BitVectorTy>
|
||||
class PackedVectorBase<T, BitNum, BitVectorTy, true> {
|
||||
protected:
|
||||
static T getValue(const BitVectorTy &Bits, unsigned Idx) {
|
||||
T val = T();
|
||||
for (unsigned i = 0; i != BitNum-1; ++i)
|
||||
val = T(val | ((Bits[(Idx << (BitNum-1)) + i] ? 1UL : 0UL) << i));
|
||||
if (Bits[(Idx << (BitNum-1)) + BitNum-1])
|
||||
val = ~val;
|
||||
return val;
|
||||
}
|
||||
|
||||
static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
|
||||
if (val < 0) {
|
||||
val = ~val;
|
||||
Bits.set((Idx << (BitNum-1)) + BitNum-1);
|
||||
}
|
||||
assert((val >> (BitNum-1)) == 0 && "value is too big");
|
||||
for (unsigned i = 0; i != BitNum-1; ++i)
|
||||
Bits[(Idx << (BitNum-1)) + i] = val & (T(1) << i);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Store a vector of values using a specific number of bits for each
|
||||
/// value. Both signed and unsigned types can be used, e.g
|
||||
/// @code
|
||||
/// PackedVector<signed, 2> vec;
|
||||
/// @endcode
|
||||
/// will create a vector accepting values -2, -1, 0, 1. Any other value will hit
|
||||
/// an assertion.
|
||||
template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
|
||||
class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy,
|
||||
std::numeric_limits<T>::is_signed> {
|
||||
BitVectorTy Bits;
|
||||
typedef PackedVectorBase<T, BitNum, BitVectorTy,
|
||||
std::numeric_limits<T>::is_signed> base;
|
||||
|
||||
public:
|
||||
class reference {
|
||||
PackedVector &Vec;
|
||||
const unsigned Idx;
|
||||
|
||||
reference(); // Undefined
|
||||
public:
|
||||
reference(PackedVector &vec, unsigned idx) : Vec(vec), Idx(idx) { }
|
||||
|
||||
reference &operator=(T val) {
|
||||
Vec.setValue(Vec.Bits, Idx, val);
|
||||
return *this;
|
||||
}
|
||||
operator T() const {
|
||||
return Vec.getValue(Vec.Bits, Idx);
|
||||
}
|
||||
};
|
||||
|
||||
PackedVector() { }
|
||||
explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) { }
|
||||
|
||||
bool empty() const { return Bits.empty(); }
|
||||
|
||||
unsigned size() const { return Bits.size() >> (BitNum-1); }
|
||||
|
||||
void clear() { Bits.clear(); }
|
||||
|
||||
void resize(unsigned N) { Bits.resize(N << (BitNum-1)); }
|
||||
|
||||
void reserve(unsigned N) { Bits.reserve(N << (BitNum-1)); }
|
||||
|
||||
PackedVector &reset() {
|
||||
Bits.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void push_back(T val) {
|
||||
resize(size()+1);
|
||||
(*this)[size()-1] = val;
|
||||
}
|
||||
|
||||
reference operator[](unsigned Idx) {
|
||||
return reference(*this, Idx);
|
||||
}
|
||||
|
||||
T operator[](unsigned Idx) const {
|
||||
return base::getValue(Bits, Idx);
|
||||
}
|
||||
|
||||
bool operator==(const PackedVector &RHS) const {
|
||||
return Bits == RHS.Bits;
|
||||
}
|
||||
|
||||
bool operator!=(const PackedVector &RHS) const {
|
||||
return Bits != RHS.Bits;
|
||||
}
|
||||
|
||||
const PackedVector &operator=(const PackedVector &RHS) {
|
||||
Bits = RHS.Bits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
PackedVector &operator|=(const PackedVector &RHS) {
|
||||
Bits |= RHS.Bits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(PackedVector &RHS) {
|
||||
Bits.swap(RHS.Bits);
|
||||
}
|
||||
};
|
||||
|
||||
// Leave BitNum=0 undefined.
|
||||
template <typename T>
|
||||
class PackedVector<T, 0>;
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
199
thirdparty/clang/include/llvm/ADT/PointerIntPair.h
vendored
Normal file
199
thirdparty/clang/include/llvm/ADT/PointerIntPair.h
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
//===- 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 IntVal 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 PtrVal, IntType IntVal) {
|
||||
assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
|
||||
"PointerIntPair formed with integer size too large for pointer");
|
||||
setPointerAndInt(PtrVal, IntVal);
|
||||
}
|
||||
explicit PointerIntPair(PointerTy PtrVal) {
|
||||
initWithPointer(PtrVal);
|
||||
}
|
||||
|
||||
PointerTy getPointer() const {
|
||||
return PtrTraits::getFromVoidPointer(
|
||||
reinterpret_cast<void*>(Value & PointerBitMask));
|
||||
}
|
||||
|
||||
IntType getInt() const {
|
||||
return (IntType)((Value >> IntShift) & IntMask);
|
||||
}
|
||||
|
||||
void setPointer(PointerTy PtrVal) {
|
||||
intptr_t PtrWord
|
||||
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
|
||||
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
|
||||
"Pointer is not sufficiently aligned");
|
||||
// Preserve all low bits, just update the pointer.
|
||||
Value = PtrWord | (Value & ~PointerBitMask);
|
||||
}
|
||||
|
||||
void setInt(IntType IntVal) {
|
||||
intptr_t IntWord = static_cast<intptr_t>(IntVal);
|
||||
assert(IntWord < (1 << IntBits) && "Integer too large for field");
|
||||
|
||||
// Preserve all bits other than the ones we are updating.
|
||||
Value &= ~ShiftedIntMask; // Remove integer field.
|
||||
Value |= IntWord << IntShift; // Set new integer.
|
||||
}
|
||||
|
||||
void initWithPointer(PointerTy PtrVal) {
|
||||
intptr_t PtrWord
|
||||
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
|
||||
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
|
||||
"Pointer is not sufficiently aligned");
|
||||
Value = PtrWord;
|
||||
}
|
||||
|
||||
void setPointerAndInt(PointerTy PtrVal, IntType IntVal) {
|
||||
intptr_t PtrWord
|
||||
= reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal));
|
||||
assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
|
||||
"Pointer is not sufficiently aligned");
|
||||
intptr_t IntWord = static_cast<intptr_t>(IntVal);
|
||||
assert(IntWord < (1 << IntBits) && "Integer too large for field");
|
||||
|
||||
Value = PtrWord | (IntWord << IntShift);
|
||||
}
|
||||
|
||||
PointerTy const *getAddrOfPointer() const {
|
||||
return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
|
||||
}
|
||||
|
||||
PointerTy *getAddrOfPointer() {
|
||||
assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
|
||||
"Can only return the address if IntBits is cleared and "
|
||||
"PtrTraits doesn't change the pointer");
|
||||
return reinterpret_cast<PointerTy *>(&Value);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Allow PointerIntPairs to be created from const void * if and only if the
|
||||
// pointer type could be created from a const void *.
|
||||
static PointerIntPair getFromOpaqueValue(const void *V) {
|
||||
(void)PtrTraits::getFromVoidPointer(V);
|
||||
return getFromOpaqueValue(const_cast<void *>(V));
|
||||
}
|
||||
|
||||
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;}
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template<typename PointerTy, unsigned IntBits, typename IntType>
|
||||
struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType> > {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
// 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() {
|
||||
uintptr_t Val = static_cast<uintptr_t>(-1);
|
||||
Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
|
||||
return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
|
||||
}
|
||||
static Ty getTombstoneKey() {
|
||||
uintptr_t Val = static_cast<uintptr_t>(-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; }
|
||||
};
|
||||
|
||||
// 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);
|
||||
}
|
||||
static inline PointerIntPair<PointerTy, IntBits, IntType>
|
||||
getFromVoidPointer(const void *P) {
|
||||
return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
|
||||
}
|
||||
enum {
|
||||
NumLowBitsAvailable = PtrTraits::NumLowBitsAvailable - IntBits
|
||||
};
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
#endif
|
||||
447
thirdparty/clang/include/llvm/ADT/PointerUnion.h
vendored
Normal file
447
thirdparty/clang/include/llvm/ADT/PointerUnion.h
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
//===- 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 {
|
||||
|
||||
template <typename T>
|
||||
struct PointerUnionTypeSelectorReturn {
|
||||
typedef T Return;
|
||||
};
|
||||
|
||||
/// \brief Get a type based on whether two types are the same or not. For:
|
||||
/// @code
|
||||
/// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
|
||||
/// @endcode
|
||||
/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
|
||||
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelector {
|
||||
typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
|
||||
};
|
||||
|
||||
template <typename T, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
|
||||
typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
||||
struct PointerUnionTypeSelectorReturn<
|
||||
PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
|
||||
typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
|
||||
Return;
|
||||
};
|
||||
|
||||
/// 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 = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
|
||||
PT2BitsAv = (int)(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;
|
||||
|
||||
struct IsPT1 {
|
||||
static const int Num = 0;
|
||||
};
|
||||
struct IsPT2 {
|
||||
static const int Num = 1;
|
||||
};
|
||||
template <typename T>
|
||||
struct UNION_DOESNT_CONTAIN_TYPE { };
|
||||
|
||||
public:
|
||||
PointerUnion() {}
|
||||
|
||||
PointerUnion(PT1 V) : Val(
|
||||
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
|
||||
}
|
||||
PointerUnion(PT2 V) : Val(
|
||||
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
|
||||
}
|
||||
|
||||
/// isNull - Return true if the pointer held in the union is null,
|
||||
/// regardless of which type it is.
|
||||
bool isNull() const {
|
||||
// Convert from the void* to one of the pointer types, to make sure that
|
||||
// we recursively strip off low bits if we have a nested PointerUnion.
|
||||
return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
|
||||
}
|
||||
operator bool() const { return !isNull(); }
|
||||
|
||||
/// is<T>() return true if the Union currently holds the type matching T.
|
||||
template<typename T>
|
||||
int is() const {
|
||||
typedef typename
|
||||
::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
|
||||
UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
|
||||
int TyNo = Ty::Num;
|
||||
return static_cast<int>(Val.getInt()) == TyNo;
|
||||
}
|
||||
|
||||
/// get<T>() - Return the value of the specified pointer type. If the
|
||||
/// specified pointer type is incorrect, assert.
|
||||
template<typename T>
|
||||
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();
|
||||
}
|
||||
|
||||
/// \brief If the union is set to the first pointer type get an address
|
||||
/// pointing to it.
|
||||
PT1 const *getAddrOfPtr1() const {
|
||||
return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
|
||||
}
|
||||
|
||||
/// \brief If the union is set to the first pointer type get an address
|
||||
/// pointing to it.
|
||||
PT1 *getAddrOfPtr1() {
|
||||
assert(is<PT1>() && "Val is not the first pointer");
|
||||
assert(get<PT1>() == Val.getPointer() &&
|
||||
"Can't get the address because PointerLikeTypeTraits changes the ptr");
|
||||
return (PT1 *)Val.getAddrOfPointer();
|
||||
}
|
||||
|
||||
/// 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.initWithPointer(
|
||||
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
|
||||
return *this;
|
||||
}
|
||||
const PointerUnion &operator=(const PT2 &RHS) {
|
||||
Val.setPointerAndInt(
|
||||
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
|
||||
1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
||||
static inline 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;
|
||||
|
||||
struct IsInnerUnion {
|
||||
ValTy Val;
|
||||
IsInnerUnion(ValTy val) : Val(val) { }
|
||||
template<typename T>
|
||||
int is() const {
|
||||
return Val.template is<InnerUnion>() &&
|
||||
Val.template get<InnerUnion>().template is<T>();
|
||||
}
|
||||
template<typename T>
|
||||
T get() const {
|
||||
return Val.template get<InnerUnion>().template get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
struct IsPT3 {
|
||||
ValTy Val;
|
||||
IsPT3(ValTy val) : Val(val) { }
|
||||
template<typename T>
|
||||
int is() const {
|
||||
return Val.template is<T>();
|
||||
}
|
||||
template<typename T>
|
||||
T get() const {
|
||||
return Val.template get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
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 held 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 {
|
||||
// If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
|
||||
typedef typename
|
||||
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
||||
>::Return Ty;
|
||||
return Ty(Val).template is<T>();
|
||||
}
|
||||
|
||||
/// get<T>() - Return the value of the specified pointer type. If the
|
||||
/// specified pointer type is incorrect, assert.
|
||||
template<typename T>
|
||||
T get() const {
|
||||
assert(is<T>() && "Invalid accessor called");
|
||||
// If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
|
||||
typedef typename
|
||||
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
||||
>::Return Ty;
|
||||
return Ty(Val).template get<T>();
|
||||
}
|
||||
|
||||
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
||||
/// return it, otherwise return null.
|
||||
template<typename T>
|
||||
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 inline 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
|
||||
};
|
||||
};
|
||||
|
||||
/// PointerUnion4 - This is a pointer union of four pointer types. See
|
||||
/// documentation for PointerUnion for usage.
|
||||
template <typename PT1, typename PT2, typename PT3, typename PT4>
|
||||
class PointerUnion4 {
|
||||
public:
|
||||
typedef PointerUnion<PT1, PT2> InnerUnion1;
|
||||
typedef PointerUnion<PT3, PT4> InnerUnion2;
|
||||
typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
|
||||
private:
|
||||
ValTy Val;
|
||||
public:
|
||||
PointerUnion4() {}
|
||||
|
||||
PointerUnion4(PT1 V) {
|
||||
Val = InnerUnion1(V);
|
||||
}
|
||||
PointerUnion4(PT2 V) {
|
||||
Val = InnerUnion1(V);
|
||||
}
|
||||
PointerUnion4(PT3 V) {
|
||||
Val = InnerUnion2(V);
|
||||
}
|
||||
PointerUnion4(PT4 V) {
|
||||
Val = InnerUnion2(V);
|
||||
}
|
||||
|
||||
/// isNull - Return true if the pointer held in the union is null,
|
||||
/// regardless of which type it is.
|
||||
bool isNull() const { return Val.isNull(); }
|
||||
operator bool() const { return !isNull(); }
|
||||
|
||||
/// is<T>() return true if the Union currently holds the type matching T.
|
||||
template<typename T>
|
||||
int is() const {
|
||||
// If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
|
||||
typedef typename
|
||||
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
|
||||
>::Return Ty;
|
||||
return Val.template is<Ty>() &&
|
||||
Val.template get<Ty>().template is<T>();
|
||||
}
|
||||
|
||||
/// get<T>() - Return the value of the specified pointer type. If the
|
||||
/// specified pointer type is incorrect, assert.
|
||||
template<typename T>
|
||||
T get() const {
|
||||
assert(is<T>() && "Invalid accessor called");
|
||||
// If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
|
||||
typedef typename
|
||||
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
|
||||
>::Return Ty;
|
||||
return Val.template get<Ty>().template get<T>();
|
||||
}
|
||||
|
||||
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
||||
/// return it, otherwise return null.
|
||||
template<typename T>
|
||||
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 PointerUnion4 &operator=(const PT1 &RHS) {
|
||||
Val = InnerUnion1(RHS);
|
||||
return *this;
|
||||
}
|
||||
const PointerUnion4 &operator=(const PT2 &RHS) {
|
||||
Val = InnerUnion1(RHS);
|
||||
return *this;
|
||||
}
|
||||
const PointerUnion4 &operator=(const PT3 &RHS) {
|
||||
Val = InnerUnion2(RHS);
|
||||
return *this;
|
||||
}
|
||||
const PointerUnion4 &operator=(const PT4 &RHS) {
|
||||
Val = InnerUnion2(RHS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
||||
static inline PointerUnion4 getFromOpaqueValue(void *VP) {
|
||||
PointerUnion4 V;
|
||||
V.Val = ValTy::getFromOpaqueValue(VP);
|
||||
return V;
|
||||
}
|
||||
};
|
||||
|
||||
// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
|
||||
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
|
||||
template<typename PT1, typename PT2, typename PT3, typename PT4>
|
||||
class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
|
||||
public:
|
||||
static inline void *
|
||||
getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
|
||||
return P.getOpaqueValue();
|
||||
}
|
||||
static inline PointerUnion4<PT1, PT2, PT3, PT4>
|
||||
getFromVoidPointer(void *P) {
|
||||
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
|
||||
}
|
||||
|
||||
// The number of bits available are the min of the two pointer types.
|
||||
enum {
|
||||
NumLowBitsAvailable =
|
||||
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
|
||||
::NumLowBitsAvailable
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
279
thirdparty/clang/include/llvm/ADT/PostOrderIterator.h
vendored
Normal file
279
thirdparty/clang/include/llvm/ADT/PostOrderIterator.h
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
//===- 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/SmallPtrSet.h"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// The po_iterator_storage template provides access to the set of already
|
||||
// visited nodes during the po_iterator's depth-first traversal.
|
||||
//
|
||||
// The default implementation simply contains a set of visited nodes, while
|
||||
// the Extended=true version uses a reference to an external set.
|
||||
//
|
||||
// It is possible to prune the depth-first traversal in several ways:
|
||||
//
|
||||
// - When providing an external set that already contains some graph nodes,
|
||||
// those nodes won't be visited again. This is useful for restarting a
|
||||
// post-order traversal on a graph with nodes that aren't dominated by a
|
||||
// single node.
|
||||
//
|
||||
// - By providing a custom SetType class, unwanted graph nodes can be excluded
|
||||
// by having the insert() function return false. This could for example
|
||||
// confine a CFG traversal to blocks in a specific loop.
|
||||
//
|
||||
// - Finally, by specializing the po_iterator_storage template itself, graph
|
||||
// edges can be pruned by returning false in the insertEdge() function. This
|
||||
// could be used to remove loop back-edges from the CFG seen by po_iterator.
|
||||
//
|
||||
// A specialized po_iterator_storage class can observe both the pre-order and
|
||||
// the post-order. The insertEdge() function is called in a pre-order, while
|
||||
// the finishPostorder() function is called just before the po_iterator moves
|
||||
// on to the next node.
|
||||
|
||||
/// Default po_iterator_storage implementation with an internal set object.
|
||||
template<class SetType, bool External>
|
||||
class po_iterator_storage {
|
||||
SetType Visited;
|
||||
public:
|
||||
// Return true if edge destination should be visited.
|
||||
template<typename NodeType>
|
||||
bool insertEdge(NodeType *From, NodeType *To) {
|
||||
return Visited.insert(To);
|
||||
}
|
||||
|
||||
// Called after all children of BB have been visited.
|
||||
template<typename NodeType>
|
||||
void finishPostorder(NodeType *BB) {}
|
||||
};
|
||||
|
||||
/// Specialization of po_iterator_storage that references an external set.
|
||||
template<class SetType>
|
||||
class po_iterator_storage<SetType, true> {
|
||||
SetType &Visited;
|
||||
public:
|
||||
po_iterator_storage(SetType &VSet) : Visited(VSet) {}
|
||||
po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {}
|
||||
|
||||
// Return true if edge destination should be visited, called with From = 0 for
|
||||
// the root node.
|
||||
// Graph edges can be pruned by specializing this function.
|
||||
template<class NodeType>
|
||||
bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); }
|
||||
|
||||
// Called after all children of BB have been visited.
|
||||
template<class NodeType>
|
||||
void finishPostorder(NodeType *BB) {}
|
||||
};
|
||||
|
||||
template<class GraphT,
|
||||
class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
|
||||
bool ExtStorage = false,
|
||||
class GT = GraphTraits<GraphT> >
|
||||
class po_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
typename GT::NodeType, ptrdiff_t>,
|
||||
public po_iterator_storage<SetType, ExtStorage> {
|
||||
typedef std::iterator<std::forward_iterator_tag,
|
||||
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::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
|
||||
|
||||
void traverseChild() {
|
||||
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
|
||||
NodeType *BB = *VisitStack.back().second++;
|
||||
if (this->insertEdge(VisitStack.back().first, BB)) {
|
||||
// If the block is not visited...
|
||||
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline po_iterator(NodeType *BB) {
|
||||
this->insertEdge((NodeType*)0, BB);
|
||||
VisitStack.push_back(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 (this->insertEdge((NodeType*)0, BB)) {
|
||||
VisitStack.push_back(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.back().first;
|
||||
}
|
||||
|
||||
// This is a nonstandard operator-> that dereferences the pointer an extra
|
||||
// time... so that you can actually call methods ON the BasicBlock, because
|
||||
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
|
||||
//
|
||||
inline NodeType *operator->() const { return operator*(); }
|
||||
|
||||
inline _Self& operator++() { // Preincrement
|
||||
this->finishPostorder(VisitStack.back().first);
|
||||
VisitStack.pop_back();
|
||||
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) {
|
||||
std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks));
|
||||
}
|
||||
public:
|
||||
typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator;
|
||||
|
||||
inline ReversePostOrderTraversal(GraphT G) {
|
||||
Initialize(GT::getEntryNode(G));
|
||||
}
|
||||
|
||||
// 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
|
||||
84
thirdparty/clang/include/llvm/ADT/PriorityQueue.h
vendored
Normal file
84
thirdparty/clang/include/llvm/ADT/PriorityQueue.h
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
//===- 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_PRIORITYQUEUE_H
|
||||
#define LLVM_ADT_PRIORITYQUEUE_H
|
||||
|
||||
#include <algorithm>
|
||||
#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
|
||||
220
thirdparty/clang/include/llvm/ADT/SCCIterator.h
vendored
Normal file
220
thirdparty/clang/include/llvm/ADT/SCCIterator.h
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
//===---- ADT/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/DenseMap.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#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 std::iterator<std::forward_iterator_tag,
|
||||
std::vector<typename GT::NodeType>, ptrdiff_t> {
|
||||
typedef typename GT::NodeType NodeType;
|
||||
typedef typename GT::ChildIteratorType ChildItTy;
|
||||
typedef std::vector<NodeType*> SccTy;
|
||||
typedef std::iterator<std::forward_iterator_tag,
|
||||
std::vector<typename GT::NodeType>, 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;
|
||||
DenseMap<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;
|
||||
|
||||
// MinVisitNumStack - Stack holding the "min" values for each node in the DFS.
|
||||
// This is used to track the minimum uplink values for all children of
|
||||
// the corresponding node on the VisitStack.
|
||||
std::vector<unsigned> MinVisitNumStack;
|
||||
|
||||
// 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)));
|
||||
//dbgs() << "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);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//dbgs() << "TarjanSCC: Popped node " << visitingN <<
|
||||
// " : minVisitNum = " << minVisitNum << "; Node visit num = " <<
|
||||
// nodeVisitNumbers[visitingN] << "\n";
|
||||
|
||||
if (minVisitNum != nodeVisitNumbers[visitingN])
|
||||
continue;
|
||||
|
||||
// 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(const GraphT &G){return _Self(GT::getEntryNode(G));}
|
||||
static inline _Self end (const GraphT &) { return _Self(); }
|
||||
|
||||
// Direct loop termination test: I.isAtEnd() is more efficient than I == end()
|
||||
inline bool isAtEnd() 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;
|
||||
}
|
||||
|
||||
/// ReplaceNode - This informs the scc_iterator that the specified Old node
|
||||
/// has been deleted, and New is to be used in its place.
|
||||
void ReplaceNode(NodeType *Old, NodeType *New) {
|
||||
assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?");
|
||||
nodeVisitNumbers[New] = nodeVisitNumbers[Old];
|
||||
nodeVisitNumbers.erase(Old);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Global constructor for the SCC iterator.
|
||||
template <class T>
|
||||
scc_iterator<T> scc_begin(const T &G) {
|
||||
return scc_iterator<T>::begin(G);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scc_iterator<T> scc_end(const T &G) {
|
||||
return scc_iterator<T>::end(G);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) {
|
||||
return scc_iterator<Inverse<T> >::begin(G);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) {
|
||||
return scc_iterator<Inverse<T> >::end(G);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
312
thirdparty/clang/include/llvm/ADT/STLExtras.h
vendored
Normal file
312
thirdparty/clang/include/llvm/ADT/STLExtras.h
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
//===- 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 <cstdlib> // for qsort
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <utility> // for std::pair
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <functional>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
template<class Ty>
|
||||
struct identity : public std::unary_function<Ty, Ty> {
|
||||
Ty &operator()(Ty &self) const {
|
||||
return self;
|
||||
}
|
||||
const Ty &operator()(const Ty &self) const {
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Ty>
|
||||
struct less_ptr : public std::binary_function<Ty, Ty, bool> {
|
||||
bool operator()(const Ty* left, const Ty* right) const {
|
||||
return *left < *right;
|
||||
}
|
||||
};
|
||||
|
||||
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>
|
||||
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
|
||||
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 (&)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
/// array_pod_sort_comparator - This is helper function for array_pod_sort,
|
||||
/// which just uses operator< on T.
|
||||
template<typename T>
|
||||
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_pod_sort_comparator - This is an internal helper function used to
|
||||
/// get type deduction of T right.
|
||||
template<typename T>
|
||||
inline int (*get_array_pod_sort_comparator(const T &))
|
||||
(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>
|
||||
inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
|
||||
// Don't dereference start iterator of empty sequence.
|
||||
if (Start == End) return;
|
||||
qsort(&*Start, End-Start, sizeof(*Start),
|
||||
get_array_pod_sort_comparator(*Start));
|
||||
}
|
||||
|
||||
template<class IteratorTy>
|
||||
inline void array_pod_sort(IteratorTy Start, IteratorTy End,
|
||||
int (*Compare)(const void*, const void*)) {
|
||||
// Don't dereference start iterator of empty sequence.
|
||||
if (Start == End) return;
|
||||
qsort(&*Start, End-Start, sizeof(*Start), Compare);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <algorithm>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// For a container of pointers, deletes the pointers and then clears the
|
||||
/// container.
|
||||
template<typename Container>
|
||||
void DeleteContainerPointers(Container &C) {
|
||||
for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
delete *I;
|
||||
C.clear();
|
||||
}
|
||||
|
||||
/// In a container of pairs (usually a map) whose second element is a pointer,
|
||||
/// deletes the second elements and then clears the container.
|
||||
template<typename Container>
|
||||
void DeleteContainerSeconds(Container &C) {
|
||||
for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
C.clear();
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
256
thirdparty/clang/include/llvm/ADT/ScopedHashTable.h
vendored
Normal file
256
thirdparty/clang/include/llvm/ADT/ScopedHashTable.h
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
//===- 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 "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
|
||||
typename AllocatorTy = MallocAllocator>
|
||||
class ScopedHashTable;
|
||||
|
||||
template <typename K, typename V>
|
||||
class ScopedHashTableVal {
|
||||
ScopedHashTableVal *NextInScope;
|
||||
ScopedHashTableVal *NextForKey;
|
||||
K Key;
|
||||
V Val;
|
||||
ScopedHashTableVal(const K &key, const V &val) : Key(key), Val(val) {}
|
||||
public:
|
||||
|
||||
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; }
|
||||
ScopedHashTableVal *getNextInScope() { return NextInScope; }
|
||||
|
||||
template <typename AllocatorTy>
|
||||
static ScopedHashTableVal *Create(ScopedHashTableVal *nextInScope,
|
||||
ScopedHashTableVal *nextForKey,
|
||||
const K &key, const V &val,
|
||||
AllocatorTy &Allocator) {
|
||||
ScopedHashTableVal *New = Allocator.template Allocate<ScopedHashTableVal>();
|
||||
// Set up the value.
|
||||
new (New) ScopedHashTableVal(key, val);
|
||||
New->NextInScope = nextInScope;
|
||||
New->NextForKey = nextForKey;
|
||||
return New;
|
||||
}
|
||||
|
||||
template <typename AllocatorTy>
|
||||
void Destroy(AllocatorTy &Allocator) {
|
||||
// Free memory referenced by the item.
|
||||
this->~ScopedHashTableVal();
|
||||
Allocator.Deallocate(this);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename K, typename V, typename KInfo = DenseMapInfo<K>,
|
||||
typename AllocatorTy = MallocAllocator>
|
||||
class ScopedHashTableScope {
|
||||
/// HT - The hashtable that we are active for.
|
||||
ScopedHashTable<K, V, KInfo, AllocatorTy> &HT;
|
||||
|
||||
/// PrevScope - This is the scope that we are shadowing in HT.
|
||||
ScopedHashTableScope *PrevScope;
|
||||
|
||||
/// LastValInScope - This is the last value that was inserted for this scope
|
||||
/// or null if none have been inserted yet.
|
||||
ScopedHashTableVal<K, V> *LastValInScope;
|
||||
void operator=(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
|
||||
ScopedHashTableScope(ScopedHashTableScope&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, AllocatorTy> &HT);
|
||||
~ScopedHashTableScope();
|
||||
|
||||
ScopedHashTableScope *getParentScope() { return PrevScope; }
|
||||
const ScopedHashTableScope *getParentScope() const { return PrevScope; }
|
||||
|
||||
private:
|
||||
friend class ScopedHashTable<K, V, KInfo, AllocatorTy>;
|
||||
ScopedHashTableVal<K, V> *getLastValInScope() {
|
||||
return LastValInScope;
|
||||
}
|
||||
void setLastValInScope(ScopedHashTableVal<K, V> *Val) {
|
||||
LastValInScope = Val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename K, typename V, typename KInfo = DenseMapInfo<K> >
|
||||
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, typename KInfo, typename AllocatorTy>
|
||||
class ScopedHashTable {
|
||||
public:
|
||||
/// ScopeTy - This is a helpful typedef that allows clients to get easy access
|
||||
/// to the name of the scope for this hash table.
|
||||
typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy;
|
||||
private:
|
||||
typedef ScopedHashTableVal<K, V> ValTy;
|
||||
DenseMap<K, ValTy*, KInfo> TopLevelMap;
|
||||
ScopeTy *CurScope;
|
||||
|
||||
AllocatorTy Allocator;
|
||||
|
||||
ScopedHashTable(const ScopedHashTable&); // NOT YET IMPLEMENTED
|
||||
void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED
|
||||
friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
|
||||
public:
|
||||
ScopedHashTable() : CurScope(0) {}
|
||||
ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {}
|
||||
~ScopedHashTable() {
|
||||
assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!");
|
||||
}
|
||||
|
||||
|
||||
/// Access to the allocator.
|
||||
typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
|
||||
typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
|
||||
AllocatorRefTy getAllocator() { return Allocator; }
|
||||
AllocatorCRefTy getAllocator() const { return Allocator; }
|
||||
|
||||
bool count(const K &Key) const {
|
||||
return TopLevelMap.count(Key);
|
||||
}
|
||||
|
||||
V lookup(const K &Key) {
|
||||
typename DenseMap<K, ValTy*, KInfo>::iterator I = TopLevelMap.find(Key);
|
||||
if (I != TopLevelMap.end())
|
||||
return I->second->getValue();
|
||||
|
||||
return V();
|
||||
}
|
||||
|
||||
void insert(const K &Key, const V &Val) {
|
||||
insertIntoScope(CurScope, Key, Val);
|
||||
}
|
||||
|
||||
typedef ScopedHashTableIterator<K, V, KInfo> iterator;
|
||||
|
||||
iterator end() { return iterator(0); }
|
||||
|
||||
iterator begin(const K &Key) {
|
||||
typename DenseMap<K, ValTy*, KInfo>::iterator I =
|
||||
TopLevelMap.find(Key);
|
||||
if (I == TopLevelMap.end()) return end();
|
||||
return iterator(I->second);
|
||||
}
|
||||
|
||||
ScopeTy *getCurScope() { return CurScope; }
|
||||
const ScopeTy *getCurScope() const { return CurScope; }
|
||||
|
||||
/// insertIntoScope - This inserts the specified key/value at the specified
|
||||
/// (possibly not the current) scope. While it is ok to insert into a scope
|
||||
/// that isn't the current one, it isn't ok to insert *underneath* an existing
|
||||
/// value of the specified key.
|
||||
void insertIntoScope(ScopeTy *S, const K &Key, const V &Val) {
|
||||
assert(S && "No scope active!");
|
||||
ScopedHashTableVal<K, V> *&KeyEntry = TopLevelMap[Key];
|
||||
KeyEntry = ValTy::Create(S->getLastValInScope(), KeyEntry, Key, Val,
|
||||
Allocator);
|
||||
S->setLastValInScope(KeyEntry);
|
||||
}
|
||||
};
|
||||
|
||||
/// ScopedHashTableScope ctor - Install this as the current scope for the hash
|
||||
/// table.
|
||||
template <typename K, typename V, typename KInfo, typename Allocator>
|
||||
ScopedHashTableScope<K, V, KInfo, Allocator>::
|
||||
ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) {
|
||||
PrevScope = HT.CurScope;
|
||||
HT.CurScope = this;
|
||||
LastValInScope = 0;
|
||||
}
|
||||
|
||||
template <typename K, typename V, typename KInfo, typename Allocator>
|
||||
ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() {
|
||||
assert(HT.CurScope == this && "Scope imbalance!");
|
||||
HT.CurScope = PrevScope;
|
||||
|
||||
// Pop and delete all values corresponding to this scope.
|
||||
while (ScopedHashTableVal<K, V> *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.
|
||||
ThisEntry->Destroy(HT.getAllocator());
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
71
thirdparty/clang/include/llvm/ADT/SetOperations.h
vendored
Normal file
71
thirdparty/clang/include/llvm/ADT/SetOperations.h
vendored
Normal file
@@ -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
|
||||
232
thirdparty/clang/include/llvm/ADT/SetVector.h
vendored
Normal file
232
thirdparty/clang/include/llvm/ADT/SetVector.h
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
//===- 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 {
|
||||
|
||||
/// \brief A vector that has set insertion semantics.
|
||||
///
|
||||
/// 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.
|
||||
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];
|
||||
}
|
||||
|
||||
/// \brief Insert a new element into the SetVector.
|
||||
/// \returns true iff the element was inserted 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.
|
||||
bool remove(const value_type& X) {
|
||||
if (set_.erase(X)) {
|
||||
typename vector_type::iterator I =
|
||||
std::find(vector_.begin(), vector_.end(), X);
|
||||
assert(I != vector_.end() && "Corrupted SetVector instances!");
|
||||
vector_.erase(I);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Remove items from the set vector based on a predicate function.
|
||||
///
|
||||
/// This is intended to be equivalent to the following code, if we could
|
||||
/// write it:
|
||||
///
|
||||
/// \code
|
||||
/// V.erase(std::remove_if(V.begin(), V.end(), P), V.end());
|
||||
/// \endcode
|
||||
///
|
||||
/// However, SetVector doesn't expose non-const iterators, making any
|
||||
/// algorithm like remove_if impossible to use.
|
||||
///
|
||||
/// \returns true if any element is removed.
|
||||
template <typename UnaryPredicate>
|
||||
bool remove_if(UnaryPredicate P) {
|
||||
typename vector_type::iterator I
|
||||
= std::remove_if(vector_.begin(), vector_.end(),
|
||||
TestAndEraseFromSet<UnaryPredicate>(P, set_));
|
||||
if (I == vector_.end())
|
||||
return false;
|
||||
vector_.erase(I, vector_.end());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Count the number of elements of a given key in the SetVector.
|
||||
/// \returns 0 if the element is not in the SetVector, 1 if it is.
|
||||
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();
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
T Ret = back();
|
||||
pop_back();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool operator==(const SetVector &that) const {
|
||||
return vector_ == that.vector_;
|
||||
}
|
||||
|
||||
bool operator!=(const SetVector &that) const {
|
||||
return vector_ != that.vector_;
|
||||
}
|
||||
|
||||
private:
|
||||
/// \brief A wrapper predicate designed for use with std::remove_if.
|
||||
///
|
||||
/// This predicate wraps a predicate suitable for use with std::remove_if to
|
||||
/// call set_.erase(x) on each element which is slated for removal.
|
||||
template <typename UnaryPredicate>
|
||||
class TestAndEraseFromSet {
|
||||
UnaryPredicate P;
|
||||
set_type &set_;
|
||||
|
||||
public:
|
||||
typedef typename UnaryPredicate::argument_type argument_type;
|
||||
|
||||
TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {}
|
||||
|
||||
bool operator()(argument_type Arg) {
|
||||
if (P(Arg)) {
|
||||
set_.erase(Arg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
set_type set_; ///< The set.
|
||||
vector_type vector_; ///< The vector.
|
||||
};
|
||||
|
||||
/// \brief 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
|
||||
574
thirdparty/clang/include/llvm/ADT/SmallBitVector.h
vendored
Normal file
574
thirdparty/clang/include/llvm/ADT/SmallBitVector.h
vendored
Normal file
@@ -0,0 +1,574 @@
|
||||
//===- llvm/ADT/SmallBitVector.h - 'Normally small' 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 SmallBitVector class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_SMALLBITVECTOR_H
|
||||
#define LLVM_ADT_SMALLBITVECTOR_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SmallBitVector - This is a 'bitvector' (really, a variable-sized bit array),
|
||||
/// optimized for the case when the array is small. It contains one
|
||||
/// pointer-sized field, which is directly used as a plain collection of bits
|
||||
/// when possible, or as a pointer to a larger heap-allocated array when
|
||||
/// necessary. This allows normal "small" cases to be fast without losing
|
||||
/// generality for large inputs.
|
||||
///
|
||||
class SmallBitVector {
|
||||
// TODO: In "large" mode, a pointer to a BitVector is used, leading to an
|
||||
// unnecessary level of indirection. It would be more efficient to use a
|
||||
// pointer to memory containing size, allocation size, and the array of bits.
|
||||
uintptr_t X;
|
||||
|
||||
enum {
|
||||
// The number of bits in this class.
|
||||
NumBaseBits = sizeof(uintptr_t) * CHAR_BIT,
|
||||
|
||||
// One bit is used to discriminate between small and large mode. The
|
||||
// remaining bits are used for the small-mode representation.
|
||||
SmallNumRawBits = NumBaseBits - 1,
|
||||
|
||||
// A few more bits are used to store the size of the bit set in small mode.
|
||||
// Theoretically this is a ceil-log2. These bits are encoded in the most
|
||||
// significant bits of the raw bits.
|
||||
SmallNumSizeBits = (NumBaseBits == 32 ? 5 :
|
||||
NumBaseBits == 64 ? 6 :
|
||||
SmallNumRawBits),
|
||||
|
||||
// The remaining bits are used to store the actual set in small mode.
|
||||
SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits
|
||||
};
|
||||
|
||||
public:
|
||||
// Encapsulation of a single bit.
|
||||
class reference {
|
||||
SmallBitVector &TheVector;
|
||||
unsigned BitPos;
|
||||
|
||||
public:
|
||||
reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {}
|
||||
|
||||
reference& operator=(reference t) {
|
||||
*this = bool(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference& operator=(bool t) {
|
||||
if (t)
|
||||
TheVector.set(BitPos);
|
||||
else
|
||||
TheVector.reset(BitPos);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return const_cast<const SmallBitVector &>(TheVector).operator[](BitPos);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
bool isSmall() const {
|
||||
return X & uintptr_t(1);
|
||||
}
|
||||
|
||||
BitVector *getPointer() const {
|
||||
assert(!isSmall());
|
||||
return reinterpret_cast<BitVector *>(X);
|
||||
}
|
||||
|
||||
void switchToSmall(uintptr_t NewSmallBits, size_t NewSize) {
|
||||
X = 1;
|
||||
setSmallSize(NewSize);
|
||||
setSmallBits(NewSmallBits);
|
||||
}
|
||||
|
||||
void switchToLarge(BitVector *BV) {
|
||||
X = reinterpret_cast<uintptr_t>(BV);
|
||||
assert(!isSmall() && "Tried to use an unaligned pointer");
|
||||
}
|
||||
|
||||
// Return all the bits used for the "small" representation; this includes
|
||||
// bits for the size as well as the element bits.
|
||||
uintptr_t getSmallRawBits() const {
|
||||
assert(isSmall());
|
||||
return X >> 1;
|
||||
}
|
||||
|
||||
void setSmallRawBits(uintptr_t NewRawBits) {
|
||||
assert(isSmall());
|
||||
X = (NewRawBits << 1) | uintptr_t(1);
|
||||
}
|
||||
|
||||
// Return the size.
|
||||
size_t getSmallSize() const {
|
||||
return getSmallRawBits() >> SmallNumDataBits;
|
||||
}
|
||||
|
||||
void setSmallSize(size_t Size) {
|
||||
setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits));
|
||||
}
|
||||
|
||||
// Return the element bits.
|
||||
uintptr_t getSmallBits() const {
|
||||
return getSmallRawBits() & ~(~uintptr_t(0) << getSmallSize());
|
||||
}
|
||||
|
||||
void setSmallBits(uintptr_t NewBits) {
|
||||
setSmallRawBits((NewBits & ~(~uintptr_t(0) << getSmallSize())) |
|
||||
(getSmallSize() << SmallNumDataBits));
|
||||
}
|
||||
|
||||
public:
|
||||
/// SmallBitVector default ctor - Creates an empty bitvector.
|
||||
SmallBitVector() : X(1) {}
|
||||
|
||||
/// SmallBitVector ctor - Creates a bitvector of specified number of bits. All
|
||||
/// bits are initialized to the specified value.
|
||||
explicit SmallBitVector(unsigned s, bool t = false) {
|
||||
if (s <= SmallNumDataBits)
|
||||
switchToSmall(t ? ~uintptr_t(0) : 0, s);
|
||||
else
|
||||
switchToLarge(new BitVector(s, t));
|
||||
}
|
||||
|
||||
/// SmallBitVector copy ctor.
|
||||
SmallBitVector(const SmallBitVector &RHS) {
|
||||
if (RHS.isSmall())
|
||||
X = RHS.X;
|
||||
else
|
||||
switchToLarge(new BitVector(*RHS.getPointer()));
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) {
|
||||
RHS.X = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
~SmallBitVector() {
|
||||
if (!isSmall())
|
||||
delete getPointer();
|
||||
}
|
||||
|
||||
/// empty - Tests whether there are no bits in this bitvector.
|
||||
bool empty() const {
|
||||
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
|
||||
}
|
||||
|
||||
/// size - Returns the number of bits in this bitvector.
|
||||
size_t size() const {
|
||||
return isSmall() ? getSmallSize() : getPointer()->size();
|
||||
}
|
||||
|
||||
/// count - Returns the number of bits which are set.
|
||||
unsigned count() const {
|
||||
if (isSmall()) {
|
||||
uintptr_t Bits = getSmallBits();
|
||||
if (NumBaseBits == 32)
|
||||
return CountPopulation_32(Bits);
|
||||
if (NumBaseBits == 64)
|
||||
return CountPopulation_64(Bits);
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->count();
|
||||
}
|
||||
|
||||
/// any - Returns true if any bit is set.
|
||||
bool any() const {
|
||||
if (isSmall())
|
||||
return getSmallBits() != 0;
|
||||
return getPointer()->any();
|
||||
}
|
||||
|
||||
/// all - Returns true if all bits are set.
|
||||
bool all() const {
|
||||
if (isSmall())
|
||||
return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1;
|
||||
return getPointer()->all();
|
||||
}
|
||||
|
||||
/// none - Returns true if none of the bits are set.
|
||||
bool none() const {
|
||||
if (isSmall())
|
||||
return getSmallBits() == 0;
|
||||
return getPointer()->none();
|
||||
}
|
||||
|
||||
/// find_first - Returns the index of the first set bit, -1 if none
|
||||
/// of the bits are set.
|
||||
int find_first() const {
|
||||
if (isSmall()) {
|
||||
uintptr_t Bits = getSmallBits();
|
||||
if (Bits == 0)
|
||||
return -1;
|
||||
if (NumBaseBits == 32)
|
||||
return CountTrailingZeros_32(Bits);
|
||||
if (NumBaseBits == 64)
|
||||
return CountTrailingZeros_64(Bits);
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->find_first();
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
if (isSmall()) {
|
||||
uintptr_t Bits = getSmallBits();
|
||||
// Mask off previous bits.
|
||||
Bits &= ~uintptr_t(0) << (Prev + 1);
|
||||
if (Bits == 0 || Prev + 1 >= getSmallSize())
|
||||
return -1;
|
||||
if (NumBaseBits == 32)
|
||||
return CountTrailingZeros_32(Bits);
|
||||
if (NumBaseBits == 64)
|
||||
return CountTrailingZeros_64(Bits);
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->find_next(Prev);
|
||||
}
|
||||
|
||||
/// clear - Clear all bits.
|
||||
void clear() {
|
||||
if (!isSmall())
|
||||
delete getPointer();
|
||||
switchToSmall(0, 0);
|
||||
}
|
||||
|
||||
/// resize - Grow or shrink the bitvector.
|
||||
void resize(unsigned N, bool t = false) {
|
||||
if (!isSmall()) {
|
||||
getPointer()->resize(N, t);
|
||||
} else if (SmallNumDataBits >= N) {
|
||||
uintptr_t NewBits = t ? ~uintptr_t(0) << getSmallSize() : 0;
|
||||
setSmallSize(N);
|
||||
setSmallBits(NewBits | getSmallBits());
|
||||
} else {
|
||||
BitVector *BV = new BitVector(N, t);
|
||||
uintptr_t OldBits = getSmallBits();
|
||||
for (size_t i = 0, e = getSmallSize(); i != e; ++i)
|
||||
(*BV)[i] = (OldBits >> i) & 1;
|
||||
switchToLarge(BV);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(unsigned N) {
|
||||
if (isSmall()) {
|
||||
if (N > SmallNumDataBits) {
|
||||
uintptr_t OldBits = getSmallRawBits();
|
||||
size_t SmallSize = getSmallSize();
|
||||
BitVector *BV = new BitVector(SmallSize);
|
||||
for (size_t i = 0; i < SmallSize; ++i)
|
||||
if ((OldBits >> i) & 1)
|
||||
BV->set(i);
|
||||
BV->reserve(N);
|
||||
switchToLarge(BV);
|
||||
}
|
||||
} else {
|
||||
getPointer()->reserve(N);
|
||||
}
|
||||
}
|
||||
|
||||
// Set, reset, flip
|
||||
SmallBitVector &set() {
|
||||
if (isSmall())
|
||||
setSmallBits(~uintptr_t(0));
|
||||
else
|
||||
getPointer()->set();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &set(unsigned Idx) {
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() | (uintptr_t(1) << Idx));
|
||||
else
|
||||
getPointer()->set(Idx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// set - Efficiently set a range of bits in [I, E)
|
||||
SmallBitVector &set(unsigned I, unsigned E) {
|
||||
assert(I <= E && "Attempted to set backwards range!");
|
||||
assert(E <= size() && "Attempted to set out-of-bounds range!");
|
||||
if (I == E) return *this;
|
||||
if (isSmall()) {
|
||||
uintptr_t EMask = ((uintptr_t)1) << E;
|
||||
uintptr_t IMask = ((uintptr_t)1) << I;
|
||||
uintptr_t Mask = EMask - IMask;
|
||||
setSmallBits(getSmallBits() | Mask);
|
||||
} else
|
||||
getPointer()->set(I, E);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &reset() {
|
||||
if (isSmall())
|
||||
setSmallBits(0);
|
||||
else
|
||||
getPointer()->reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &reset(unsigned Idx) {
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx));
|
||||
else
|
||||
getPointer()->reset(Idx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// reset - Efficiently reset a range of bits in [I, E)
|
||||
SmallBitVector &reset(unsigned I, unsigned E) {
|
||||
assert(I <= E && "Attempted to reset backwards range!");
|
||||
assert(E <= size() && "Attempted to reset out-of-bounds range!");
|
||||
if (I == E) return *this;
|
||||
if (isSmall()) {
|
||||
uintptr_t EMask = ((uintptr_t)1) << E;
|
||||
uintptr_t IMask = ((uintptr_t)1) << I;
|
||||
uintptr_t Mask = EMask - IMask;
|
||||
setSmallBits(getSmallBits() & ~Mask);
|
||||
} else
|
||||
getPointer()->reset(I, E);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &flip() {
|
||||
if (isSmall())
|
||||
setSmallBits(~getSmallBits());
|
||||
else
|
||||
getPointer()->flip();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &flip(unsigned Idx) {
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx));
|
||||
else
|
||||
getPointer()->flip(Idx);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// No argument flip.
|
||||
SmallBitVector operator~() const {
|
||||
return SmallBitVector(*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.");
|
||||
if (isSmall())
|
||||
return ((getSmallBits() >> Idx) & 1) != 0;
|
||||
return getPointer()->operator[](Idx);
|
||||
}
|
||||
|
||||
bool test(unsigned Idx) const {
|
||||
return (*this)[Idx];
|
||||
}
|
||||
|
||||
/// Test if any common bits are set.
|
||||
bool anyCommon(const SmallBitVector &RHS) const {
|
||||
if (isSmall() && RHS.isSmall())
|
||||
return (getSmallBits() & RHS.getSmallBits()) != 0;
|
||||
if (!isSmall() && !RHS.isSmall())
|
||||
return getPointer()->anyCommon(*RHS.getPointer());
|
||||
|
||||
for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i)
|
||||
if (test(i) && RHS.test(i))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
bool operator==(const SmallBitVector &RHS) const {
|
||||
if (size() != RHS.size())
|
||||
return false;
|
||||
if (isSmall())
|
||||
return getSmallBits() == RHS.getSmallBits();
|
||||
else
|
||||
return *getPointer() == *RHS.getPointer();
|
||||
}
|
||||
|
||||
bool operator!=(const SmallBitVector &RHS) const {
|
||||
return !(*this == RHS);
|
||||
}
|
||||
|
||||
// Intersection, union, disjoint union.
|
||||
SmallBitVector &operator&=(const SmallBitVector &RHS) {
|
||||
resize(std::max(size(), RHS.size()));
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() & RHS.getSmallBits());
|
||||
else if (!RHS.isSmall())
|
||||
getPointer()->operator&=(*RHS.getPointer());
|
||||
else {
|
||||
SmallBitVector Copy = RHS;
|
||||
Copy.resize(size());
|
||||
getPointer()->operator&=(*Copy.getPointer());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &operator|=(const SmallBitVector &RHS) {
|
||||
resize(std::max(size(), RHS.size()));
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() | RHS.getSmallBits());
|
||||
else if (!RHS.isSmall())
|
||||
getPointer()->operator|=(*RHS.getPointer());
|
||||
else {
|
||||
SmallBitVector Copy = RHS;
|
||||
Copy.resize(size());
|
||||
getPointer()->operator|=(*Copy.getPointer());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallBitVector &operator^=(const SmallBitVector &RHS) {
|
||||
resize(std::max(size(), RHS.size()));
|
||||
if (isSmall())
|
||||
setSmallBits(getSmallBits() ^ RHS.getSmallBits());
|
||||
else if (!RHS.isSmall())
|
||||
getPointer()->operator^=(*RHS.getPointer());
|
||||
else {
|
||||
SmallBitVector Copy = RHS;
|
||||
Copy.resize(size());
|
||||
getPointer()->operator^=(*Copy.getPointer());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Assignment operator.
|
||||
const SmallBitVector &operator=(const SmallBitVector &RHS) {
|
||||
if (isSmall()) {
|
||||
if (RHS.isSmall())
|
||||
X = RHS.X;
|
||||
else
|
||||
switchToLarge(new BitVector(*RHS.getPointer()));
|
||||
} else {
|
||||
if (!RHS.isSmall())
|
||||
*getPointer() = *RHS.getPointer();
|
||||
else {
|
||||
delete getPointer();
|
||||
X = RHS.X;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
const SmallBitVector &operator=(SmallBitVector &&RHS) {
|
||||
if (this != &RHS) {
|
||||
clear();
|
||||
swap(RHS);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void swap(SmallBitVector &RHS) {
|
||||
std::swap(X, RHS.X);
|
||||
}
|
||||
|
||||
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
|
||||
/// This computes "*this |= Mask".
|
||||
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
if (isSmall())
|
||||
applyMask<true, false>(Mask, MaskWords);
|
||||
else
|
||||
getPointer()->setBitsInMask(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsInMask - Clear any bits in this vector that are set in Mask.
|
||||
/// Don't resize. This computes "*this &= ~Mask".
|
||||
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
if (isSmall())
|
||||
applyMask<false, false>(Mask, MaskWords);
|
||||
else
|
||||
getPointer()->clearBitsInMask(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this |= ~Mask".
|
||||
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
if (isSmall())
|
||||
applyMask<true, true>(Mask, MaskWords);
|
||||
else
|
||||
getPointer()->setBitsNotInMask(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this &= Mask".
|
||||
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
if (isSmall())
|
||||
applyMask<false, true>(Mask, MaskWords);
|
||||
else
|
||||
getPointer()->clearBitsNotInMask(Mask, MaskWords);
|
||||
}
|
||||
|
||||
private:
|
||||
template<bool AddBits, bool InvertMask>
|
||||
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
|
||||
assert((NumBaseBits == 64 || NumBaseBits == 32) && "Unsupported word size");
|
||||
if (NumBaseBits == 64 && MaskWords >= 2) {
|
||||
uint64_t M = Mask[0] | (uint64_t(Mask[1]) << 32);
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) setSmallBits(getSmallBits() | M);
|
||||
else setSmallBits(getSmallBits() & ~M);
|
||||
} else {
|
||||
uint32_t M = Mask[0];
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) setSmallBits(getSmallBits() | M);
|
||||
else setSmallBits(getSmallBits() & ~M);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline SmallBitVector
|
||||
operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) {
|
||||
SmallBitVector Result(LHS);
|
||||
Result &= RHS;
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline SmallBitVector
|
||||
operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) {
|
||||
SmallBitVector Result(LHS);
|
||||
Result |= RHS;
|
||||
return Result;
|
||||
}
|
||||
|
||||
inline SmallBitVector
|
||||
operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
|
||||
SmallBitVector Result(LHS);
|
||||
Result ^= RHS;
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
namespace std {
|
||||
/// Implement std::swap in terms of BitVector swap.
|
||||
inline void
|
||||
swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) {
|
||||
LHS.swap(RHS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
307
thirdparty/clang/include/llvm/ADT/SmallPtrSet.h
vendored
Normal file
307
thirdparty/clang/include/llvm/ADT/SmallPtrSet.h
vendored
Normal file
@@ -0,0 +1,307 @@
|
||||
//===- 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 "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
|
||||
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:
|
||||
/// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
|
||||
const void **SmallArray;
|
||||
/// CurArray - This is the current set of buckets. If equal to SmallArray,
|
||||
/// then the set is in 'small mode'.
|
||||
const void **CurArray;
|
||||
/// CurArraySize - The allocated size of CurArray, always a power of two.
|
||||
unsigned CurArraySize;
|
||||
|
||||
// If small, this is # elts allocated consecutively
|
||||
unsigned NumElements;
|
||||
unsigned NumTombstones;
|
||||
|
||||
// Helper to copy construct a SmallPtrSet.
|
||||
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that);
|
||||
explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) :
|
||||
SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
|
||||
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
|
||||
"Initial size must be a power of two!");
|
||||
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; }
|
||||
|
||||
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(unsigned NewSize);
|
||||
|
||||
void operator=(const SmallPtrSetImpl &RHS) LLVM_DELETED_FUNCTION;
|
||||
protected:
|
||||
/// swap - Swaps the elements of two sets.
|
||||
/// Note: This method assumes that both sets have the same small size.
|
||||
void swap(SmallPtrSetImpl &RHS);
|
||||
|
||||
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;
|
||||
const void *const *End;
|
||||
public:
|
||||
explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
|
||||
: Bucket(BP), End(E) {
|
||||
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() {
|
||||
assert(Bucket <= End);
|
||||
while (Bucket != End &&
|
||||
(*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:
|
||||
typedef PtrTy value_type;
|
||||
typedef PtrTy reference;
|
||||
typedef PtrTy pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
explicit SmallPtrSetIterator(const void *const *BP, const void *const *E)
|
||||
: SmallPtrSetIteratorImpl(BP, E) {}
|
||||
|
||||
// Most methods provided by baseclass.
|
||||
|
||||
const PtrTy operator*() const {
|
||||
assert(Bucket < End);
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
|
||||
/// power of two (which means N itself if N is already a power of two).
|
||||
template<unsigned N>
|
||||
struct RoundUpToPowerOfTwo;
|
||||
|
||||
/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a
|
||||
/// helper template used to implement RoundUpToPowerOfTwo.
|
||||
template<unsigned N, bool isPowerTwo>
|
||||
struct RoundUpToPowerOfTwoH {
|
||||
enum { Val = N };
|
||||
};
|
||||
template<unsigned N>
|
||||
struct RoundUpToPowerOfTwoH<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 = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
|
||||
};
|
||||
};
|
||||
|
||||
template<unsigned N>
|
||||
struct RoundUpToPowerOfTwo {
|
||||
enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
|
||||
};
|
||||
|
||||
|
||||
/// SmallPtrSet - This class implements a set which is optimized 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 = RoundUpToPowerOfTwo<SmallSize>::Val };
|
||||
/// SmallStorage - Fixed size storage used in 'small mode'.
|
||||
const void *SmallStorage[SmallSizePowTwo];
|
||||
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
|
||||
public:
|
||||
SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {}
|
||||
SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {}
|
||||
|
||||
template<typename It>
|
||||
SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {
|
||||
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, CurArray+CurArraySize);
|
||||
}
|
||||
inline iterator end() const {
|
||||
return iterator(CurArray+CurArraySize, 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;
|
||||
}
|
||||
|
||||
/// swap - Swaps the elements of two sets.
|
||||
void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
|
||||
SmallPtrSetImpl::swap(RHS);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
/// Implement std::swap in terms of SmallPtrSet swap.
|
||||
template<class T, unsigned N>
|
||||
inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
|
||||
LHS.swap(RHS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
119
thirdparty/clang/include/llvm/ADT/SmallSet.h
vendored
Normal file
119
thirdparty/clang/include/llvm/ADT/SmallSet.h
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
//===- 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/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.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, typename C = std::less<T> >
|
||||
class SmallSet {
|
||||
/// Use a SmallVector to hold the elements here (even though it will never
|
||||
/// reach its 'large' stage) to avoid calling the default ctors of elements
|
||||
/// we will never use.
|
||||
SmallVector<T, N> Vector;
|
||||
std::set<T, C> 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.
|
||||
/// Returns true if the element is inserted (it was not in the set before).
|
||||
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
|
||||
300
thirdparty/clang/include/llvm/ADT/SmallString.h
vendored
Normal file
300
thirdparty/clang/include/llvm/ADT/SmallString.h
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
//===- 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/ADT/StringRef.h"
|
||||
|
||||
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 from a StringRef.
|
||||
SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
|
||||
|
||||
/// Initialize with a range.
|
||||
template<typename ItTy>
|
||||
SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
|
||||
|
||||
/// Copy ctor.
|
||||
SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {}
|
||||
|
||||
// Note that in order to add new overloads for append & assign, we have to
|
||||
// duplicate the inherited versions so as not to inadvertently hide them.
|
||||
|
||||
/// @}
|
||||
/// @name String Assignment
|
||||
/// @{
|
||||
|
||||
/// Assign from a repeated element.
|
||||
void assign(size_t NumElts, char Elt) {
|
||||
this->SmallVectorImpl<char>::assign(NumElts, Elt);
|
||||
}
|
||||
|
||||
/// Assign from an iterator pair.
|
||||
template<typename in_iter>
|
||||
void assign(in_iter S, in_iter E) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(S, E);
|
||||
}
|
||||
|
||||
/// Assign from a StringRef.
|
||||
void assign(StringRef RHS) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// Assign from a SmallVector.
|
||||
void assign(const SmallVectorImpl<char> &RHS) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Concatenation
|
||||
/// @{
|
||||
|
||||
/// Append from an iterator pair.
|
||||
template<typename in_iter>
|
||||
void append(in_iter S, in_iter E) {
|
||||
SmallVectorImpl<char>::append(S, E);
|
||||
}
|
||||
|
||||
void append(size_t NumInputs, char Elt) {
|
||||
SmallVectorImpl<char>::append(NumInputs, Elt);
|
||||
}
|
||||
|
||||
|
||||
/// Append from a StringRef.
|
||||
void append(StringRef RHS) {
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// Append from a SmallVector.
|
||||
void append(const SmallVectorImpl<char> &RHS) {
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Comparison
|
||||
/// @{
|
||||
|
||||
/// Check for string equality. This is more efficient than compare() when
|
||||
/// the relative ordering of inequal strings isn't needed.
|
||||
bool equals(StringRef RHS) const {
|
||||
return str().equals(RHS);
|
||||
}
|
||||
|
||||
/// Check for string equality, ignoring case.
|
||||
bool equals_lower(StringRef RHS) const {
|
||||
return str().equals_lower(RHS);
|
||||
}
|
||||
|
||||
/// Compare two strings; the result is -1, 0, or 1 if this string is
|
||||
/// lexicographically less than, equal to, or greater than the \p RHS.
|
||||
int compare(StringRef RHS) const {
|
||||
return str().compare(RHS);
|
||||
}
|
||||
|
||||
/// compare_lower - Compare two strings, ignoring case.
|
||||
int compare_lower(StringRef RHS) const {
|
||||
return str().compare_lower(RHS);
|
||||
}
|
||||
|
||||
/// compare_numeric - Compare two strings, treating sequences of digits as
|
||||
/// numbers.
|
||||
int compare_numeric(StringRef RHS) const {
|
||||
return str().compare_numeric(RHS);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Predicates
|
||||
/// @{
|
||||
|
||||
/// startswith - Check if this string starts with the given \p Prefix.
|
||||
bool startswith(StringRef Prefix) const {
|
||||
return str().startswith(Prefix);
|
||||
}
|
||||
|
||||
/// endswith - Check if this string ends with the given \p Suffix.
|
||||
bool endswith(StringRef Suffix) const {
|
||||
return str().endswith(Suffix);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Searching
|
||||
/// @{
|
||||
|
||||
/// find - Search for the first character \p C in the string.
|
||||
///
|
||||
/// \return - The index of the first occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
return str().find(C, From);
|
||||
}
|
||||
|
||||
/// Search for the first string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t find(StringRef Str, size_t From = 0) const {
|
||||
return str().find(Str, From);
|
||||
}
|
||||
|
||||
/// Search for the last character \p C in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t rfind(char C, size_t From = StringRef::npos) const {
|
||||
return str().rfind(C, From);
|
||||
}
|
||||
|
||||
/// Search for the last string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t rfind(StringRef Str) const {
|
||||
return str().rfind(Str);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is \p C, or npos if not
|
||||
/// found. Same as find.
|
||||
size_t find_first_of(char C, size_t From = 0) const {
|
||||
return str().find_first_of(C, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is in \p Chars, or npos if
|
||||
/// not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_of(StringRef Chars, size_t From = 0) const {
|
||||
return str().find_first_of(Chars, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is not \p C or npos if not
|
||||
/// found.
|
||||
size_t find_first_not_of(char C, size_t From = 0) const {
|
||||
return str().find_first_not_of(C, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is not in the string
|
||||
/// \p Chars, or npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
|
||||
return str().find_first_not_of(Chars, From);
|
||||
}
|
||||
|
||||
/// Find the last character in the string that is \p C, or npos if not
|
||||
/// found.
|
||||
size_t find_last_of(char C, size_t From = StringRef::npos) const {
|
||||
return str().find_last_of(C, From);
|
||||
}
|
||||
|
||||
/// Find the last character in the string that is in \p C, or npos if not
|
||||
/// found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_last_of(
|
||||
StringRef Chars, size_t From = StringRef::npos) const {
|
||||
return str().find_last_of(Chars, From);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Helpful Algorithms
|
||||
/// @{
|
||||
|
||||
/// Return the number of occurrences of \p C in the string.
|
||||
size_t count(char C) const {
|
||||
return str().count(C);
|
||||
}
|
||||
|
||||
/// Return the number of non-overlapped occurrences of \p Str in the
|
||||
/// string.
|
||||
size_t count(StringRef Str) const {
|
||||
return str().count(Str);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Substring Operations
|
||||
/// @{
|
||||
|
||||
/// Return a reference to the substring from [Start, Start + N).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param N The number of characters to included in the substring. If \p N
|
||||
/// exceeds the number of characters remaining in the string, the string
|
||||
/// suffix (starting with \p Start) will be returned.
|
||||
StringRef substr(size_t Start, size_t N = StringRef::npos) const {
|
||||
return str().substr(Start, N);
|
||||
}
|
||||
|
||||
/// Return a reference to the substring from [Start, End).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param End The index following the last character to include in the
|
||||
/// substring. If this is npos, or less than \p Start, or exceeds the
|
||||
/// number of characters remaining in the string, the string suffix
|
||||
/// (starting with \p Start) will be returned.
|
||||
StringRef slice(size_t Start, size_t End) const {
|
||||
return str().slice(Start, End);
|
||||
}
|
||||
|
||||
// Extra methods.
|
||||
|
||||
/// Explicit conversion to StringRef.
|
||||
StringRef str() const { return StringRef(this->begin(), this->size()); }
|
||||
|
||||
// TODO: Make this const, if it's safe...
|
||||
const char* c_str() {
|
||||
this->push_back(0);
|
||||
this->pop_back();
|
||||
return this->data();
|
||||
}
|
||||
|
||||
/// Implicit conversion to StringRef.
|
||||
operator StringRef() const { return str(); }
|
||||
|
||||
// Extra operators.
|
||||
const SmallString &operator=(StringRef RHS) {
|
||||
this->clear();
|
||||
return *this += RHS;
|
||||
}
|
||||
|
||||
SmallString &operator+=(StringRef RHS) {
|
||||
this->append(RHS.begin(), RHS.end());
|
||||
return *this;
|
||||
}
|
||||
SmallString &operator+=(char C) {
|
||||
this->push_back(C);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
944
thirdparty/clang/include/llvm/ADT/SmallVector.h
vendored
Normal file
944
thirdparty/clang/include/llvm/ADT/SmallVector.h
vendored
Normal file
@@ -0,0 +1,944 @@
|
||||
//===- 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/Support/AlignOf.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SmallVectorBase - This is all the non-templated stuff common to all
|
||||
/// SmallVectors.
|
||||
class SmallVectorBase {
|
||||
protected:
|
||||
void *BeginX, *EndX, *CapacityX;
|
||||
|
||||
protected:
|
||||
SmallVectorBase(void *FirstEl, size_t Size)
|
||||
: BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {}
|
||||
|
||||
/// grow_pod - This is an implementation of the grow() method which only works
|
||||
/// on POD-like data types and is out of line to reduce code duplication.
|
||||
void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize);
|
||||
|
||||
public:
|
||||
/// size_in_bytes - This returns size()*sizeof(T).
|
||||
size_t size_in_bytes() const {
|
||||
return size_t((char*)EndX - (char*)BeginX);
|
||||
}
|
||||
|
||||
/// capacity_in_bytes - This returns capacity()*sizeof(T).
|
||||
size_t capacity_in_bytes() const {
|
||||
return size_t((char*)CapacityX - (char*)BeginX);
|
||||
}
|
||||
|
||||
bool empty() const { return BeginX == EndX; }
|
||||
};
|
||||
|
||||
template <typename T, unsigned N> struct SmallVectorStorage;
|
||||
|
||||
/// SmallVectorTemplateCommon - This is the part of SmallVectorTemplateBase
|
||||
/// which does not depend on whether the type T is a POD. The extra dummy
|
||||
/// template argument is used by ArrayRef to avoid unnecessarily requiring T
|
||||
/// to be complete.
|
||||
template <typename T, typename = void>
|
||||
class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
private:
|
||||
template <typename, unsigned> friend struct SmallVectorStorage;
|
||||
|
||||
// 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. Use an array of char of sufficient alignment.
|
||||
typedef llvm::AlignedCharArrayUnion<T> U;
|
||||
U FirstEl;
|
||||
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
|
||||
|
||||
protected:
|
||||
SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {}
|
||||
|
||||
void grow_pod(size_t MinSizeInBytes, size_t TSize) {
|
||||
SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize);
|
||||
}
|
||||
|
||||
/// isSmall - Return true if this is a smallvector which has not had dynamic
|
||||
/// memory allocated for it.
|
||||
bool isSmall() const {
|
||||
return BeginX == static_cast<const void*>(&FirstEl);
|
||||
}
|
||||
|
||||
/// resetToSmall - Put this vector in a state of being small.
|
||||
void resetToSmall() {
|
||||
BeginX = EndX = CapacityX = &FirstEl;
|
||||
}
|
||||
|
||||
void setEnd(T *P) { this->EndX = P; }
|
||||
public:
|
||||
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;
|
||||
|
||||
// forward iterator creation methods.
|
||||
iterator begin() { return (iterator)this->BeginX; }
|
||||
const_iterator begin() const { return (const_iterator)this->BeginX; }
|
||||
iterator end() { return (iterator)this->EndX; }
|
||||
const_iterator end() const { return (const_iterator)this->EndX; }
|
||||
protected:
|
||||
iterator capacity_ptr() { return (iterator)this->CapacityX; }
|
||||
const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
|
||||
public:
|
||||
|
||||
// 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());}
|
||||
|
||||
size_type size() const { return end()-begin(); }
|
||||
size_type max_size() const { return size_type(-1) / sizeof(T); }
|
||||
|
||||
/// capacity - Return the total number of elements in the currently allocated
|
||||
/// buffer.
|
||||
size_t capacity() const { return capacity_ptr() - begin(); }
|
||||
|
||||
/// 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()); }
|
||||
|
||||
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() {
|
||||
assert(!empty());
|
||||
return begin()[0];
|
||||
}
|
||||
const_reference front() const {
|
||||
assert(!empty());
|
||||
return begin()[0];
|
||||
}
|
||||
|
||||
reference back() {
|
||||
assert(!empty());
|
||||
return end()[-1];
|
||||
}
|
||||
const_reference back() const {
|
||||
assert(!empty());
|
||||
return end()[-1];
|
||||
}
|
||||
};
|
||||
|
||||
/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
|
||||
/// implementations that are designed to work with non-POD-like T's.
|
||||
template <typename T, bool isPodLike>
|
||||
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
|
||||
protected:
|
||||
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
|
||||
|
||||
static void destroy_range(T *S, T *E) {
|
||||
while (S != E) {
|
||||
--E;
|
||||
E->~T();
|
||||
}
|
||||
}
|
||||
|
||||
/// move - Use move-assignment to move the range [I, E) onto the
|
||||
/// objects starting with "Dest". This is just <memory>'s
|
||||
/// std::move, but not all stdlibs actually provide that.
|
||||
template<typename It1, typename It2>
|
||||
static It2 move(It1 I, It1 E, It2 Dest) {
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
for (; I != E; ++I, ++Dest)
|
||||
*Dest = ::std::move(*I);
|
||||
return Dest;
|
||||
#else
|
||||
return ::std::copy(I, E, Dest);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// move_backward - Use move-assignment to move the range
|
||||
/// [I, E) onto the objects ending at "Dest", moving objects
|
||||
/// in reverse order. This is just <algorithm>'s
|
||||
/// std::move_backward, but not all stdlibs actually provide that.
|
||||
template<typename It1, typename It2>
|
||||
static It2 move_backward(It1 I, It1 E, It2 Dest) {
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
while (I != E)
|
||||
*--Dest = ::std::move(*--E);
|
||||
return Dest;
|
||||
#else
|
||||
return ::std::copy_backward(I, E, Dest);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// uninitialized_move - Move the range [I, E) into the uninitialized
|
||||
/// memory starting with "Dest", constructing elements as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
for (; I != E; ++I, ++Dest)
|
||||
::new ((void*) &*Dest) T(::std::move(*I));
|
||||
#else
|
||||
::std::uninitialized_copy(I, E, Dest);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized
|
||||
/// memory starting with "Dest", constructing elements as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
|
||||
std::uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
/// grow - Grow the allocated memory (without initializing new
|
||||
/// elements), doubling the size of the allocated memory.
|
||||
/// Guarantees space for at least one more element, or MinSize more
|
||||
/// elements if specified.
|
||||
void grow(size_t MinSize = 0);
|
||||
|
||||
public:
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
::new ((void*) this->end()) T(Elt);
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
void push_back(T &&Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
::new ((void*) this->end()) T(::std::move(Elt));
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
#endif
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
this->end()->~T();
|
||||
}
|
||||
};
|
||||
|
||||
// Define this out-of-line to dissuade the C++ compiler from inlining it.
|
||||
template <typename T, bool isPodLike>
|
||||
void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
|
||||
size_t CurCapacity = this->capacity();
|
||||
size_t CurSize = this->size();
|
||||
// Always grow, even from zero.
|
||||
size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2));
|
||||
if (NewCapacity < MinSize)
|
||||
NewCapacity = MinSize;
|
||||
T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
|
||||
|
||||
// Move the elements over.
|
||||
this->uninitialized_move(this->begin(), this->end(), NewElts);
|
||||
|
||||
// Destroy the original elements.
|
||||
destroy_range(this->begin(), this->end());
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!this->isSmall())
|
||||
free(this->begin());
|
||||
|
||||
this->setEnd(NewElts+CurSize);
|
||||
this->BeginX = NewElts;
|
||||
this->CapacityX = this->begin()+NewCapacity;
|
||||
}
|
||||
|
||||
|
||||
/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
|
||||
/// implementations that are designed to work with POD-like T's.
|
||||
template <typename T>
|
||||
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
|
||||
protected:
|
||||
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
|
||||
|
||||
// No need to do a destroy loop for POD's.
|
||||
static void destroy_range(T *, T *) {}
|
||||
|
||||
/// move - Use move-assignment to move the range [I, E) onto the
|
||||
/// objects starting with "Dest". For PODs, this is just memcpy.
|
||||
template<typename It1, typename It2>
|
||||
static It2 move(It1 I, It1 E, It2 Dest) {
|
||||
return ::std::copy(I, E, Dest);
|
||||
}
|
||||
|
||||
/// move_backward - Use move-assignment to move the range
|
||||
/// [I, E) onto the objects ending at "Dest", moving objects
|
||||
/// in reverse order.
|
||||
template<typename It1, typename It2>
|
||||
static It2 move_backward(It1 I, It1 E, It2 Dest) {
|
||||
return ::std::copy_backward(I, E, Dest);
|
||||
}
|
||||
|
||||
/// uninitialized_move - Move the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_move(It1 I, It1 E, It2 Dest) {
|
||||
// Just do a copy.
|
||||
uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
|
||||
// Arbitrary iterator types; just use the basic implementation.
|
||||
std::uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename T1, typename T2>
|
||||
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) {
|
||||
// Use memcpy for PODs iterated by pointers (which includes SmallVector
|
||||
// iterators): std::uninitialized_copy optimizes to memmove, but we can
|
||||
// use memcpy here.
|
||||
memcpy(Dest, I, (E-I)*sizeof(T));
|
||||
}
|
||||
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(size_t MinSize = 0) {
|
||||
this->grow_pod(MinSize*sizeof(T), sizeof(T));
|
||||
}
|
||||
public:
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
memcpy(this->end(), &Elt, sizeof(T));
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// 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 : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
|
||||
|
||||
SmallVectorImpl(const SmallVectorImpl&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
typedef typename SuperClass::iterator iterator;
|
||||
typedef typename SuperClass::size_type size_type;
|
||||
|
||||
protected:
|
||||
// Default ctor - Initialize to empty.
|
||||
explicit SmallVectorImpl(unsigned N)
|
||||
: SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
|
||||
}
|
||||
|
||||
public:
|
||||
~SmallVectorImpl() {
|
||||
// Destroy the constructed elements in the vector.
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!this->isSmall())
|
||||
free(this->begin());
|
||||
}
|
||||
|
||||
|
||||
void clear() {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->EndX = this->BeginX;
|
||||
}
|
||||
|
||||
void resize(unsigned N) {
|
||||
if (N < this->size()) {
|
||||
this->destroy_range(this->begin()+N, this->end());
|
||||
this->setEnd(this->begin()+N);
|
||||
} else if (N > this->size()) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
std::uninitialized_fill(this->end(), this->begin()+N, T());
|
||||
this->setEnd(this->begin()+N);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(unsigned N, const T &NV) {
|
||||
if (N < this->size()) {
|
||||
this->destroy_range(this->begin()+N, this->end());
|
||||
this->setEnd(this->begin()+N);
|
||||
} else if (N > this->size()) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
std::uninitialized_fill(this->end(), this->begin()+N, NV);
|
||||
this->setEnd(this->begin()+N);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(unsigned N) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
T Result = ::std::move(this->back());
|
||||
#else
|
||||
T Result = this->back();
|
||||
#endif
|
||||
this->pop_back();
|
||||
return Result;
|
||||
}
|
||||
|
||||
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(this->capacity_ptr()-this->end()))
|
||||
this->grow(this->size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
// TODO: NEED To compile time dispatch on whether in_iter is a random access
|
||||
// iterator to use the fast uninitialized_copy.
|
||||
std::uninitialized_copy(in_start, in_end, this->end());
|
||||
this->setEnd(this->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(this->capacity_ptr()-this->end()))
|
||||
this->grow(this->size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
|
||||
this->setEnd(this->end() + NumInputs);
|
||||
}
|
||||
|
||||
void assign(unsigned NumElts, const T &Elt) {
|
||||
clear();
|
||||
if (this->capacity() < NumElts)
|
||||
this->grow(NumElts);
|
||||
this->setEnd(this->begin()+NumElts);
|
||||
std::uninitialized_fill(this->begin(), this->end(), Elt);
|
||||
}
|
||||
|
||||
iterator erase(iterator I) {
|
||||
assert(I >= this->begin() && "Iterator to erase is out of bounds.");
|
||||
assert(I < this->end() && "Erasing at past-the-end iterator.");
|
||||
|
||||
iterator N = I;
|
||||
// Shift all elts down one.
|
||||
this->move(I+1, this->end(), I);
|
||||
// Drop the last elt.
|
||||
this->pop_back();
|
||||
return(N);
|
||||
}
|
||||
|
||||
iterator erase(iterator S, iterator E) {
|
||||
assert(S >= this->begin() && "Range to erase is out of bounds.");
|
||||
assert(S <= E && "Trying to erase invalid range.");
|
||||
assert(E <= this->end() && "Trying to erase past the end.");
|
||||
|
||||
iterator N = S;
|
||||
// Shift all elts down.
|
||||
iterator I = this->move(E, this->end(), S);
|
||||
// Drop the last elts.
|
||||
this->destroy_range(I, this->end());
|
||||
this->setEnd(I);
|
||||
return(N);
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
iterator insert(iterator I, T &&Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
this->push_back(::std::move(Elt));
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
::new ((void*) this->end()) T(::std::move(this->back()));
|
||||
this->setEnd(this->end()+1);
|
||||
// Push everything else over.
|
||||
this->move_backward(I, this->end()-1, this->end());
|
||||
|
||||
// If we just moved the element we're inserting, be sure to update
|
||||
// the reference.
|
||||
T *EltPtr = &Elt;
|
||||
if (I <= EltPtr && EltPtr < this->EndX)
|
||||
++EltPtr;
|
||||
|
||||
*I = ::std::move(*EltPtr);
|
||||
return I;
|
||||
}
|
||||
size_t EltNo = I-this->begin();
|
||||
this->grow();
|
||||
I = this->begin()+EltNo;
|
||||
goto Retry;
|
||||
}
|
||||
#endif
|
||||
|
||||
iterator insert(iterator I, const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
this->push_back(Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
::new ((void*) this->end()) T(this->back());
|
||||
this->setEnd(this->end()+1);
|
||||
// Push everything else over.
|
||||
this->move_backward(I, this->end()-1, this->end());
|
||||
|
||||
// If we just moved the element we're inserting, be sure to update
|
||||
// the reference.
|
||||
const T *EltPtr = &Elt;
|
||||
if (I <= EltPtr && EltPtr < this->EndX)
|
||||
++EltPtr;
|
||||
|
||||
*I = *EltPtr;
|
||||
return I;
|
||||
}
|
||||
size_t EltNo = I-this->begin();
|
||||
this->grow();
|
||||
I = this->begin()+EltNo;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(NumToInsert, Elt);
|
||||
return this->begin()+InsertElt;
|
||||
}
|
||||
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->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(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(this->end()-NumToInsert, this->end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
this->move_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.
|
||||
|
||||
// Move over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_move(I, OldEnd, this->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) {
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(From, To);
|
||||
return this->begin()+InsertElt;
|
||||
}
|
||||
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
|
||||
size_t NumToInsert = std::distance(From, To);
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->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(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(this->end()-NumToInsert, this->end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
this->move_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.
|
||||
|
||||
// Move over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
|
||||
*J = *From;
|
||||
++J; ++From;
|
||||
}
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
this->uninitialized_copy(From, To, OldEnd);
|
||||
return I;
|
||||
}
|
||||
|
||||
SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
|
||||
#endif
|
||||
|
||||
bool operator==(const SmallVectorImpl &RHS) const {
|
||||
if (this->size() != RHS.size()) return false;
|
||||
return std::equal(this->begin(), this->end(), RHS.begin());
|
||||
}
|
||||
bool operator!=(const SmallVectorImpl &RHS) const {
|
||||
return !(*this == RHS);
|
||||
}
|
||||
|
||||
bool operator<(const SmallVectorImpl &RHS) const {
|
||||
return std::lexicographical_compare(this->begin(), this->end(),
|
||||
RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// Set the array size to \p N, which the current array must have enough
|
||||
/// capacity for.
|
||||
///
|
||||
/// This does not construct or destroy any elements in the vector.
|
||||
///
|
||||
/// Clients can use this in conjunction with capacity() to write past the end
|
||||
/// of the buffer when they know that more elements are available, and only
|
||||
/// update the size later. This avoids the cost of value initializing elements
|
||||
/// which will only be overwritten.
|
||||
void set_size(unsigned N) {
|
||||
assert(N <= this->capacity());
|
||||
this->setEnd(this->begin() + N);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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 (!this->isSmall() && !RHS.isSmall()) {
|
||||
std::swap(this->BeginX, RHS.BeginX);
|
||||
std::swap(this->EndX, RHS.EndX);
|
||||
std::swap(this->CapacityX, RHS.CapacityX);
|
||||
return;
|
||||
}
|
||||
if (RHS.size() > this->capacity())
|
||||
this->grow(RHS.size());
|
||||
if (this->size() > RHS.capacity())
|
||||
RHS.grow(this->size());
|
||||
|
||||
// Swap the shared elements.
|
||||
size_t NumShared = this->size();
|
||||
if (NumShared > RHS.size()) NumShared = RHS.size();
|
||||
for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
|
||||
std::swap((*this)[i], RHS[i]);
|
||||
|
||||
// Copy over the extra elts.
|
||||
if (this->size() > RHS.size()) {
|
||||
size_t EltDiff = this->size() - RHS.size();
|
||||
this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
|
||||
RHS.setEnd(RHS.end()+EltDiff);
|
||||
this->destroy_range(this->begin()+NumShared, this->end());
|
||||
this->setEnd(this->begin()+NumShared);
|
||||
} else if (RHS.size() > this->size()) {
|
||||
size_t EltDiff = RHS.size() - this->size();
|
||||
this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
|
||||
this->setEnd(this->end() + EltDiff);
|
||||
this->destroy_range(RHS.begin()+NumShared, RHS.end());
|
||||
RHS.setEnd(RHS.begin()+NumShared);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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.
|
||||
size_t RHSSize = RHS.size();
|
||||
size_t CurSize = this->size();
|
||||
if (CurSize >= RHSSize) {
|
||||
// Assign common elements.
|
||||
iterator NewEnd;
|
||||
if (RHSSize)
|
||||
NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
|
||||
else
|
||||
NewEnd = this->begin();
|
||||
|
||||
// Destroy excess elements.
|
||||
this->destroy_range(NewEnd, this->end());
|
||||
|
||||
// Trim.
|
||||
this->setEnd(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.
|
||||
// FIXME: don't do this if they're efficiently moveable.
|
||||
if (this->capacity() < RHSSize) {
|
||||
// Destroy current elements.
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->setEnd(this->begin());
|
||||
CurSize = 0;
|
||||
this->grow(RHSSize);
|
||||
} else if (CurSize) {
|
||||
// Otherwise, use assignment for the already-constructed elements.
|
||||
std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
|
||||
}
|
||||
|
||||
// Copy construct the new elements in place.
|
||||
this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
|
||||
this->begin()+CurSize);
|
||||
|
||||
// Set end.
|
||||
this->setEnd(this->begin()+RHSSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
template <typename T>
|
||||
SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
|
||||
// Avoid self-assignment.
|
||||
if (this == &RHS) return *this;
|
||||
|
||||
// If the RHS isn't small, clear this vector and then steal its buffer.
|
||||
if (!RHS.isSmall()) {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
if (!this->isSmall()) free(this->begin());
|
||||
this->BeginX = RHS.BeginX;
|
||||
this->EndX = RHS.EndX;
|
||||
this->CapacityX = RHS.CapacityX;
|
||||
RHS.resetToSmall();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we already have sufficient space, assign the common elements, then
|
||||
// destroy any excess.
|
||||
size_t RHSSize = RHS.size();
|
||||
size_t CurSize = this->size();
|
||||
if (CurSize >= RHSSize) {
|
||||
// Assign common elements.
|
||||
iterator NewEnd = this->begin();
|
||||
if (RHSSize)
|
||||
NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd);
|
||||
|
||||
// Destroy excess elements and trim the bounds.
|
||||
this->destroy_range(NewEnd, this->end());
|
||||
this->setEnd(NewEnd);
|
||||
|
||||
// Clear the RHS.
|
||||
RHS.clear();
|
||||
|
||||
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.
|
||||
// FIXME: this may not actually make any sense if we can efficiently move
|
||||
// elements.
|
||||
if (this->capacity() < RHSSize) {
|
||||
// Destroy current elements.
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->setEnd(this->begin());
|
||||
CurSize = 0;
|
||||
this->grow(RHSSize);
|
||||
} else if (CurSize) {
|
||||
// Otherwise, use assignment for the already-constructed elements.
|
||||
this->move(RHS.begin(), RHS.end(), this->begin());
|
||||
}
|
||||
|
||||
// Move-construct the new elements in place.
|
||||
this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
|
||||
this->begin()+CurSize);
|
||||
|
||||
// Set end.
|
||||
this->setEnd(this->begin()+RHSSize);
|
||||
|
||||
RHS.clear();
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Storage for the SmallVector elements which aren't contained in
|
||||
/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1'
|
||||
/// element is in the base class. This is specialized for the N=1 and N=0 cases
|
||||
/// to avoid allocating unnecessary storage.
|
||||
template <typename T, unsigned N>
|
||||
struct SmallVectorStorage {
|
||||
typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1];
|
||||
};
|
||||
template <typename T> struct SmallVectorStorage<T, 1> {};
|
||||
template <typename T> struct SmallVectorStorage<T, 0> {};
|
||||
|
||||
/// 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> {
|
||||
/// Storage - Inline space for elements which aren't stored in the base class.
|
||||
SmallVectorStorage<T, N> Storage;
|
||||
public:
|
||||
SmallVector() : SmallVectorImpl<T>(N) {
|
||||
}
|
||||
|
||||
explicit SmallVector(unsigned Size, const T &Value = T())
|
||||
: SmallVectorImpl<T>(N) {
|
||||
this->assign(Size, Value);
|
||||
}
|
||||
|
||||
template<typename ItTy>
|
||||
SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
|
||||
this->append(S, E);
|
||||
}
|
||||
|
||||
SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
|
||||
if (!RHS.empty())
|
||||
SmallVectorImpl<T>::operator=(RHS);
|
||||
}
|
||||
|
||||
const SmallVector &operator=(const SmallVector &RHS) {
|
||||
SmallVectorImpl<T>::operator=(RHS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
|
||||
if (!RHS.empty())
|
||||
SmallVectorImpl<T>::operator=(::std::move(RHS));
|
||||
}
|
||||
|
||||
const SmallVector &operator=(SmallVector &&RHS) {
|
||||
SmallVectorImpl<T>::operator=(::std::move(RHS));
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template<typename T, unsigned N>
|
||||
static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
|
||||
return X.capacity_in_bytes();
|
||||
}
|
||||
|
||||
} // 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
|
||||
897
thirdparty/clang/include/llvm/ADT/SparseBitVector.h
vendored
Normal file
897
thirdparty/clang/include/llvm/ADT/SparseBitVector.h
vendored
Normal file
@@ -0,0 +1,897 @@
|
||||
//===- 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 "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
|
||||
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
|
||||
: public 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
|
||||
llvm_unreachable("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]);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
llvm_unreachable("Illegal empty element");
|
||||
}
|
||||
|
||||
/// 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 &= ~0UL << BitPos;
|
||||
|
||||
if (Copy != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
|
||||
llvm_unreachable("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]);
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
llvm_unreachable("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;
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned ElementSize>
|
||||
struct ilist_traits<SparseBitVectorElement<ElementSize> >
|
||||
: public ilist_default_traits<SparseBitVectorElement<ElementSize> > {
|
||||
typedef SparseBitVectorElement<ElementSize> Element;
|
||||
|
||||
Element *createSentinel() const { return static_cast<Element *>(&Sentinel); }
|
||||
static void destroySentinel(Element *) {}
|
||||
|
||||
Element *provideInitialHead() const { return createSentinel(); }
|
||||
Element *ensureHead(Element *) const { return createSentinel(); }
|
||||
static void noteHead(Element *, Element *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_half_node<Element> Sentinel;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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, raw_ostream &out) {
|
||||
out << "[";
|
||||
|
||||
typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(),
|
||||
be = LHS.end();
|
||||
if (bi != be) {
|
||||
out << *bi;
|
||||
for (++bi; bi != be; ++bi) {
|
||||
out << " " << *bi;
|
||||
}
|
||||
}
|
||||
out << "]\n";
|
||||
}
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
526
thirdparty/clang/include/llvm/ADT/SparseMultiSet.h
vendored
Normal file
526
thirdparty/clang/include/llvm/ADT/SparseMultiSet.h
vendored
Normal file
@@ -0,0 +1,526 @@
|
||||
//===--- llvm/ADT/SparseMultiSet.h - Sparse multiset ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SparseMultiSet class, which adds multiset behavior to
|
||||
// the SparseSet.
|
||||
//
|
||||
// A sparse multiset holds a small number of objects identified by integer keys
|
||||
// from a moderately sized universe. The sparse multiset uses more memory than
|
||||
// other containers in order to provide faster operations. Any key can map to
|
||||
// multiple values. A SparseMultiSetNode class is provided, which serves as a
|
||||
// convenient base class for the contents of a SparseMultiSet.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_SPARSEMULTISET_H
|
||||
#define LLVM_ADT_SPARSEMULTISET_H
|
||||
|
||||
#include "llvm/ADT/SparseSet.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Fast multiset implementation for objects that can be identified by small
|
||||
/// unsigned keys.
|
||||
///
|
||||
/// SparseMultiSet allocates memory proportional to the size of the key
|
||||
/// universe, so it is not recommended for building composite data structures.
|
||||
/// It is useful for algorithms that require a single set with fast operations.
|
||||
///
|
||||
/// Compared to DenseSet and DenseMap, SparseMultiSet provides constant-time
|
||||
/// fast clear() as fast as a vector. The find(), insert(), and erase()
|
||||
/// operations are all constant time, and typically faster than a hash table.
|
||||
/// The iteration order doesn't depend on numerical key values, it only depends
|
||||
/// on the order of insert() and erase() operations. Iteration order is the
|
||||
/// insertion order. Iteration is only provided over elements of equivalent
|
||||
/// keys, but iterators are bidirectional.
|
||||
///
|
||||
/// Compared to BitVector, SparseMultiSet<unsigned> uses 8x-40x more memory, but
|
||||
/// offers constant-time clear() and size() operations as well as fast iteration
|
||||
/// independent on the size of the universe.
|
||||
///
|
||||
/// SparseMultiSet contains a dense vector holding all the objects and a sparse
|
||||
/// array holding indexes into the dense vector. Most of the memory is used by
|
||||
/// the sparse array which is the size of the key universe. The SparseT template
|
||||
/// parameter provides a space/speed tradeoff for sets holding many elements.
|
||||
///
|
||||
/// When SparseT is uint32_t, find() only touches up to 3 cache lines, but the
|
||||
/// sparse array uses 4 x Universe bytes.
|
||||
///
|
||||
/// When SparseT is uint8_t (the default), find() touches up to 3+[N/256] cache
|
||||
/// lines, but the sparse array is 4x smaller. N is the number of elements in
|
||||
/// the set.
|
||||
///
|
||||
/// For sets that may grow to thousands of elements, SparseT should be set to
|
||||
/// uint16_t or uint32_t.
|
||||
///
|
||||
/// Multiset behavior is provided by providing doubly linked lists for values
|
||||
/// that are inlined in the dense vector. SparseMultiSet is a good choice when
|
||||
/// one desires a growable number of entries per key, as it will retain the
|
||||
/// SparseSet algorithmic properties despite being growable. Thus, it is often a
|
||||
/// better choice than a SparseSet of growable containers or a vector of
|
||||
/// vectors. SparseMultiSet also keeps iterators valid after erasure (provided
|
||||
/// the iterators don't point to the element erased), allowing for more
|
||||
/// intuitive and fast removal.
|
||||
///
|
||||
/// @tparam ValueT The type of objects in the set.
|
||||
/// @tparam KeyFunctorT A functor that computes an unsigned index from KeyT.
|
||||
/// @tparam SparseT An unsigned integer type. See above.
|
||||
///
|
||||
template<typename ValueT,
|
||||
typename KeyFunctorT = llvm::identity<unsigned>,
|
||||
typename SparseT = uint8_t>
|
||||
class SparseMultiSet {
|
||||
/// The actual data that's stored, as a doubly-linked list implemented via
|
||||
/// indices into the DenseVector. The doubly linked list is implemented
|
||||
/// circular in Prev indices, and INVALID-terminated in Next indices. This
|
||||
/// provides efficient access to list tails. These nodes can also be
|
||||
/// tombstones, in which case they are actually nodes in a single-linked
|
||||
/// freelist of recyclable slots.
|
||||
struct SMSNode {
|
||||
static const unsigned INVALID = ~0U;
|
||||
|
||||
ValueT Data;
|
||||
unsigned Prev;
|
||||
unsigned Next;
|
||||
|
||||
SMSNode(ValueT D, unsigned P, unsigned N) : Data(D), Prev(P), Next(N) { }
|
||||
|
||||
/// List tails have invalid Nexts.
|
||||
bool isTail() const {
|
||||
return Next == INVALID;
|
||||
}
|
||||
|
||||
/// Whether this node is a tombstone node, and thus is in our freelist.
|
||||
bool isTombstone() const {
|
||||
return Prev == INVALID;
|
||||
}
|
||||
|
||||
/// Since the list is circular in Prev, all non-tombstone nodes have a valid
|
||||
/// Prev.
|
||||
bool isValid() const { return Prev != INVALID; }
|
||||
};
|
||||
|
||||
typedef typename KeyFunctorT::argument_type KeyT;
|
||||
typedef SmallVector<SMSNode, 8> DenseT;
|
||||
DenseT Dense;
|
||||
SparseT *Sparse;
|
||||
unsigned Universe;
|
||||
KeyFunctorT KeyIndexOf;
|
||||
SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf;
|
||||
|
||||
/// We have a built-in recycler for reusing tombstone slots. This recycler
|
||||
/// puts a singly-linked free list into tombstone slots, allowing us quick
|
||||
/// erasure, iterator preservation, and dense size.
|
||||
unsigned FreelistIdx;
|
||||
unsigned NumFree;
|
||||
|
||||
unsigned sparseIndex(const ValueT &Val) const {
|
||||
assert(ValIndexOf(Val) < Universe &&
|
||||
"Invalid key in set. Did object mutate?");
|
||||
return ValIndexOf(Val);
|
||||
}
|
||||
unsigned sparseIndex(const SMSNode &N) const { return sparseIndex(N.Data); }
|
||||
|
||||
// Disable copy construction and assignment.
|
||||
// This data structure is not meant to be used that way.
|
||||
SparseMultiSet(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
|
||||
SparseMultiSet &operator=(const SparseMultiSet&) LLVM_DELETED_FUNCTION;
|
||||
|
||||
/// Whether the given entry is the head of the list. List heads's previous
|
||||
/// pointers are to the tail of the list, allowing for efficient access to the
|
||||
/// list tail. D must be a valid entry node.
|
||||
bool isHead(const SMSNode &D) const {
|
||||
assert(D.isValid() && "Invalid node for head");
|
||||
return Dense[D.Prev].isTail();
|
||||
}
|
||||
|
||||
/// Whether the given entry is a singleton entry, i.e. the only entry with
|
||||
/// that key.
|
||||
bool isSingleton(const SMSNode &N) const {
|
||||
assert(N.isValid() && "Invalid node for singleton");
|
||||
// Is N its own predecessor?
|
||||
return &Dense[N.Prev] == &N;
|
||||
}
|
||||
|
||||
/// Add in the given SMSNode. Uses a free entry in our freelist if
|
||||
/// available. Returns the index of the added node.
|
||||
unsigned addValue(const ValueT& V, unsigned Prev, unsigned Next) {
|
||||
if (NumFree == 0) {
|
||||
Dense.push_back(SMSNode(V, Prev, Next));
|
||||
return Dense.size() - 1;
|
||||
}
|
||||
|
||||
// Peel off a free slot
|
||||
unsigned Idx = FreelistIdx;
|
||||
unsigned NextFree = Dense[Idx].Next;
|
||||
assert(Dense[Idx].isTombstone() && "Non-tombstone free?");
|
||||
|
||||
Dense[Idx] = SMSNode(V, Prev, Next);
|
||||
FreelistIdx = NextFree;
|
||||
--NumFree;
|
||||
return Idx;
|
||||
}
|
||||
|
||||
/// Make the current index a new tombstone. Pushes it onto the freelist.
|
||||
void makeTombstone(unsigned Idx) {
|
||||
Dense[Idx].Prev = SMSNode::INVALID;
|
||||
Dense[Idx].Next = FreelistIdx;
|
||||
FreelistIdx = Idx;
|
||||
++NumFree;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef ValueT value_type;
|
||||
typedef ValueT &reference;
|
||||
typedef const ValueT &const_reference;
|
||||
typedef ValueT *pointer;
|
||||
typedef const ValueT *const_pointer;
|
||||
|
||||
SparseMultiSet()
|
||||
: Sparse(0), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) { }
|
||||
|
||||
~SparseMultiSet() { free(Sparse); }
|
||||
|
||||
/// Set the universe size which determines the largest key the set can hold.
|
||||
/// The universe must be sized before any elements can be added.
|
||||
///
|
||||
/// @param U Universe size. All object keys must be less than U.
|
||||
///
|
||||
void setUniverse(unsigned U) {
|
||||
// It's not hard to resize the universe on a non-empty set, but it doesn't
|
||||
// seem like a likely use case, so we can add that code when we need it.
|
||||
assert(empty() && "Can only resize universe on an empty map");
|
||||
// Hysteresis prevents needless reallocations.
|
||||
if (U >= Universe/4 && U <= Universe)
|
||||
return;
|
||||
free(Sparse);
|
||||
// The Sparse array doesn't actually need to be initialized, so malloc
|
||||
// would be enough here, but that will cause tools like valgrind to
|
||||
// complain about branching on uninitialized data.
|
||||
Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
|
||||
Universe = U;
|
||||
}
|
||||
|
||||
/// Our iterators are iterators over the collection of objects that share a
|
||||
/// key.
|
||||
template<typename SMSPtrTy>
|
||||
class iterator_base : public std::iterator<std::bidirectional_iterator_tag,
|
||||
ValueT> {
|
||||
friend class SparseMultiSet;
|
||||
SMSPtrTy SMS;
|
||||
unsigned Idx;
|
||||
unsigned SparseIdx;
|
||||
|
||||
iterator_base(SMSPtrTy P, unsigned I, unsigned SI)
|
||||
: SMS(P), Idx(I), SparseIdx(SI) { }
|
||||
|
||||
/// Whether our iterator has fallen outside our dense vector.
|
||||
bool isEnd() const {
|
||||
if (Idx == SMSNode::INVALID)
|
||||
return true;
|
||||
|
||||
assert(Idx < SMS->Dense.size() && "Out of range, non-INVALID Idx?");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Whether our iterator is properly keyed, i.e. the SparseIdx is valid
|
||||
bool isKeyed() const { return SparseIdx < SMS->Universe; }
|
||||
|
||||
unsigned Prev() const { return SMS->Dense[Idx].Prev; }
|
||||
unsigned Next() const { return SMS->Dense[Idx].Next; }
|
||||
|
||||
void setPrev(unsigned P) { SMS->Dense[Idx].Prev = P; }
|
||||
void setNext(unsigned N) { SMS->Dense[Idx].Next = N; }
|
||||
|
||||
public:
|
||||
typedef std::iterator<std::bidirectional_iterator_tag, ValueT> super;
|
||||
typedef typename super::value_type value_type;
|
||||
typedef typename super::difference_type difference_type;
|
||||
typedef typename super::pointer pointer;
|
||||
typedef typename super::reference reference;
|
||||
|
||||
iterator_base(const iterator_base &RHS)
|
||||
: SMS(RHS.SMS), Idx(RHS.Idx), SparseIdx(RHS.SparseIdx) { }
|
||||
|
||||
const iterator_base &operator=(const iterator_base &RHS) {
|
||||
SMS = RHS.SMS;
|
||||
Idx = RHS.Idx;
|
||||
SparseIdx = RHS.SparseIdx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
|
||||
"Dereferencing iterator of invalid key or index");
|
||||
|
||||
return SMS->Dense[Idx].Data;
|
||||
}
|
||||
pointer operator->() const { return &operator*(); }
|
||||
|
||||
/// Comparison operators
|
||||
bool operator==(const iterator_base &RHS) const {
|
||||
// end compares equal
|
||||
if (SMS == RHS.SMS && Idx == RHS.Idx) {
|
||||
assert((isEnd() || SparseIdx == RHS.SparseIdx) &&
|
||||
"Same dense entry, but different keys?");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator_base &RHS) const {
|
||||
return !operator==(RHS);
|
||||
}
|
||||
|
||||
/// Increment and decrement operators
|
||||
iterator_base &operator--() { // predecrement - Back up
|
||||
assert(isKeyed() && "Decrementing an invalid iterator");
|
||||
assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) &&
|
||||
"Decrementing head of list");
|
||||
|
||||
// If we're at the end, then issue a new find()
|
||||
if (isEnd())
|
||||
Idx = SMS->findIndex(SparseIdx).Prev();
|
||||
else
|
||||
Idx = Prev();
|
||||
|
||||
return *this;
|
||||
}
|
||||
iterator_base &operator++() { // preincrement - Advance
|
||||
assert(!isEnd() && isKeyed() && "Incrementing an invalid/end iterator");
|
||||
Idx = Next();
|
||||
return *this;
|
||||
}
|
||||
iterator_base operator--(int) { // postdecrement
|
||||
iterator_base I(*this);
|
||||
--*this;
|
||||
return I;
|
||||
}
|
||||
iterator_base operator++(int) { // postincrement
|
||||
iterator_base I(*this);
|
||||
++*this;
|
||||
return I;
|
||||
}
|
||||
};
|
||||
typedef iterator_base<SparseMultiSet *> iterator;
|
||||
typedef iterator_base<const SparseMultiSet *> const_iterator;
|
||||
|
||||
// Convenience types
|
||||
typedef std::pair<iterator, iterator> RangePair;
|
||||
|
||||
/// Returns an iterator past this container. Note that such an iterator cannot
|
||||
/// be decremented, but will compare equal to other end iterators.
|
||||
iterator end() { return iterator(this, SMSNode::INVALID, SMSNode::INVALID); }
|
||||
const_iterator end() const {
|
||||
return const_iterator(this, SMSNode::INVALID, SMSNode::INVALID);
|
||||
}
|
||||
|
||||
/// Returns true if the set is empty.
|
||||
///
|
||||
/// This is not the same as BitVector::empty().
|
||||
///
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
/// Returns the number of elements in the set.
|
||||
///
|
||||
/// This is not the same as BitVector::size() which returns the size of the
|
||||
/// universe.
|
||||
///
|
||||
unsigned size() const {
|
||||
assert(NumFree <= Dense.size() && "Out-of-bounds free entries");
|
||||
return Dense.size() - NumFree;
|
||||
}
|
||||
|
||||
/// Clears the set. This is a very fast constant time operation.
|
||||
///
|
||||
void clear() {
|
||||
// Sparse does not need to be cleared, see find().
|
||||
Dense.clear();
|
||||
NumFree = 0;
|
||||
FreelistIdx = SMSNode::INVALID;
|
||||
}
|
||||
|
||||
/// Find an element by its index.
|
||||
///
|
||||
/// @param Idx A valid index to find.
|
||||
/// @returns An iterator to the element identified by key, or end().
|
||||
///
|
||||
iterator findIndex(unsigned Idx) {
|
||||
assert(Idx < Universe && "Key out of range");
|
||||
assert(std::numeric_limits<SparseT>::is_integer &&
|
||||
!std::numeric_limits<SparseT>::is_signed &&
|
||||
"SparseT must be an unsigned integer type");
|
||||
const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
|
||||
for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) {
|
||||
const unsigned FoundIdx = sparseIndex(Dense[i]);
|
||||
// Check that we're pointing at the correct entry and that it is the head
|
||||
// of a valid list.
|
||||
if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i]))
|
||||
return iterator(this, i, Idx);
|
||||
// Stride is 0 when SparseT >= unsigned. We don't need to loop.
|
||||
if (!Stride)
|
||||
break;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
/// Find an element by its key.
|
||||
///
|
||||
/// @param Key A valid key to find.
|
||||
/// @returns An iterator to the element identified by key, or end().
|
||||
///
|
||||
iterator find(const KeyT &Key) {
|
||||
return findIndex(KeyIndexOf(Key));
|
||||
}
|
||||
|
||||
const_iterator find(const KeyT &Key) const {
|
||||
iterator I = const_cast<SparseMultiSet*>(this)->findIndex(KeyIndexOf(Key));
|
||||
return const_iterator(I.SMS, I.Idx, KeyIndexOf(Key));
|
||||
}
|
||||
|
||||
/// Returns the number of elements identified by Key. This will be linear in
|
||||
/// the number of elements of that key.
|
||||
unsigned count(const KeyT &Key) const {
|
||||
unsigned Ret = 0;
|
||||
for (const_iterator It = find(Key); It != end(); ++It)
|
||||
++Ret;
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// Returns true if this set contains an element identified by Key.
|
||||
bool contains(const KeyT &Key) const {
|
||||
return find(Key) != end();
|
||||
}
|
||||
|
||||
/// Return the head and tail of the subset's list, otherwise returns end().
|
||||
iterator getHead(const KeyT &Key) { return find(Key); }
|
||||
iterator getTail(const KeyT &Key) {
|
||||
iterator I = find(Key);
|
||||
if (I != end())
|
||||
I = iterator(this, I.Prev(), KeyIndexOf(Key));
|
||||
return I;
|
||||
}
|
||||
|
||||
/// The bounds of the range of items sharing Key K. First member is the head
|
||||
/// of the list, and the second member is a decrementable end iterator for
|
||||
/// that key.
|
||||
RangePair equal_range(const KeyT &K) {
|
||||
iterator B = find(K);
|
||||
iterator E = iterator(this, SMSNode::INVALID, B.SparseIdx);
|
||||
return make_pair(B, E);
|
||||
}
|
||||
|
||||
/// Insert a new element at the tail of the subset list. Returns an iterator
|
||||
/// to the newly added entry.
|
||||
iterator insert(const ValueT &Val) {
|
||||
unsigned Idx = sparseIndex(Val);
|
||||
iterator I = findIndex(Idx);
|
||||
|
||||
unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
|
||||
|
||||
if (I == end()) {
|
||||
// Make a singleton list
|
||||
Sparse[Idx] = NodeIdx;
|
||||
Dense[NodeIdx].Prev = NodeIdx;
|
||||
return iterator(this, NodeIdx, Idx);
|
||||
}
|
||||
|
||||
// Stick it at the end.
|
||||
unsigned HeadIdx = I.Idx;
|
||||
unsigned TailIdx = I.Prev();
|
||||
Dense[TailIdx].Next = NodeIdx;
|
||||
Dense[HeadIdx].Prev = NodeIdx;
|
||||
Dense[NodeIdx].Prev = TailIdx;
|
||||
|
||||
return iterator(this, NodeIdx, Idx);
|
||||
}
|
||||
|
||||
/// Erases an existing element identified by a valid iterator.
|
||||
///
|
||||
/// This invalidates iterators pointing at the same entry, but erase() returns
|
||||
/// an iterator pointing to the next element in the subset's list. This makes
|
||||
/// it possible to erase selected elements while iterating over the subset:
|
||||
///
|
||||
/// tie(I, E) = Set.equal_range(Key);
|
||||
/// while (I != E)
|
||||
/// if (test(*I))
|
||||
/// I = Set.erase(I);
|
||||
/// else
|
||||
/// ++I;
|
||||
///
|
||||
/// Note that if the last element in the subset list is erased, this will
|
||||
/// return an end iterator which can be decremented to get the new tail (if it
|
||||
/// exists):
|
||||
///
|
||||
/// tie(B, I) = Set.equal_range(Key);
|
||||
/// for (bool isBegin = B == I; !isBegin; /* empty */) {
|
||||
/// isBegin = (--I) == B;
|
||||
/// if (test(I))
|
||||
/// break;
|
||||
/// I = erase(I);
|
||||
/// }
|
||||
iterator erase(iterator I) {
|
||||
assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() &&
|
||||
"erasing invalid/end/tombstone iterator");
|
||||
|
||||
// First, unlink the node from its list. Then swap the node out with the
|
||||
// dense vector's last entry
|
||||
iterator NextI = unlink(Dense[I.Idx]);
|
||||
|
||||
// Put in a tombstone.
|
||||
makeTombstone(I.Idx);
|
||||
|
||||
return NextI;
|
||||
}
|
||||
|
||||
/// Erase all elements with the given key. This invalidates all
|
||||
/// iterators of that key.
|
||||
void eraseAll(const KeyT &K) {
|
||||
for (iterator I = find(K); I != end(); /* empty */)
|
||||
I = erase(I);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Unlink the node from its list. Returns the next node in the list.
|
||||
iterator unlink(const SMSNode &N) {
|
||||
if (isSingleton(N)) {
|
||||
// Singleton is already unlinked
|
||||
assert(N.Next == SMSNode::INVALID && "Singleton has next?");
|
||||
return iterator(this, SMSNode::INVALID, ValIndexOf(N.Data));
|
||||
}
|
||||
|
||||
if (isHead(N)) {
|
||||
// If we're the head, then update the sparse array and our next.
|
||||
Sparse[sparseIndex(N)] = N.Next;
|
||||
Dense[N.Next].Prev = N.Prev;
|
||||
return iterator(this, N.Next, ValIndexOf(N.Data));
|
||||
}
|
||||
|
||||
if (N.isTail()) {
|
||||
// If we're the tail, then update our head and our previous.
|
||||
findIndex(sparseIndex(N)).setPrev(N.Prev);
|
||||
Dense[N.Prev].Next = N.Next;
|
||||
|
||||
// Give back an end iterator that can be decremented
|
||||
iterator I(this, N.Prev, ValIndexOf(N.Data));
|
||||
return ++I;
|
||||
}
|
||||
|
||||
// Otherwise, just drop us
|
||||
Dense[N.Next].Prev = N.Prev;
|
||||
Dense[N.Prev].Next = N.Next;
|
||||
return iterator(this, N.Next, ValIndexOf(N.Data));
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
308
thirdparty/clang/include/llvm/ADT/SparseSet.h
vendored
Normal file
308
thirdparty/clang/include/llvm/ADT/SparseSet.h
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
//===--- llvm/ADT/SparseSet.h - Sparse 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 SparseSet class derived from the version described in
|
||||
// Briggs, Torczon, "An efficient representation for sparse sets", ACM Letters
|
||||
// on Programming Languages and Systems, Volume 2 Issue 1-4, March-Dec. 1993.
|
||||
//
|
||||
// A sparse set holds a small number of objects identified by integer keys from
|
||||
// a moderately sized universe. The sparse set uses more memory than other
|
||||
// containers in order to provide faster operations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_SPARSESET_H
|
||||
#define LLVM_ADT_SPARSESET_H
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <limits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SparseSetValTraits - Objects in a SparseSet are identified by keys that can
|
||||
/// be uniquely converted to a small integer less than the set's universe. This
|
||||
/// class allows the set to hold values that differ from the set's key type as
|
||||
/// long as an index can still be derived from the value. SparseSet never
|
||||
/// directly compares ValueT, only their indices, so it can map keys to
|
||||
/// arbitrary values. SparseSetValTraits computes the index from the value
|
||||
/// object. To compute the index from a key, SparseSet uses a separate
|
||||
/// KeyFunctorT template argument.
|
||||
///
|
||||
/// A simple type declaration, SparseSet<Type>, handles these cases:
|
||||
/// - unsigned key, identity index, identity value
|
||||
/// - unsigned key, identity index, fat value providing getSparseSetIndex()
|
||||
///
|
||||
/// The type declaration SparseSet<Type, UnaryFunction> handles:
|
||||
/// - unsigned key, remapped index, identity value (virtual registers)
|
||||
/// - pointer key, pointer-derived index, identity value (node+ID)
|
||||
/// - pointer key, pointer-derived index, fat value with getSparseSetIndex()
|
||||
///
|
||||
/// Only other, unexpected cases require specializing SparseSetValTraits.
|
||||
///
|
||||
/// For best results, ValueT should not require a destructor.
|
||||
///
|
||||
template<typename ValueT>
|
||||
struct SparseSetValTraits {
|
||||
static unsigned getValIndex(const ValueT &Val) {
|
||||
return Val.getSparseSetIndex();
|
||||
}
|
||||
};
|
||||
|
||||
/// SparseSetValFunctor - Helper class for selecting SparseSetValTraits. The
|
||||
/// generic implementation handles ValueT classes which either provide
|
||||
/// getSparseSetIndex() or specialize SparseSetValTraits<>.
|
||||
///
|
||||
template<typename KeyT, typename ValueT, typename KeyFunctorT>
|
||||
struct SparseSetValFunctor {
|
||||
unsigned operator()(const ValueT &Val) const {
|
||||
return SparseSetValTraits<ValueT>::getValIndex(Val);
|
||||
}
|
||||
};
|
||||
|
||||
/// SparseSetValFunctor<KeyT, KeyT> - Helper class for the common case of
|
||||
/// identity key/value sets.
|
||||
template<typename KeyT, typename KeyFunctorT>
|
||||
struct SparseSetValFunctor<KeyT, KeyT, KeyFunctorT> {
|
||||
unsigned operator()(const KeyT &Key) const {
|
||||
return KeyFunctorT()(Key);
|
||||
}
|
||||
};
|
||||
|
||||
/// SparseSet - Fast set implmentation for objects that can be identified by
|
||||
/// small unsigned keys.
|
||||
///
|
||||
/// SparseSet allocates memory proportional to the size of the key universe, so
|
||||
/// it is not recommended for building composite data structures. It is useful
|
||||
/// for algorithms that require a single set with fast operations.
|
||||
///
|
||||
/// Compared to DenseSet and DenseMap, SparseSet provides constant-time fast
|
||||
/// clear() and iteration as fast as a vector. The find(), insert(), and
|
||||
/// erase() operations are all constant time, and typically faster than a hash
|
||||
/// table. The iteration order doesn't depend on numerical key values, it only
|
||||
/// depends on the order of insert() and erase() operations. When no elements
|
||||
/// have been erased, the iteration order is the insertion order.
|
||||
///
|
||||
/// Compared to BitVector, SparseSet<unsigned> uses 8x-40x more memory, but
|
||||
/// offers constant-time clear() and size() operations as well as fast
|
||||
/// iteration independent on the size of the universe.
|
||||
///
|
||||
/// SparseSet contains a dense vector holding all the objects and a sparse
|
||||
/// array holding indexes into the dense vector. Most of the memory is used by
|
||||
/// the sparse array which is the size of the key universe. The SparseT
|
||||
/// template parameter provides a space/speed tradeoff for sets holding many
|
||||
/// elements.
|
||||
///
|
||||
/// When SparseT is uint32_t, find() only touches 2 cache lines, but the sparse
|
||||
/// array uses 4 x Universe bytes.
|
||||
///
|
||||
/// When SparseT is uint8_t (the default), find() touches up to 2+[N/256] cache
|
||||
/// lines, but the sparse array is 4x smaller. N is the number of elements in
|
||||
/// the set.
|
||||
///
|
||||
/// For sets that may grow to thousands of elements, SparseT should be set to
|
||||
/// uint16_t or uint32_t.
|
||||
///
|
||||
/// @tparam ValueT The type of objects in the set.
|
||||
/// @tparam KeyFunctorT A functor that computes an unsigned index from KeyT.
|
||||
/// @tparam SparseT An unsigned integer type. See above.
|
||||
///
|
||||
template<typename ValueT,
|
||||
typename KeyFunctorT = llvm::identity<unsigned>,
|
||||
typename SparseT = uint8_t>
|
||||
class SparseSet {
|
||||
typedef typename KeyFunctorT::argument_type KeyT;
|
||||
typedef SmallVector<ValueT, 8> DenseT;
|
||||
DenseT Dense;
|
||||
SparseT *Sparse;
|
||||
unsigned Universe;
|
||||
KeyFunctorT KeyIndexOf;
|
||||
SparseSetValFunctor<KeyT, ValueT, KeyFunctorT> ValIndexOf;
|
||||
|
||||
// Disable copy construction and assignment.
|
||||
// This data structure is not meant to be used that way.
|
||||
SparseSet(const SparseSet&) LLVM_DELETED_FUNCTION;
|
||||
SparseSet &operator=(const SparseSet&) LLVM_DELETED_FUNCTION;
|
||||
|
||||
public:
|
||||
typedef ValueT value_type;
|
||||
typedef ValueT &reference;
|
||||
typedef const ValueT &const_reference;
|
||||
typedef ValueT *pointer;
|
||||
typedef const ValueT *const_pointer;
|
||||
|
||||
SparseSet() : Sparse(0), Universe(0) {}
|
||||
~SparseSet() { free(Sparse); }
|
||||
|
||||
/// setUniverse - Set the universe size which determines the largest key the
|
||||
/// set can hold. The universe must be sized before any elements can be
|
||||
/// added.
|
||||
///
|
||||
/// @param U Universe size. All object keys must be less than U.
|
||||
///
|
||||
void setUniverse(unsigned U) {
|
||||
// It's not hard to resize the universe on a non-empty set, but it doesn't
|
||||
// seem like a likely use case, so we can add that code when we need it.
|
||||
assert(empty() && "Can only resize universe on an empty map");
|
||||
// Hysteresis prevents needless reallocations.
|
||||
if (U >= Universe/4 && U <= Universe)
|
||||
return;
|
||||
free(Sparse);
|
||||
// The Sparse array doesn't actually need to be initialized, so malloc
|
||||
// would be enough here, but that will cause tools like valgrind to
|
||||
// complain about branching on uninitialized data.
|
||||
Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT)));
|
||||
Universe = U;
|
||||
}
|
||||
|
||||
// Import trivial vector stuff from DenseT.
|
||||
typedef typename DenseT::iterator iterator;
|
||||
typedef typename DenseT::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return Dense.begin(); }
|
||||
const_iterator end() const { return Dense.end(); }
|
||||
iterator begin() { return Dense.begin(); }
|
||||
iterator end() { return Dense.end(); }
|
||||
|
||||
/// empty - Returns true if the set is empty.
|
||||
///
|
||||
/// This is not the same as BitVector::empty().
|
||||
///
|
||||
bool empty() const { return Dense.empty(); }
|
||||
|
||||
/// size - Returns the number of elements in the set.
|
||||
///
|
||||
/// This is not the same as BitVector::size() which returns the size of the
|
||||
/// universe.
|
||||
///
|
||||
unsigned size() const { return Dense.size(); }
|
||||
|
||||
/// clear - Clears the set. This is a very fast constant time operation.
|
||||
///
|
||||
void clear() {
|
||||
// Sparse does not need to be cleared, see find().
|
||||
Dense.clear();
|
||||
}
|
||||
|
||||
/// findIndex - Find an element by its index.
|
||||
///
|
||||
/// @param Idx A valid index to find.
|
||||
/// @returns An iterator to the element identified by key, or end().
|
||||
///
|
||||
iterator findIndex(unsigned Idx) {
|
||||
assert(Idx < Universe && "Key out of range");
|
||||
assert(std::numeric_limits<SparseT>::is_integer &&
|
||||
!std::numeric_limits<SparseT>::is_signed &&
|
||||
"SparseT must be an unsigned integer type");
|
||||
const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
|
||||
for (unsigned i = Sparse[Idx], e = size(); i < e; i += Stride) {
|
||||
const unsigned FoundIdx = ValIndexOf(Dense[i]);
|
||||
assert(FoundIdx < Universe && "Invalid key in set. Did object mutate?");
|
||||
if (Idx == FoundIdx)
|
||||
return begin() + i;
|
||||
// Stride is 0 when SparseT >= unsigned. We don't need to loop.
|
||||
if (!Stride)
|
||||
break;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
/// find - Find an element by its key.
|
||||
///
|
||||
/// @param Key A valid key to find.
|
||||
/// @returns An iterator to the element identified by key, or end().
|
||||
///
|
||||
iterator find(const KeyT &Key) {
|
||||
return findIndex(KeyIndexOf(Key));
|
||||
}
|
||||
|
||||
const_iterator find(const KeyT &Key) const {
|
||||
return const_cast<SparseSet*>(this)->findIndex(KeyIndexOf(Key));
|
||||
}
|
||||
|
||||
/// count - Returns true if this set contains an element identified by Key.
|
||||
///
|
||||
bool count(const KeyT &Key) const {
|
||||
return find(Key) != end();
|
||||
}
|
||||
|
||||
/// insert - Attempts to insert a new element.
|
||||
///
|
||||
/// If Val is successfully inserted, return (I, true), where I is an iterator
|
||||
/// pointing to the newly inserted element.
|
||||
///
|
||||
/// If the set already contains an element with the same key as Val, return
|
||||
/// (I, false), where I is an iterator pointing to the existing element.
|
||||
///
|
||||
/// Insertion invalidates all iterators.
|
||||
///
|
||||
std::pair<iterator, bool> insert(const ValueT &Val) {
|
||||
unsigned Idx = ValIndexOf(Val);
|
||||
iterator I = findIndex(Idx);
|
||||
if (I != end())
|
||||
return std::make_pair(I, false);
|
||||
Sparse[Idx] = size();
|
||||
Dense.push_back(Val);
|
||||
return std::make_pair(end() - 1, true);
|
||||
}
|
||||
|
||||
/// array subscript - If an element already exists with this key, return it.
|
||||
/// Otherwise, automatically construct a new value from Key, insert it,
|
||||
/// and return the newly inserted element.
|
||||
ValueT &operator[](const KeyT &Key) {
|
||||
return *insert(ValueT(Key)).first;
|
||||
}
|
||||
|
||||
/// erase - Erases an existing element identified by a valid iterator.
|
||||
///
|
||||
/// This invalidates all iterators, but erase() returns an iterator pointing
|
||||
/// to the next element. This makes it possible to erase selected elements
|
||||
/// while iterating over the set:
|
||||
///
|
||||
/// for (SparseSet::iterator I = Set.begin(); I != Set.end();)
|
||||
/// if (test(*I))
|
||||
/// I = Set.erase(I);
|
||||
/// else
|
||||
/// ++I;
|
||||
///
|
||||
/// Note that end() changes when elements are erased, unlike std::list.
|
||||
///
|
||||
iterator erase(iterator I) {
|
||||
assert(unsigned(I - begin()) < size() && "Invalid iterator");
|
||||
if (I != end() - 1) {
|
||||
*I = Dense.back();
|
||||
unsigned BackIdx = ValIndexOf(Dense.back());
|
||||
assert(BackIdx < Universe && "Invalid key in set. Did object mutate?");
|
||||
Sparse[BackIdx] = I - begin();
|
||||
}
|
||||
// This depends on SmallVector::pop_back() not invalidating iterators.
|
||||
// std::vector::pop_back() doesn't give that guarantee.
|
||||
Dense.pop_back();
|
||||
return I;
|
||||
}
|
||||
|
||||
/// erase - Erases an element identified by Key, if it exists.
|
||||
///
|
||||
/// @param Key The key identifying the element to erase.
|
||||
/// @returns True when an element was erased, false if no element was found.
|
||||
///
|
||||
bool erase(const KeyT &Key) {
|
||||
iterator I = find(Key);
|
||||
if (I == end())
|
||||
return false;
|
||||
erase(I);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
181
thirdparty/clang/include/llvm/ADT/Statistic.h
vendored
Normal file
181
thirdparty/clang/include/llvm/ADT/Statistic.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
//===-- 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
|
||||
|
||||
#include "llvm/Support/Atomic.h"
|
||||
#include "llvm/Support/Valgrind.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
|
||||
class Statistic {
|
||||
public:
|
||||
const char *Name;
|
||||
const char *Desc;
|
||||
volatile llvm::sys::cas_flag Value;
|
||||
bool Initialized;
|
||||
|
||||
llvm::sys::cas_flag 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; }
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
|
||||
const Statistic &operator=(unsigned Val) {
|
||||
Value = Val;
|
||||
return init();
|
||||
}
|
||||
|
||||
const Statistic &operator++() {
|
||||
// FIXME: This function and all those that follow carefully use an
|
||||
// atomic operation to update the value safely in the presence of
|
||||
// concurrent accesses, but not to read the return value, so the
|
||||
// return value is not thread safe.
|
||||
sys::AtomicIncrement(&Value);
|
||||
return init();
|
||||
}
|
||||
|
||||
unsigned operator++(int) {
|
||||
init();
|
||||
unsigned OldValue = Value;
|
||||
sys::AtomicIncrement(&Value);
|
||||
return OldValue;
|
||||
}
|
||||
|
||||
const Statistic &operator--() {
|
||||
sys::AtomicDecrement(&Value);
|
||||
return init();
|
||||
}
|
||||
|
||||
unsigned operator--(int) {
|
||||
init();
|
||||
unsigned OldValue = Value;
|
||||
sys::AtomicDecrement(&Value);
|
||||
return OldValue;
|
||||
}
|
||||
|
||||
const Statistic &operator+=(const unsigned &V) {
|
||||
if (!V) return *this;
|
||||
sys::AtomicAdd(&Value, V);
|
||||
return init();
|
||||
}
|
||||
|
||||
const Statistic &operator-=(const unsigned &V) {
|
||||
if (!V) return *this;
|
||||
sys::AtomicAdd(&Value, -V);
|
||||
return init();
|
||||
}
|
||||
|
||||
const Statistic &operator*=(const unsigned &V) {
|
||||
sys::AtomicMul(&Value, V);
|
||||
return init();
|
||||
}
|
||||
|
||||
const Statistic &operator/=(const unsigned &V) {
|
||||
sys::AtomicDiv(&Value, V);
|
||||
return init();
|
||||
}
|
||||
|
||||
#else // Statistics are disabled in release builds.
|
||||
|
||||
const Statistic &operator=(unsigned Val) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Statistic &operator++() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned operator++(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Statistic &operator--() {
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned operator--(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Statistic &operator+=(const unsigned &V) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Statistic &operator-=(const unsigned &V) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Statistic &operator*=(const unsigned &V) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Statistic &operator/=(const unsigned &V) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
|
||||
|
||||
protected:
|
||||
Statistic &init() {
|
||||
bool tmp = Initialized;
|
||||
sys::MemoryFence();
|
||||
if (!tmp) RegisterStatistic();
|
||||
TsanHappensAfter(this);
|
||||
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 }
|
||||
|
||||
/// \brief Enable the collection and printing of statistics.
|
||||
void EnableStatistics();
|
||||
|
||||
/// \brief Check if statistics are enabled.
|
||||
bool AreStatisticsEnabled();
|
||||
|
||||
/// \brief Print statistics to the file returned by CreateInfoOutputFile().
|
||||
void PrintStatistics();
|
||||
|
||||
/// \brief Print statistics to the given output stream.
|
||||
void PrintStatistics(raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
164
thirdparty/clang/include/llvm/ADT/StringExtras.h
vendored
Normal file
164
thirdparty/clang/include/llvm/ADT/StringExtras.h
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
//===-- 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/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
||||
/// hexdigit - Return the hexadecimal character for the
|
||||
/// given number \p X (which should be less than 16).
|
||||
static inline char hexdigit(unsigned X, bool LowerCase = false) {
|
||||
const char HexChar = LowerCase ? 'a' : 'A';
|
||||
return X < 10 ? '0' + X : HexChar + X - 10;
|
||||
}
|
||||
|
||||
/// Interpret the given character \p C as a hexadecimal digit and return its
|
||||
/// value.
|
||||
///
|
||||
/// If \p C is not a valid hex digit, -1U is returned.
|
||||
static inline unsigned hexDigitValue(char C) {
|
||||
if (C >= '0' && C <= '9') return C-'0';
|
||||
if (C >= 'a' && C <= 'f') return C-'a'+10U;
|
||||
if (C >= 'A' && C <= 'F') return C-'A'+10U;
|
||||
return -1U;
|
||||
}
|
||||
|
||||
/// utohex_buffer - Emit the specified number into the buffer specified by
|
||||
/// BufferEnd, returning a pointer to the start of the string. This can be used
|
||||
/// like this: (note that the buffer must be large enough to handle any number):
|
||||
/// 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[17];
|
||||
return utohex_buffer(X, Buffer+17);
|
||||
}
|
||||
|
||||
static inline std::string utostr_32(uint32_t X, bool isNeg = false) {
|
||||
char Buffer[11];
|
||||
char *BufPtr = Buffer+11;
|
||||
|
||||
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, Buffer+11);
|
||||
}
|
||||
|
||||
static __declspec(noinline) inline std::string utostr(uint64_t X, bool isNeg = false) {
|
||||
char Buffer[21];
|
||||
char *BufPtr = Buffer+21;
|
||||
|
||||
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, Buffer+21);
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/// StrInStrNoCase - Portable version of strcasestr. Locates the first
|
||||
/// occurrence of string 's1' in string 's2', ignoring case. Returns
|
||||
/// the offset of s2 in s1 or npos if s2 cannot be found.
|
||||
StringRef::size_type StrInStrNoCase(StringRef s1, StringRef s2);
|
||||
|
||||
/// 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 function returns a pair containing the extracted token and the
|
||||
/// remaining tail string.
|
||||
std::pair<StringRef, StringRef> getToken(StringRef Source,
|
||||
StringRef 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(StringRef Source,
|
||||
SmallVectorImpl<StringRef> &OutFragments,
|
||||
StringRef Delimiters = " \t\n\v\f\r");
|
||||
|
||||
/// HashString - Hash function for strings.
|
||||
///
|
||||
/// This is the Bernstein hash function.
|
||||
//
|
||||
// FIXME: Investigate whether a modified bernstein hash function performs
|
||||
// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||
// X*33+c -> X*33^c
|
||||
static inline unsigned HashString(StringRef Str, unsigned Result = 0) {
|
||||
for (unsigned i = 0, e = Str.size(); i != e; ++i)
|
||||
Result = Result * 33 + (unsigned char)Str[i];
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th).
|
||||
static inline StringRef getOrdinalSuffix(unsigned Val) {
|
||||
// It is critically important that we do this perfectly for
|
||||
// user-written sequences with over 100 elements.
|
||||
switch (Val % 100) {
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
return "th";
|
||||
default:
|
||||
switch (Val % 10) {
|
||||
case 1: return "st";
|
||||
case 2: return "nd";
|
||||
case 3: return "rd";
|
||||
default: return "th";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
465
thirdparty/clang/include/llvm/ADT/StringMap.h
vendored
Normal file
465
thirdparty/clang/include/llvm/ADT/StringMap.h
vendored
Normal file
@@ -0,0 +1,465 @@
|
||||
//===--- 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/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <cstring>
|
||||
|
||||
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 {
|
||||
protected:
|
||||
// Array of NumBuckets pointers to entries, null pointers are holes.
|
||||
// TheTable[NumBuckets] contains a sentinel value for easy iteration. Followed
|
||||
// by an array of the actual hash values as unsigned integers.
|
||||
StringMapEntryBase **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();
|
||||
|
||||
/// 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(StringRef Key);
|
||||
|
||||
/// 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(StringRef Key) 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(StringRef Key);
|
||||
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) {}
|
||||
|
||||
StringRef getKey() const {
|
||||
return StringRef(getKeyData(), getKeyLength());
|
||||
}
|
||||
|
||||
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);}
|
||||
|
||||
StringRef first() const { return StringRef(getKeyData(), getKeyLength()); }
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
/// GetStringMapEntryFromKeyData - Given key data that is known to be embedded
|
||||
/// into a StringMapEntry, return the StringMapEntry itself.
|
||||
static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) {
|
||||
char *Ptr = const_cast<char*>(KeyData) - sizeof(StringMapEntry<ValueTy>);
|
||||
return *reinterpret_cast<StringMapEntry*>(Ptr);
|
||||
}
|
||||
|
||||
/// Destroy - Destroy this StringMapEntry, releasing memory back to the
|
||||
/// specified allocator.
|
||||
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;
|
||||
public:
|
||||
typedef StringMapEntry<ValueTy> MapEntryTy;
|
||||
|
||||
StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
|
||||
explicit StringMap(unsigned InitialSize)
|
||||
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
|
||||
|
||||
explicit StringMap(AllocatorTy A)
|
||||
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {}
|
||||
|
||||
StringMap(unsigned InitialSize, AllocatorTy A)
|
||||
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))),
|
||||
Allocator(A) {}
|
||||
|
||||
StringMap(const StringMap &RHS)
|
||||
: StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {
|
||||
assert(RHS.empty() &&
|
||||
"Copy ctor from non-empty stringmap not implemented yet!");
|
||||
(void)RHS;
|
||||
}
|
||||
void operator=(const StringMap &RHS) {
|
||||
assert(RHS.empty() &&
|
||||
"assignment from non-empty stringmap not implemented yet!");
|
||||
(void)RHS;
|
||||
clear();
|
||||
}
|
||||
|
||||
typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy;
|
||||
typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy;
|
||||
AllocatorRefTy getAllocator() { return Allocator; }
|
||||
AllocatorCRefTy getAllocator() const { return Allocator; }
|
||||
|
||||
typedef const char* key_type;
|
||||
typedef ValueTy mapped_type;
|
||||
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(StringRef Key) {
|
||||
int Bucket = FindKey(Key);
|
||||
if (Bucket == -1) return end();
|
||||
return iterator(TheTable+Bucket, true);
|
||||
}
|
||||
|
||||
const_iterator find(StringRef Key) const {
|
||||
int Bucket = FindKey(Key);
|
||||
if (Bucket == -1) return end();
|
||||
return const_iterator(TheTable+Bucket, true);
|
||||
}
|
||||
|
||||
/// lookup - Return the entry for the specified key, or a default
|
||||
/// constructed value if no such entry exists.
|
||||
ValueTy lookup(StringRef Key) const {
|
||||
const_iterator it = find(Key);
|
||||
if (it != end())
|
||||
return it->second;
|
||||
return ValueTy();
|
||||
}
|
||||
|
||||
ValueTy &operator[](StringRef Key) {
|
||||
return GetOrCreateValue(Key).getValue();
|
||||
}
|
||||
|
||||
size_type count(StringRef Key) const {
|
||||
return find(Key) == end() ? 0 : 1;
|
||||
}
|
||||
|
||||
/// 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->getKey());
|
||||
StringMapEntryBase *&Bucket = TheTable[BucketNo];
|
||||
if (Bucket && Bucket != getTombstoneVal())
|
||||
return false; // Already exists in map.
|
||||
|
||||
if (Bucket == getTombstoneVal())
|
||||
--NumTombstones;
|
||||
Bucket = KeyValue;
|
||||
++NumItems;
|
||||
assert(NumItems + NumTombstones <= NumBuckets);
|
||||
|
||||
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 (unsigned I = 0, E = NumBuckets; I != E; ++I) {
|
||||
StringMapEntryBase *&Bucket = TheTable[I];
|
||||
if (Bucket && Bucket != getTombstoneVal()) {
|
||||
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
|
||||
}
|
||||
Bucket = 0;
|
||||
}
|
||||
|
||||
NumItems = 0;
|
||||
NumTombstones = 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>
|
||||
MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
|
||||
unsigned BucketNo = LookupBucketFor(Key);
|
||||
StringMapEntryBase *&Bucket = TheTable[BucketNo];
|
||||
if (Bucket && Bucket != getTombstoneVal())
|
||||
return *static_cast<MapEntryTy*>(Bucket);
|
||||
|
||||
MapEntryTy *NewItem =
|
||||
MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val);
|
||||
|
||||
if (Bucket == getTombstoneVal())
|
||||
--NumTombstones;
|
||||
++NumItems;
|
||||
assert(NumItems + NumTombstones <= NumBuckets);
|
||||
|
||||
// Fill in the bucket for the hash table. The FullHashValue was already
|
||||
// filled in by LookupBucketFor.
|
||||
Bucket = NewItem;
|
||||
|
||||
RehashTable();
|
||||
return *NewItem;
|
||||
}
|
||||
|
||||
MapEntryTy &GetOrCreateValue(StringRef Key) {
|
||||
return GetOrCreateValue(Key, 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(StringRef Key) {
|
||||
iterator I = find(Key);
|
||||
if (I == end()) return false;
|
||||
erase(I);
|
||||
return true;
|
||||
}
|
||||
|
||||
~StringMap() {
|
||||
clear();
|
||||
free(TheTable);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename ValueTy>
|
||||
class StringMapConstIterator {
|
||||
protected:
|
||||
StringMapEntryBase **Ptr;
|
||||
public:
|
||||
typedef StringMapEntry<ValueTy> value_type;
|
||||
|
||||
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
|
||||
bool NoAdvance = false)
|
||||
: Ptr(Bucket) {
|
||||
if (!NoAdvance) AdvancePastEmptyBuckets();
|
||||
}
|
||||
|
||||
const value_type &operator*() const {
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
||||
}
|
||||
const value_type *operator->() const {
|
||||
return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
||||
}
|
||||
|
||||
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 == 0 || *Ptr == StringMapImpl::getTombstoneVal())
|
||||
++Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueTy>
|
||||
class StringMapIterator : public StringMapConstIterator<ValueTy> {
|
||||
public:
|
||||
explicit StringMapIterator(StringMapEntryBase **Bucket,
|
||||
bool NoAdvance = false)
|
||||
: StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
|
||||
}
|
||||
StringMapEntry<ValueTy> &operator*() const {
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
||||
}
|
||||
StringMapEntry<ValueTy> *operator->() const {
|
||||
return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
553
thirdparty/clang/include/llvm/ADT/StringRef.h
vendored
Normal file
553
thirdparty/clang/include/llvm/ADT/StringRef.h
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
//===--- StringRef.h - Constant String Reference Wrapper --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_STRINGREF_H
|
||||
#define LLVM_ADT_STRINGREF_H
|
||||
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
template<typename T>
|
||||
class SmallVectorImpl;
|
||||
class APInt;
|
||||
class hash_code;
|
||||
class StringRef;
|
||||
|
||||
/// Helper functions for StringRef::getAsInteger.
|
||||
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result);
|
||||
|
||||
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
|
||||
|
||||
/// StringRef - Represent a constant reference to a string, i.e. a character
|
||||
/// array and a length, which need not be null terminated.
|
||||
///
|
||||
/// This class does not own the string data, it is expected to be used in
|
||||
/// situations where the character data resides in some other buffer, whose
|
||||
/// lifetime extends past that of the StringRef. For this reason, it is not in
|
||||
/// general safe to store a StringRef.
|
||||
class StringRef {
|
||||
public:
|
||||
typedef const char *iterator;
|
||||
typedef const char *const_iterator;
|
||||
static const size_t npos = ~size_t(0);
|
||||
typedef size_t size_type;
|
||||
|
||||
private:
|
||||
/// The start of the string, in an external buffer.
|
||||
const char *Data;
|
||||
|
||||
/// The length of the string.
|
||||
size_t Length;
|
||||
|
||||
// Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min()
|
||||
// Changing the arg of min to be an integer, instead of a reference to an
|
||||
// integer works around this bug.
|
||||
static size_t min(size_t a, size_t b) { return a < b ? a : b; }
|
||||
static size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||
|
||||
// Workaround memcmp issue with null pointers (undefined behavior)
|
||||
// by providing a specialized version
|
||||
static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
|
||||
if (Length == 0) { return 0; }
|
||||
return ::memcmp(Lhs,Rhs,Length);
|
||||
}
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
/// Construct an empty string ref.
|
||||
/*implicit*/ StringRef() : Data(0), Length(0) {}
|
||||
|
||||
/// Construct a string ref from a cstring.
|
||||
/*implicit*/ StringRef(const char *Str)
|
||||
: Data(Str) {
|
||||
assert(Str && "StringRef cannot be built from a NULL argument");
|
||||
Length = ::strlen(Str); // invoking strlen(NULL) is undefined behavior
|
||||
}
|
||||
|
||||
/// Construct a string ref from a pointer and length.
|
||||
/*implicit*/ StringRef(const char *data, size_t length)
|
||||
: Data(data), Length(length) {
|
||||
assert((data || length == 0) &&
|
||||
"StringRef cannot be built from a NULL argument with non-null length");
|
||||
}
|
||||
|
||||
/// Construct a string ref from an std::string.
|
||||
/*implicit*/ StringRef(const std::string &Str)
|
||||
: Data(Str.data()), Length(Str.length()) {}
|
||||
|
||||
/// @}
|
||||
/// @name Iterators
|
||||
/// @{
|
||||
|
||||
iterator begin() const { return Data; }
|
||||
|
||||
iterator end() const { return Data + Length; }
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
/// data - Get a pointer to the start of the string (which may not be null
|
||||
/// terminated).
|
||||
const char *data() const { return Data; }
|
||||
|
||||
/// empty - Check if the string is empty.
|
||||
bool empty() const { return Length == 0; }
|
||||
|
||||
/// size - Get the string size.
|
||||
size_t size() const { return Length; }
|
||||
|
||||
/// front - Get the first character in the string.
|
||||
char front() const {
|
||||
assert(!empty());
|
||||
return Data[0];
|
||||
}
|
||||
|
||||
/// back - Get the last character in the string.
|
||||
char back() const {
|
||||
assert(!empty());
|
||||
return Data[Length-1];
|
||||
}
|
||||
|
||||
/// equals - Check for string equality, this is more efficient than
|
||||
/// compare() when the relative ordering of inequal strings isn't needed.
|
||||
bool equals(StringRef RHS) const {
|
||||
return (Length == RHS.Length &&
|
||||
compareMemory(Data, RHS.Data, RHS.Length) == 0);
|
||||
}
|
||||
|
||||
/// equals_lower - Check for string equality, ignoring case.
|
||||
bool equals_lower(StringRef RHS) const {
|
||||
return Length == RHS.Length && compare_lower(RHS) == 0;
|
||||
}
|
||||
|
||||
/// compare - Compare two strings; the result is -1, 0, or 1 if this string
|
||||
/// is lexicographically less than, equal to, or greater than the \p RHS.
|
||||
int compare(StringRef RHS) const {
|
||||
// Check the prefix for a mismatch.
|
||||
if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length)))
|
||||
return Res < 0 ? -1 : 1;
|
||||
|
||||
// Otherwise the prefixes match, so we only need to check the lengths.
|
||||
if (Length == RHS.Length)
|
||||
return 0;
|
||||
return Length < RHS.Length ? -1 : 1;
|
||||
}
|
||||
|
||||
/// compare_lower - Compare two strings, ignoring case.
|
||||
int compare_lower(StringRef RHS) const;
|
||||
|
||||
/// compare_numeric - Compare two strings, treating sequences of digits as
|
||||
/// numbers.
|
||||
int compare_numeric(StringRef RHS) const;
|
||||
|
||||
/// \brief Determine the edit distance between this string and another
|
||||
/// string.
|
||||
///
|
||||
/// \param Other the string to compare this string against.
|
||||
///
|
||||
/// \param AllowReplacements whether to allow character
|
||||
/// replacements (change one character into another) as a single
|
||||
/// operation, rather than as two operations (an insertion and a
|
||||
/// removal).
|
||||
///
|
||||
/// \param MaxEditDistance If non-zero, the maximum edit distance that
|
||||
/// this routine is allowed to compute. If the edit distance will exceed
|
||||
/// that maximum, returns \c MaxEditDistance+1.
|
||||
///
|
||||
/// \returns the minimum number of character insertions, removals,
|
||||
/// or (if \p AllowReplacements is \c true) replacements needed to
|
||||
/// transform one of the given strings into the other. If zero,
|
||||
/// the strings are identical.
|
||||
unsigned edit_distance(StringRef Other, bool AllowReplacements = true,
|
||||
unsigned MaxEditDistance = 0);
|
||||
|
||||
/// str - Get the contents as an std::string.
|
||||
std::string str() const {
|
||||
if (Data == 0) return std::string();
|
||||
return std::string(Data, Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
|
||||
char operator[](size_t Index) const {
|
||||
assert(Index < Length && "Invalid index!");
|
||||
return Data[Index];
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Type Conversions
|
||||
/// @{
|
||||
|
||||
operator std::string() const {
|
||||
return str();
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Predicates
|
||||
/// @{
|
||||
|
||||
/// Check if this string starts with the given \p Prefix.
|
||||
bool startswith(StringRef Prefix) const {
|
||||
return Length >= Prefix.Length &&
|
||||
compareMemory(Data, Prefix.Data, Prefix.Length) == 0;
|
||||
}
|
||||
|
||||
/// Check if this string ends with the given \p Suffix.
|
||||
bool endswith(StringRef Suffix) const {
|
||||
return Length >= Suffix.Length &&
|
||||
compareMemory(end() - Suffix.Length, Suffix.Data, Suffix.Length) == 0;
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Searching
|
||||
/// @{
|
||||
|
||||
/// Search for the first character \p C in the string.
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
for (size_t i = min(From, Length), e = Length; i != e; ++i)
|
||||
if (Data[i] == C)
|
||||
return i;
|
||||
return npos;
|
||||
}
|
||||
|
||||
/// Search for the first string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t find(StringRef Str, size_t From = 0) const;
|
||||
|
||||
/// Search for the last character \p C in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t rfind(char C, size_t From = npos) const {
|
||||
From = min(From, Length);
|
||||
size_t i = From;
|
||||
while (i != 0) {
|
||||
--i;
|
||||
if (Data[i] == C)
|
||||
return i;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
/// Search for the last string \p Str in the string.
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t rfind(StringRef Str) const;
|
||||
|
||||
/// Find the first character in the string that is \p C, or npos if not
|
||||
/// found. Same as find.
|
||||
size_type find_first_of(char C, size_t From = 0) const {
|
||||
return find(C, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is in \p Chars, or npos if
|
||||
/// not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_type find_first_of(StringRef Chars, size_t From = 0) const;
|
||||
|
||||
/// Find the first character in the string that is not \p C or npos if not
|
||||
/// found.
|
||||
size_type find_first_not_of(char C, size_t From = 0) const;
|
||||
|
||||
/// Find the first character in the string that is not in the string
|
||||
/// \p Chars, or npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_type find_first_not_of(StringRef Chars, size_t From = 0) const;
|
||||
|
||||
/// Find the last character in the string that is \p C, or npos if not
|
||||
/// found.
|
||||
size_type find_last_of(char C, size_t From = npos) const {
|
||||
return rfind(C, From);
|
||||
}
|
||||
|
||||
/// Find the last character in the string that is in \p C, or npos if not
|
||||
/// found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_type find_last_of(StringRef Chars, size_t From = npos) const;
|
||||
|
||||
/// Find the last character in the string that is not \p C, or npos if not
|
||||
/// found.
|
||||
size_type find_last_not_of(char C, size_t From = npos) const;
|
||||
|
||||
/// Find the last character in the string that is not in \p Chars, or
|
||||
/// npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_type find_last_not_of(StringRef Chars, size_t From = npos) const;
|
||||
|
||||
/// @}
|
||||
/// @name Helpful Algorithms
|
||||
/// @{
|
||||
|
||||
/// Return the number of occurrences of \p C in the string.
|
||||
size_t count(char C) const {
|
||||
size_t Count = 0;
|
||||
for (size_t i = 0, e = Length; i != e; ++i)
|
||||
if (Data[i] == C)
|
||||
++Count;
|
||||
return Count;
|
||||
}
|
||||
|
||||
/// Return the number of non-overlapped occurrences of \p Str in
|
||||
/// the string.
|
||||
size_t count(StringRef Str) const;
|
||||
|
||||
/// Parse the current string as an integer of the specified radix. If
|
||||
/// \p Radix is specified as zero, this does radix autosensing using
|
||||
/// extended C rules: 0 is octal, 0x is hex, 0b is binary.
|
||||
///
|
||||
/// If the string is invalid or if only a subset of the string is valid,
|
||||
/// this returns true to signify the error. The string is considered
|
||||
/// erroneous if empty or if it overflows T.
|
||||
template <typename T>
|
||||
typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
long long LLVal;
|
||||
if (getAsSignedInteger(*this, Radix, LLVal) ||
|
||||
static_cast<T>(LLVal) != LLVal)
|
||||
return true;
|
||||
Result = LLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if_c<!std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
unsigned long long ULLVal;
|
||||
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
|
||||
static_cast<T>(ULLVal) != ULLVal)
|
||||
return true;
|
||||
Result = ULLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse the current string as an integer of the specified \p Radix, or of
|
||||
/// an autosensed radix if the \p Radix given is 0. The current value in
|
||||
/// \p Result is discarded, and the storage is changed to be wide enough to
|
||||
/// store the parsed integer.
|
||||
///
|
||||
/// \returns true if the string does not solely consist of a valid
|
||||
/// non-empty number in the appropriate base.
|
||||
///
|
||||
/// APInt::fromString is superficially similar but assumes the
|
||||
/// string is well-formed in the given radix.
|
||||
bool getAsInteger(unsigned Radix, APInt &Result) const;
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
// Convert the given ASCII string to lowercase.
|
||||
std::string lower() const;
|
||||
|
||||
/// Convert the given ASCII string to uppercase.
|
||||
std::string upper() const;
|
||||
|
||||
/// @}
|
||||
/// @name Substring Operations
|
||||
/// @{
|
||||
|
||||
/// Return a reference to the substring from [Start, Start + N).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param N The number of characters to included in the substring. If N
|
||||
/// exceeds the number of characters remaining in the string, the string
|
||||
/// suffix (starting with \p Start) will be returned.
|
||||
StringRef substr(size_t Start, size_t N = npos) const {
|
||||
Start = min(Start, Length);
|
||||
return StringRef(Data + Start, min(N, Length - Start));
|
||||
}
|
||||
|
||||
/// Return a StringRef equal to 'this' but with the first \p N elements
|
||||
/// dropped.
|
||||
StringRef drop_front(unsigned N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(N);
|
||||
}
|
||||
|
||||
/// Return a StringRef equal to 'this' but with the last \p N elements
|
||||
/// dropped.
|
||||
StringRef drop_back(unsigned N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(0, size()-N);
|
||||
}
|
||||
|
||||
/// Return a reference to the substring from [Start, End).
|
||||
///
|
||||
/// \param Start The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param End The index following the last character to include in the
|
||||
/// substring. If this is npos, or less than \p Start, or exceeds the
|
||||
/// number of characters remaining in the string, the string suffix
|
||||
/// (starting with \p Start) will be returned.
|
||||
StringRef slice(size_t Start, size_t End) const {
|
||||
Start = min(Start, Length);
|
||||
End = min(max(Start, End), Length);
|
||||
return StringRef(Data + Start, End - Start);
|
||||
}
|
||||
|
||||
/// Split into two substrings around the first occurrence of a separator
|
||||
/// character.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// maximal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator The character to split on.
|
||||
/// \returns The split substrings.
|
||||
std::pair<StringRef, StringRef> split(char Separator) const {
|
||||
size_t Idx = find(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
|
||||
}
|
||||
|
||||
/// Split into two substrings around the first occurrence of a separator
|
||||
/// string.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// maximal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator - The string to split on.
|
||||
/// \return - The split substrings.
|
||||
std::pair<StringRef, StringRef> split(StringRef Separator) const {
|
||||
size_t Idx = find(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos));
|
||||
}
|
||||
|
||||
/// Split into substrings around the occurrences of a separator string.
|
||||
///
|
||||
/// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most
|
||||
/// \p MaxSplit splits are done and consequently <= \p MaxSplit
|
||||
/// elements are added to A.
|
||||
/// If \p KeepEmpty is false, empty strings are not added to \p A. They
|
||||
/// still count when considering \p MaxSplit
|
||||
/// An useful invariant is that
|
||||
/// Separator.join(A) == *this if MaxSplit == -1 and KeepEmpty == true
|
||||
///
|
||||
/// \param A - Where to put the substrings.
|
||||
/// \param Separator - The string to split on.
|
||||
/// \param MaxSplit - The maximum number of times the string is split.
|
||||
/// \param KeepEmpty - True if empty substring should be added.
|
||||
void split(SmallVectorImpl<StringRef> &A,
|
||||
StringRef Separator, int MaxSplit = -1,
|
||||
bool KeepEmpty = true) const;
|
||||
|
||||
/// Split into two substrings around the last occurrence of a separator
|
||||
/// character.
|
||||
///
|
||||
/// If \p Separator is in the string, then the result is a pair (LHS, RHS)
|
||||
/// such that (*this == LHS + Separator + RHS) is true and RHS is
|
||||
/// minimal. If \p Separator is not in the string, then the result is a
|
||||
/// pair (LHS, RHS) where (*this == LHS) and (RHS == "").
|
||||
///
|
||||
/// \param Separator - The character to split on.
|
||||
/// \return - The split substrings.
|
||||
std::pair<StringRef, StringRef> rsplit(char Separator) const {
|
||||
size_t Idx = rfind(Separator);
|
||||
if (Idx == npos)
|
||||
return std::make_pair(*this, StringRef());
|
||||
return std::make_pair(slice(0, Idx), slice(Idx+1, npos));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the left removed.
|
||||
StringRef ltrim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return drop_front(std::min(Length, find_first_not_of(Chars)));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the right removed.
|
||||
StringRef rtrim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return drop_back(Length - std::min(Length, find_last_not_of(Chars) + 1));
|
||||
}
|
||||
|
||||
/// Return string with consecutive characters in \p Chars starting from
|
||||
/// the left and right removed.
|
||||
StringRef trim(StringRef Chars = " \t\n\v\f\r") const {
|
||||
return ltrim(Chars).rtrim(Chars);
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// @name StringRef Comparison Operators
|
||||
/// @{
|
||||
|
||||
inline bool operator==(StringRef LHS, StringRef RHS) {
|
||||
return LHS.equals(RHS);
|
||||
}
|
||||
|
||||
inline bool operator!=(StringRef LHS, StringRef RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
inline bool operator<(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) == -1;
|
||||
}
|
||||
|
||||
inline bool operator<=(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) != 1;
|
||||
}
|
||||
|
||||
inline bool operator>(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) == 1;
|
||||
}
|
||||
|
||||
inline bool operator>=(StringRef LHS, StringRef RHS) {
|
||||
return LHS.compare(RHS) != -1;
|
||||
}
|
||||
|
||||
inline std::string &operator+=(std::string &buffer, StringRef string) {
|
||||
return buffer.append(string.data(), string.size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
/// \brief Compute a hash_code for a StringRef.
|
||||
hash_code hash_value(StringRef S);
|
||||
|
||||
// StringRefs can be treated like a POD type.
|
||||
template <typename T> struct isPodLike;
|
||||
template <> struct isPodLike<StringRef> { static const bool value = true; };
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
45
thirdparty/clang/include/llvm/ADT/StringSet.h
vendored
Normal file
45
thirdparty/clang/include/llvm/ADT/StringSet.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
//===--- 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"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// StringSet - A wrapper for StringMap that provides set-like functionality.
|
||||
template <class AllocatorTy = llvm::MallocAllocator>
|
||||
class StringSet : public llvm::StringMap<char, AllocatorTy> {
|
||||
typedef llvm::StringMap<char, AllocatorTy> base;
|
||||
public:
|
||||
|
||||
/// insert - Insert the specified key into the set. If the key already
|
||||
/// exists in the set, return false and ignore the request, otherwise insert
|
||||
/// it and return true.
|
||||
bool insert(StringRef Key) {
|
||||
// Get or create the map entry for the key; if it doesn't exist the value
|
||||
// type will be default constructed which we use to detect insert.
|
||||
//
|
||||
// We use '+' as the sentinel value in the map.
|
||||
assert(!Key.empty());
|
||||
StringMapEntry<char> &Entry = this->GetOrCreateValue(Key);
|
||||
if (Entry.getValue() == '+')
|
||||
return false;
|
||||
Entry.setValue('+');
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // LLVM_ADT_STRINGSET_H
|
||||
126
thirdparty/clang/include/llvm/ADT/StringSwitch.h
vendored
Normal file
126
thirdparty/clang/include/llvm/ADT/StringSwitch.h
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
//===--- StringSwitch.h - Switch-on-literal-string Construct --------------===/
|
||||
//
|
||||
// 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 StringSwitch template, which mimics a switch()
|
||||
// statement whose cases are string literals.
|
||||
//
|
||||
//===----------------------------------------------------------------------===/
|
||||
#ifndef LLVM_ADT_STRINGSWITCH_H
|
||||
#define LLVM_ADT_STRINGSWITCH_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief A switch()-like statement whose cases are string literals.
|
||||
///
|
||||
/// The StringSwitch class is a simple form of a switch() statement that
|
||||
/// determines whether the given string matches one of the given string
|
||||
/// literals. The template type parameter \p T is the type of the value that
|
||||
/// will be returned from the string-switch expression. For example,
|
||||
/// the following code switches on the name of a color in \c argv[i]:
|
||||
///
|
||||
/// \code
|
||||
/// Color color = StringSwitch<Color>(argv[i])
|
||||
/// .Case("red", Red)
|
||||
/// .Case("orange", Orange)
|
||||
/// .Case("yellow", Yellow)
|
||||
/// .Case("green", Green)
|
||||
/// .Case("blue", Blue)
|
||||
/// .Case("indigo", Indigo)
|
||||
/// .Cases("violet", "purple", Violet)
|
||||
/// .Default(UnknownColor);
|
||||
/// \endcode
|
||||
template<typename T, typename R = T>
|
||||
class StringSwitch {
|
||||
/// \brief The string we are matching.
|
||||
StringRef Str;
|
||||
|
||||
/// \brief The pointer to the result of this switch statement, once known,
|
||||
/// null before that.
|
||||
const T *Result;
|
||||
|
||||
public:
|
||||
explicit StringSwitch(StringRef S)
|
||||
: Str(S), Result(0) { }
|
||||
|
||||
template<unsigned N>
|
||||
StringSwitch& Case(const char (&S)[N], const T& Value) {
|
||||
if (!Result && N-1 == Str.size() &&
|
||||
(std::memcmp(S, Str.data(), N-1) == 0)) {
|
||||
Result = &Value;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<unsigned N>
|
||||
StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
|
||||
if (!Result && Str.size() >= N-1 &&
|
||||
std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0) {
|
||||
Result = &Value;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<unsigned N>
|
||||
StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
|
||||
if (!Result && Str.size() >= N-1 &&
|
||||
std::memcmp(S, Str.data(), N-1) == 0) {
|
||||
Result = &Value;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<unsigned N0, unsigned N1>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value);
|
||||
}
|
||||
|
||||
template<unsigned N0, unsigned N1, unsigned N2>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value).Case(S2, Value);
|
||||
}
|
||||
|
||||
template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const char (&S3)[N3],
|
||||
const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value);
|
||||
}
|
||||
|
||||
template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const char (&S3)[N3],
|
||||
const char (&S4)[N4], const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value)
|
||||
.Case(S4, Value);
|
||||
}
|
||||
|
||||
R Default(const T& Value) const {
|
||||
if (Result)
|
||||
return *Result;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
operator R() const {
|
||||
assert(Result && "Fell off the end of a string-switch");
|
||||
return *Result;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ADT_STRINGSWITCH_H
|
||||
291
thirdparty/clang/include/llvm/ADT/TinyPtrVector.h
vendored
Normal file
291
thirdparty/clang/include/llvm/ADT/TinyPtrVector.h
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- 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_TINYPTRVECTOR_H
|
||||
#define LLVM_ADT_TINYPTRVECTOR_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// TinyPtrVector - This class is specialized for cases where there are
|
||||
/// normally 0 or 1 element in a vector, but is general enough to go beyond that
|
||||
/// when required.
|
||||
///
|
||||
/// NOTE: This container doesn't allow you to store a null pointer into it.
|
||||
///
|
||||
template <typename EltTy>
|
||||
class TinyPtrVector {
|
||||
public:
|
||||
typedef llvm::SmallVector<EltTy, 4> VecTy;
|
||||
typedef typename VecTy::value_type value_type;
|
||||
|
||||
llvm::PointerUnion<EltTy, VecTy*> Val;
|
||||
|
||||
TinyPtrVector() {}
|
||||
~TinyPtrVector() {
|
||||
if (VecTy *V = Val.template dyn_cast<VecTy*>())
|
||||
delete V;
|
||||
}
|
||||
|
||||
TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
|
||||
if (VecTy *V = Val.template dyn_cast<VecTy*>())
|
||||
Val = new VecTy(*V);
|
||||
}
|
||||
TinyPtrVector &operator=(const TinyPtrVector &RHS) {
|
||||
if (this == &RHS)
|
||||
return *this;
|
||||
if (RHS.empty()) {
|
||||
this->clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Try to squeeze into the single slot. If it won't fit, allocate a copied
|
||||
// vector.
|
||||
if (Val.template is<EltTy>()) {
|
||||
if (RHS.size() == 1)
|
||||
Val = RHS.front();
|
||||
else
|
||||
Val = new VecTy(*RHS.Val.template get<VecTy*>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we have a full vector allocated, try to re-use it.
|
||||
if (RHS.Val.template is<EltTy>()) {
|
||||
Val.template get<VecTy*>()->clear();
|
||||
Val.template get<VecTy*>()->push_back(RHS.front());
|
||||
} else {
|
||||
*Val.template get<VecTy*>() = *RHS.Val.template get<VecTy*>();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if LLVM_HAS_RVALUE_REFERENCES
|
||||
TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) {
|
||||
RHS.Val = (EltTy)0;
|
||||
}
|
||||
TinyPtrVector &operator=(TinyPtrVector &&RHS) {
|
||||
if (this == &RHS)
|
||||
return *this;
|
||||
if (RHS.empty()) {
|
||||
this->clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If this vector has been allocated on the heap, re-use it if cheap. If it
|
||||
// would require more copying, just delete it and we'll steal the other
|
||||
// side.
|
||||
if (VecTy *V = Val.template dyn_cast<VecTy*>()) {
|
||||
if (RHS.Val.template is<EltTy>()) {
|
||||
V->clear();
|
||||
V->push_back(RHS.front());
|
||||
return *this;
|
||||
}
|
||||
delete V;
|
||||
}
|
||||
|
||||
Val = RHS.Val;
|
||||
RHS.Val = (EltTy)0;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
// implicit conversion operator to ArrayRef.
|
||||
operator ArrayRef<EltTy>() const {
|
||||
if (Val.isNull())
|
||||
return ArrayRef<EltTy>();
|
||||
if (Val.template is<EltTy>())
|
||||
return *Val.getAddrOfPtr1();
|
||||
return *Val.template get<VecTy*>();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
// This vector can be empty if it contains no element, or if it
|
||||
// contains a pointer to an empty vector.
|
||||
if (Val.isNull()) return true;
|
||||
if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
|
||||
return Vec->empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned size() const {
|
||||
if (empty())
|
||||
return 0;
|
||||
if (Val.template is<EltTy>())
|
||||
return 1;
|
||||
return Val.template get<VecTy*>()->size();
|
||||
}
|
||||
|
||||
typedef const EltTy *const_iterator;
|
||||
typedef EltTy *iterator;
|
||||
|
||||
iterator begin() {
|
||||
if (Val.template is<EltTy>())
|
||||
return Val.getAddrOfPtr1();
|
||||
|
||||
return Val.template get<VecTy *>()->begin();
|
||||
|
||||
}
|
||||
iterator end() {
|
||||
if (Val.template is<EltTy>())
|
||||
return begin() + (Val.isNull() ? 0 : 1);
|
||||
|
||||
return Val.template get<VecTy *>()->end();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
|
||||
}
|
||||
|
||||
EltTy operator[](unsigned i) const {
|
||||
assert(!Val.isNull() && "can't index into an empty vector");
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>()) {
|
||||
assert(i == 0 && "tinyvector index out of range");
|
||||
return V;
|
||||
}
|
||||
|
||||
assert(i < Val.template get<VecTy*>()->size() &&
|
||||
"tinyvector index out of range");
|
||||
return (*Val.template get<VecTy*>())[i];
|
||||
}
|
||||
|
||||
EltTy front() const {
|
||||
assert(!empty() && "vector empty");
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>())
|
||||
return V;
|
||||
return Val.template get<VecTy*>()->front();
|
||||
}
|
||||
|
||||
EltTy back() const {
|
||||
assert(!empty() && "vector empty");
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>())
|
||||
return V;
|
||||
return Val.template get<VecTy*>()->back();
|
||||
}
|
||||
|
||||
void push_back(EltTy NewVal) {
|
||||
assert(NewVal != 0 && "Can't add a null value");
|
||||
|
||||
// If we have nothing, add something.
|
||||
if (Val.isNull()) {
|
||||
Val = NewVal;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a single value, convert to a vector.
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>()) {
|
||||
Val = new VecTy();
|
||||
Val.template get<VecTy*>()->push_back(V);
|
||||
}
|
||||
|
||||
// Add the new value, we know we have a vector.
|
||||
Val.template get<VecTy*>()->push_back(NewVal);
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
// If we have a single value, convert to empty.
|
||||
if (Val.template is<EltTy>())
|
||||
Val = (EltTy)0;
|
||||
else if (VecTy *Vec = Val.template get<VecTy*>())
|
||||
Vec->pop_back();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
// If we have a single value, convert to empty.
|
||||
if (Val.template is<EltTy>()) {
|
||||
Val = (EltTy)0;
|
||||
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
|
||||
// If we have a vector form, just clear it.
|
||||
Vec->clear();
|
||||
}
|
||||
// Otherwise, we're already empty.
|
||||
}
|
||||
|
||||
iterator erase(iterator I) {
|
||||
assert(I >= begin() && "Iterator to erase is out of bounds.");
|
||||
assert(I < end() && "Erasing at past-the-end iterator.");
|
||||
|
||||
// If we have a single value, convert to empty.
|
||||
if (Val.template is<EltTy>()) {
|
||||
if (I == begin())
|
||||
Val = (EltTy)0;
|
||||
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
|
||||
// multiple items in a vector; just do the erase, there is no
|
||||
// benefit to collapsing back to a pointer
|
||||
return Vec->erase(I);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator erase(iterator S, iterator E) {
|
||||
assert(S >= begin() && "Range to erase is out of bounds.");
|
||||
assert(S <= E && "Trying to erase invalid range.");
|
||||
assert(E <= end() && "Trying to erase past the end.");
|
||||
|
||||
if (Val.template is<EltTy>()) {
|
||||
if (S == begin() && S != E)
|
||||
Val = (EltTy)0;
|
||||
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
|
||||
return Vec->erase(S, E);
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
iterator insert(iterator I, const EltTy &Elt) {
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
if (I == end()) {
|
||||
push_back(Elt);
|
||||
return llvm::prior(end());
|
||||
}
|
||||
assert(!Val.isNull() && "Null value with non-end insert iterator.");
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>()) {
|
||||
assert(I == begin());
|
||||
Val = Elt;
|
||||
push_back(V);
|
||||
return begin();
|
||||
}
|
||||
|
||||
return Val.template get<VecTy*>()->insert(I, Elt);
|
||||
}
|
||||
|
||||
template<typename ItTy>
|
||||
iterator insert(iterator I, ItTy From, ItTy To) {
|
||||
assert(I >= this->begin() && "Insertion iterator is out of bounds.");
|
||||
assert(I <= this->end() && "Inserting past the end of the vector.");
|
||||
if (From == To)
|
||||
return I;
|
||||
|
||||
// If we have a single value, convert to a vector.
|
||||
ptrdiff_t Offset = I - begin();
|
||||
if (Val.isNull()) {
|
||||
if (llvm::next(From) == To) {
|
||||
Val = *From;
|
||||
return begin();
|
||||
}
|
||||
|
||||
Val = new VecTy();
|
||||
} else if (EltTy V = Val.template dyn_cast<EltTy>()) {
|
||||
Val = new VecTy();
|
||||
Val.template get<VecTy*>()->push_back(V);
|
||||
}
|
||||
return Val.template get<VecTy*>()->insert(begin() + Offset, From, To);
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
447
thirdparty/clang/include/llvm/ADT/Triple.h
vendored
Normal file
447
thirdparty/clang/include/llvm/ADT/Triple.h
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
//===-- 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 "llvm/ADT/Twine.h"
|
||||
|
||||
// Some system headers or GCC predefined macros conflict with identifiers in
|
||||
// this file. Undefine them here.
|
||||
#undef mips
|
||||
#undef sparc
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// Triple - Helper class for working with target triples.
|
||||
///
|
||||
/// Target triples are strings in the canonical form:
|
||||
/// 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.
|
||||
///
|
||||
/// At its core the Triple class is designed to be a wrapper for a triple
|
||||
/// string; the constructor does not change or normalize the triple string.
|
||||
/// Clients that need to handle the non-canonical triples that users often
|
||||
/// specify should use the normalize method.
|
||||
///
|
||||
/// See autoconf/config.guess for a glimpse into what triples look like in
|
||||
/// practice.
|
||||
class Triple {
|
||||
public:
|
||||
enum ArchType {
|
||||
UnknownArch,
|
||||
|
||||
arm, // ARM: arm, armv.*, xscale
|
||||
aarch64, // AArch64: aarch64
|
||||
hexagon, // Hexagon: hexagon
|
||||
mips, // MIPS: mips, mipsallegrex
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel
|
||||
mips64, // MIPS64: mips64
|
||||
mips64el,// MIPS64EL: mips64el
|
||||
msp430, // MSP430: msp430
|
||||
ppc, // PPC: powerpc
|
||||
ppc64, // PPC64: powerpc64, ppu
|
||||
r600, // R600: AMD GPUs HD2XXX - HD6XXX
|
||||
sparc, // Sparc: sparc
|
||||
sparcv9, // Sparcv9: Sparcv9
|
||||
tce, // TCE (http://tce.cs.tut.fi/): tce
|
||||
thumb, // Thumb: thumb, thumbv.*
|
||||
x86, // X86: i[3-9]86
|
||||
x86_64, // X86-64: amd64, x86_64
|
||||
xcore, // XCore: xcore
|
||||
mblaze, // MBlaze: mblaze
|
||||
nvptx, // NVPTX: 32-bit
|
||||
nvptx64, // NVPTX: 64-bit
|
||||
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
|
||||
amdil, // amdil: amd IL
|
||||
spir, // SPIR: standard portable IR for OpenCL 32-bit version
|
||||
spir64 // SPIR: standard portable IR for OpenCL 64-bit version
|
||||
};
|
||||
enum VendorType {
|
||||
UnknownVendor,
|
||||
|
||||
Apple,
|
||||
PC,
|
||||
SCEI,
|
||||
BGP,
|
||||
BGQ,
|
||||
Freescale,
|
||||
IBM
|
||||
};
|
||||
enum OSType {
|
||||
UnknownOS,
|
||||
|
||||
AuroraUX,
|
||||
Cygwin,
|
||||
Darwin,
|
||||
DragonFly,
|
||||
FreeBSD,
|
||||
IOS,
|
||||
KFreeBSD,
|
||||
Linux,
|
||||
Lv2, // PS3
|
||||
MacOSX,
|
||||
MinGW32, // i*86-pc-mingw32, *-w64-mingw32
|
||||
NetBSD,
|
||||
OpenBSD,
|
||||
Solaris,
|
||||
Win32,
|
||||
Haiku,
|
||||
Minix,
|
||||
RTEMS,
|
||||
NaCl, // Native Client
|
||||
CNK, // BG/P Compute-Node Kernel
|
||||
Bitrig,
|
||||
AIX
|
||||
};
|
||||
enum EnvironmentType {
|
||||
UnknownEnvironment,
|
||||
|
||||
GNU,
|
||||
GNUEABI,
|
||||
GNUEABIHF,
|
||||
GNUX32,
|
||||
EABI,
|
||||
MachO,
|
||||
Android,
|
||||
ELF
|
||||
};
|
||||
|
||||
private:
|
||||
std::string Data;
|
||||
|
||||
/// The parsed arch type.
|
||||
ArchType Arch;
|
||||
|
||||
/// The parsed vendor type.
|
||||
VendorType Vendor;
|
||||
|
||||
/// The parsed OS type.
|
||||
OSType OS;
|
||||
|
||||
/// The parsed Environment type.
|
||||
EnvironmentType Environment;
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
/// \brief Default constructor is the same as an empty string and leaves all
|
||||
/// triple fields unknown.
|
||||
Triple() : Data(), Arch(), Vendor(), OS(), Environment() {}
|
||||
|
||||
explicit Triple(const Twine &Str);
|
||||
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
|
||||
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
|
||||
const Twine &EnvironmentStr);
|
||||
|
||||
/// @}
|
||||
/// @name Normalization
|
||||
/// @{
|
||||
|
||||
/// normalize - Turn an arbitrary machine specification into the canonical
|
||||
/// triple form (or something sensible that the Triple class understands if
|
||||
/// nothing better can reasonably be done). In particular, it handles the
|
||||
/// common case in which otherwise valid components are in the wrong order.
|
||||
static std::string normalize(StringRef Str);
|
||||
|
||||
/// @}
|
||||
/// @name Typed Component Access
|
||||
/// @{
|
||||
|
||||
/// getArch - Get the parsed architecture type of this triple.
|
||||
ArchType getArch() const { return Arch; }
|
||||
|
||||
/// getVendor - Get the parsed vendor type of this triple.
|
||||
VendorType getVendor() const { return Vendor; }
|
||||
|
||||
/// getOS - Get the parsed operating system type of this triple.
|
||||
OSType getOS() const { return OS; }
|
||||
|
||||
/// hasEnvironment - Does this triple have the optional environment
|
||||
/// (fourth) component?
|
||||
bool hasEnvironment() const {
|
||||
return getEnvironmentName() != "";
|
||||
}
|
||||
|
||||
/// getEnvironment - Get the parsed environment type of this triple.
|
||||
EnvironmentType getEnvironment() const { return Environment; }
|
||||
|
||||
/// getOSVersion - Parse the version number from the OS name component of the
|
||||
/// triple, if present.
|
||||
///
|
||||
/// For example, "fooos1.2.3" would return (1, 2, 3).
|
||||
///
|
||||
/// If an entry is not defined, it will be returned as 0.
|
||||
void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const;
|
||||
|
||||
/// getOSMajorVersion - Return just the major version number, this is
|
||||
/// specialized because it is a common query.
|
||||
unsigned getOSMajorVersion() const {
|
||||
unsigned Maj, Min, Micro;
|
||||
getOSVersion(Maj, Min, Micro);
|
||||
return Maj;
|
||||
}
|
||||
|
||||
/// getMacOSXVersion - Parse the version number as with getOSVersion and then
|
||||
/// translate generic "darwin" versions to the corresponding OS X versions.
|
||||
/// This may also be called with IOS triples but the OS X version number is
|
||||
/// just set to a constant 10.4.0 in that case. Returns true if successful.
|
||||
bool getMacOSXVersion(unsigned &Major, unsigned &Minor,
|
||||
unsigned &Micro) const;
|
||||
|
||||
/// getiOSVersion - Parse the version number as with getOSVersion. This should
|
||||
/// only be called with IOS triples.
|
||||
void getiOSVersion(unsigned &Major, unsigned &Minor,
|
||||
unsigned &Micro) const;
|
||||
|
||||
/// @}
|
||||
/// @name Direct Component Access
|
||||
/// @{
|
||||
|
||||
const std::string &str() const { return Data; }
|
||||
|
||||
const std::string &getTriple() const { return Data; }
|
||||
|
||||
/// getArchName - Get the architecture (first) component of the
|
||||
/// triple.
|
||||
StringRef getArchName() const;
|
||||
|
||||
/// getVendorName - Get the vendor (second) component of the triple.
|
||||
StringRef getVendorName() const;
|
||||
|
||||
/// getOSName - Get the operating system (third) component of the
|
||||
/// triple.
|
||||
StringRef getOSName() const;
|
||||
|
||||
/// getEnvironmentName - Get the optional environment (fourth)
|
||||
/// component of the triple, or "" if empty.
|
||||
StringRef getEnvironmentName() const;
|
||||
|
||||
/// getOSAndEnvironmentName - Get the operating system and optional
|
||||
/// environment components as a single string (separated by a '-'
|
||||
/// if the environment component is present).
|
||||
StringRef getOSAndEnvironmentName() const;
|
||||
|
||||
/// @}
|
||||
/// @name Convenience Predicates
|
||||
/// @{
|
||||
|
||||
/// \brief Test whether the architecture is 64-bit
|
||||
///
|
||||
/// Note that this tests for 64-bit pointer width, and nothing else. Note
|
||||
/// that we intentionally expose only three predicates, 64-bit, 32-bit, and
|
||||
/// 16-bit. The inner details of pointer width for particular architectures
|
||||
/// is not summed up in the triple, and so only a coarse grained predicate
|
||||
/// system is provided.
|
||||
bool isArch64Bit() const;
|
||||
|
||||
/// \brief Test whether the architecture is 32-bit
|
||||
///
|
||||
/// Note that this tests for 32-bit pointer width, and nothing else.
|
||||
bool isArch32Bit() const;
|
||||
|
||||
/// \brief Test whether the architecture is 16-bit
|
||||
///
|
||||
/// Note that this tests for 16-bit pointer width, and nothing else.
|
||||
bool isArch16Bit() const;
|
||||
|
||||
/// isOSVersionLT - Helper function for doing comparisons against version
|
||||
/// numbers included in the target triple.
|
||||
bool isOSVersionLT(unsigned Major, unsigned Minor = 0,
|
||||
unsigned Micro = 0) const {
|
||||
unsigned LHS[3];
|
||||
getOSVersion(LHS[0], LHS[1], LHS[2]);
|
||||
|
||||
if (LHS[0] != Major)
|
||||
return LHS[0] < Major;
|
||||
if (LHS[1] != Minor)
|
||||
return LHS[1] < Minor;
|
||||
if (LHS[2] != Micro)
|
||||
return LHS[1] < Micro;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isMacOSXVersionLT - Comparison function for checking OS X version
|
||||
/// compatibility, which handles supporting skewed version numbering schemes
|
||||
/// used by the "darwin" triples.
|
||||
unsigned isMacOSXVersionLT(unsigned Major, unsigned Minor = 0,
|
||||
unsigned Micro = 0) const {
|
||||
assert(isMacOSX() && "Not an OS X triple!");
|
||||
|
||||
// If this is OS X, expect a sane version number.
|
||||
if (getOS() == Triple::MacOSX)
|
||||
return isOSVersionLT(Major, Minor, Micro);
|
||||
|
||||
// Otherwise, compare to the "Darwin" number.
|
||||
assert(Major == 10 && "Unexpected major version");
|
||||
return isOSVersionLT(Minor + 4, Micro, 0);
|
||||
}
|
||||
|
||||
/// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both
|
||||
/// "darwin" and "osx" as OS X triples.
|
||||
bool isMacOSX() const {
|
||||
return getOS() == Triple::Darwin || getOS() == Triple::MacOSX;
|
||||
}
|
||||
|
||||
/// Is this an iOS triple.
|
||||
bool isiOS() const {
|
||||
return getOS() == Triple::IOS;
|
||||
}
|
||||
|
||||
/// isOSDarwin - Is this a "Darwin" OS (OS X or iOS).
|
||||
bool isOSDarwin() const {
|
||||
return isMacOSX() || isiOS();
|
||||
}
|
||||
|
||||
/// \brief Tests for either Cygwin or MinGW OS
|
||||
bool isOSCygMing() const {
|
||||
return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32;
|
||||
}
|
||||
|
||||
/// isOSWindows - Is this a "Windows" OS.
|
||||
bool isOSWindows() const {
|
||||
return getOS() == Triple::Win32 || isOSCygMing();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the OS is NaCl (Native Client)
|
||||
bool isOSNaCl() const {
|
||||
return getOS() == Triple::NaCl;
|
||||
}
|
||||
|
||||
/// \brief Tests whether the OS uses the ELF binary format.
|
||||
bool isOSBinFormatELF() const {
|
||||
return !isOSDarwin() && !isOSWindows();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the OS uses the COFF binary format.
|
||||
bool isOSBinFormatCOFF() const {
|
||||
return isOSWindows();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the environment is MachO.
|
||||
// FIXME: Should this be an OSBinFormat predicate?
|
||||
bool isEnvironmentMachO() const {
|
||||
return getEnvironment() == Triple::MachO || isOSDarwin();
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @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);
|
||||
|
||||
/// setEnvironment - Set the environment (fourth) component of the triple
|
||||
/// to a known type.
|
||||
void setEnvironment(EnvironmentType Kind);
|
||||
|
||||
/// setTriple - Set all components to the new triple \p Str.
|
||||
void setTriple(const Twine &Str);
|
||||
|
||||
/// setArchName - Set the architecture (first) component of the
|
||||
/// triple by name.
|
||||
void setArchName(StringRef Str);
|
||||
|
||||
/// setVendorName - Set the vendor (second) component of the triple
|
||||
/// by name.
|
||||
void setVendorName(StringRef Str);
|
||||
|
||||
/// setOSName - Set the operating system (third) component of the
|
||||
/// triple by name.
|
||||
void setOSName(StringRef Str);
|
||||
|
||||
/// setEnvironmentName - Set the optional environment (fourth)
|
||||
/// component of the triple by name.
|
||||
void setEnvironmentName(StringRef Str);
|
||||
|
||||
/// setOSAndEnvironmentName - Set the operating system and optional
|
||||
/// environment components with a single string.
|
||||
void setOSAndEnvironmentName(StringRef Str);
|
||||
|
||||
/// getArchNameForAssembler - Get an architecture name that is understood by
|
||||
/// the target assembler.
|
||||
const char *getArchNameForAssembler();
|
||||
|
||||
/// @}
|
||||
/// @name Helpers to build variants of a particular triple.
|
||||
/// @{
|
||||
|
||||
/// \brief Form a triple with a 32-bit variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a 32-bit architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple get32BitArchVariant() const;
|
||||
|
||||
/// \brief Form a triple with a 64-bit variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a 64-bit architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple get64BitArchVariant() const;
|
||||
|
||||
/// @}
|
||||
/// @name Static helpers for IDs.
|
||||
/// @{
|
||||
|
||||
/// getArchTypeName - Get the canonical name for the \p Kind architecture.
|
||||
static const char *getArchTypeName(ArchType Kind);
|
||||
|
||||
/// getArchTypePrefix - Get the "prefix" canonical name for the \p Kind
|
||||
/// architecture. This is the prefix used by the architecture specific
|
||||
/// builtins, and is suitable for passing to \see
|
||||
/// Intrinsic::getIntrinsicForGCCBuiltin().
|
||||
///
|
||||
/// \return - The architecture prefix, or 0 if none is defined.
|
||||
static const char *getArchTypePrefix(ArchType Kind);
|
||||
|
||||
/// getVendorTypeName - Get the canonical name for the \p Kind vendor.
|
||||
static const char *getVendorTypeName(VendorType Kind);
|
||||
|
||||
/// getOSTypeName - Get the canonical name for the \p Kind operating system.
|
||||
static const char *getOSTypeName(OSType Kind);
|
||||
|
||||
/// getEnvironmentTypeName - Get the canonical name for the \p Kind
|
||||
/// environment.
|
||||
static const char *getEnvironmentTypeName(EnvironmentType Kind);
|
||||
|
||||
/// @}
|
||||
/// @name Static helpers for converting alternate architecture names.
|
||||
/// @{
|
||||
|
||||
/// getArchTypeForLLVMName - The canonical type for the given LLVM
|
||||
/// architecture name (e.g., "x86").
|
||||
static ArchType getArchTypeForLLVMName(StringRef Str);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
||||
#endif
|
||||
524
thirdparty/clang/include/llvm/ADT/Twine.h
vendored
Normal file
524
thirdparty/clang/include/llvm/ADT/Twine.h
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
//===-- Twine.h - Fast Temporary String Concatenation -----------*- 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_TWINE_H
|
||||
#define LLVM_ADT_TWINE_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
template <typename T>
|
||||
class SmallVectorImpl;
|
||||
class StringRef;
|
||||
class raw_ostream;
|
||||
|
||||
/// Twine - A lightweight data structure for efficiently representing the
|
||||
/// concatenation of temporary values as strings.
|
||||
///
|
||||
/// A Twine is a kind of rope, it represents a concatenated string using a
|
||||
/// binary-tree, where the string is the preorder of the nodes. Since the
|
||||
/// Twine can be efficiently rendered into a buffer when its result is used,
|
||||
/// it avoids the cost of generating temporary values for intermediate string
|
||||
/// results -- particularly in cases when the Twine result is never
|
||||
/// required. By explicitly tracking the type of leaf nodes, we can also avoid
|
||||
/// the creation of temporary strings for conversions operations (such as
|
||||
/// appending an integer to a string).
|
||||
///
|
||||
/// A Twine is not intended for use directly and should not be stored, its
|
||||
/// implementation relies on the ability to store pointers to temporary stack
|
||||
/// objects which may be deallocated at the end of a statement. Twines should
|
||||
/// only be used accepted as const references in arguments, when an API wishes
|
||||
/// to accept possibly-concatenated strings.
|
||||
///
|
||||
/// Twines support a special 'null' value, which always concatenates to form
|
||||
/// itself, and renders as an empty string. This can be returned from APIs to
|
||||
/// effectively nullify any concatenations performed on the result.
|
||||
///
|
||||
/// \b Implementation
|
||||
///
|
||||
/// Given the nature of a Twine, it is not possible for the Twine's
|
||||
/// concatenation method to construct interior nodes; the result must be
|
||||
/// represented inside the returned value. For this reason a Twine object
|
||||
/// actually holds two values, the left- and right-hand sides of a
|
||||
/// concatenation. We also have nullary Twine objects, which are effectively
|
||||
/// sentinel values that represent empty strings.
|
||||
///
|
||||
/// Thus, a Twine can effectively have zero, one, or two children. The \see
|
||||
/// isNullary(), \see isUnary(), and \see isBinary() predicates exist for
|
||||
/// testing the number of children.
|
||||
///
|
||||
/// We maintain a number of invariants on Twine objects (FIXME: Why):
|
||||
/// - Nullary twines are always represented with their Kind on the left-hand
|
||||
/// side, and the Empty kind on the right-hand side.
|
||||
/// - Unary twines are always represented with the value on the left-hand
|
||||
/// side, and the Empty kind on the right-hand side.
|
||||
/// - If a Twine has another Twine as a child, that child should always be
|
||||
/// binary (otherwise it could have been folded into the parent).
|
||||
///
|
||||
/// These invariants are check by \see isValid().
|
||||
///
|
||||
/// \b Efficiency Considerations
|
||||
///
|
||||
/// The Twine is designed to yield efficient and small code for common
|
||||
/// situations. For this reason, the concat() method is inlined so that
|
||||
/// concatenations of leaf nodes can be optimized into stores directly into a
|
||||
/// single stack allocated object.
|
||||
///
|
||||
/// In practice, not all compilers can be trusted to optimize concat() fully,
|
||||
/// so we provide two additional methods (and accompanying operator+
|
||||
/// overloads) to guarantee that particularly important cases (cstring plus
|
||||
/// StringRef) codegen as desired.
|
||||
class Twine {
|
||||
/// NodeKind - Represent the type of an argument.
|
||||
enum NodeKind {
|
||||
/// An empty string; the result of concatenating anything with it is also
|
||||
/// empty.
|
||||
NullKind,
|
||||
|
||||
/// The empty string.
|
||||
EmptyKind,
|
||||
|
||||
/// A pointer to a Twine instance.
|
||||
TwineKind,
|
||||
|
||||
/// A pointer to a C string instance.
|
||||
CStringKind,
|
||||
|
||||
/// A pointer to an std::string instance.
|
||||
StdStringKind,
|
||||
|
||||
/// A pointer to a StringRef instance.
|
||||
StringRefKind,
|
||||
|
||||
/// A char value reinterpreted as a pointer, to render as a character.
|
||||
CharKind,
|
||||
|
||||
/// An unsigned int value reinterpreted as a pointer, to render as an
|
||||
/// unsigned decimal integer.
|
||||
DecUIKind,
|
||||
|
||||
/// An int value reinterpreted as a pointer, to render as a signed
|
||||
/// decimal integer.
|
||||
DecIKind,
|
||||
|
||||
/// A pointer to an unsigned long value, to render as an unsigned decimal
|
||||
/// integer.
|
||||
DecULKind,
|
||||
|
||||
/// A pointer to a long value, to render as a signed decimal integer.
|
||||
DecLKind,
|
||||
|
||||
/// A pointer to an unsigned long long value, to render as an unsigned
|
||||
/// decimal integer.
|
||||
DecULLKind,
|
||||
|
||||
/// A pointer to a long long value, to render as a signed decimal integer.
|
||||
DecLLKind,
|
||||
|
||||
/// A pointer to a uint64_t value, to render as an unsigned hexadecimal
|
||||
/// integer.
|
||||
UHexKind
|
||||
};
|
||||
|
||||
union Child
|
||||
{
|
||||
const Twine *twine;
|
||||
const char *cString;
|
||||
const std::string *stdString;
|
||||
const StringRef *stringRef;
|
||||
char character;
|
||||
unsigned int decUI;
|
||||
int decI;
|
||||
const unsigned long *decUL;
|
||||
const long *decL;
|
||||
const unsigned long long *decULL;
|
||||
const long long *decLL;
|
||||
const uint64_t *uHex;
|
||||
};
|
||||
|
||||
private:
|
||||
/// LHS - The prefix in the concatenation, which may be uninitialized for
|
||||
/// Null or Empty kinds.
|
||||
Child LHS;
|
||||
/// RHS - The suffix in the concatenation, which may be uninitialized for
|
||||
/// Null or Empty kinds.
|
||||
Child RHS;
|
||||
// enums stored as unsigned chars to save on space while some compilers
|
||||
// don't support specifying the backing type for an enum
|
||||
/// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
|
||||
unsigned char LHSKind;
|
||||
/// RHSKind - The NodeKind of the left hand side, \see getLHSKind().
|
||||
unsigned char RHSKind;
|
||||
|
||||
private:
|
||||
/// Construct a nullary twine; the kind must be NullKind or EmptyKind.
|
||||
explicit Twine(NodeKind Kind)
|
||||
: LHSKind(Kind), RHSKind(EmptyKind) {
|
||||
assert(isNullary() && "Invalid kind!");
|
||||
}
|
||||
|
||||
/// Construct a binary twine.
|
||||
explicit Twine(const Twine &_LHS, const Twine &_RHS)
|
||||
: LHSKind(TwineKind), RHSKind(TwineKind) {
|
||||
LHS.twine = &_LHS;
|
||||
RHS.twine = &_RHS;
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct a twine from explicit values.
|
||||
explicit Twine(Child _LHS, NodeKind _LHSKind,
|
||||
Child _RHS, NodeKind _RHSKind)
|
||||
: LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// isNull - Check for the null twine.
|
||||
bool isNull() const {
|
||||
return getLHSKind() == NullKind;
|
||||
}
|
||||
|
||||
/// isEmpty - Check for the empty twine.
|
||||
bool isEmpty() const {
|
||||
return getLHSKind() == EmptyKind;
|
||||
}
|
||||
|
||||
/// isNullary - Check if this is a nullary twine (null or empty).
|
||||
bool isNullary() const {
|
||||
return isNull() || isEmpty();
|
||||
}
|
||||
|
||||
/// isUnary - Check if this is a unary twine.
|
||||
bool isUnary() const {
|
||||
return getRHSKind() == EmptyKind && !isNullary();
|
||||
}
|
||||
|
||||
/// isBinary - Check if this is a binary twine.
|
||||
bool isBinary() const {
|
||||
return getLHSKind() != NullKind && getRHSKind() != EmptyKind;
|
||||
}
|
||||
|
||||
/// isValid - Check if this is a valid twine (satisfying the invariants on
|
||||
/// order and number of arguments).
|
||||
bool isValid() const {
|
||||
// Nullary twines always have Empty on the RHS.
|
||||
if (isNullary() && getRHSKind() != EmptyKind)
|
||||
return false;
|
||||
|
||||
// Null should never appear on the RHS.
|
||||
if (getRHSKind() == NullKind)
|
||||
return false;
|
||||
|
||||
// The RHS cannot be non-empty if the LHS is empty.
|
||||
if (getRHSKind() != EmptyKind && getLHSKind() == EmptyKind)
|
||||
return false;
|
||||
|
||||
// A twine child should always be binary.
|
||||
if (getLHSKind() == TwineKind &&
|
||||
!LHS.twine->isBinary())
|
||||
return false;
|
||||
if (getRHSKind() == TwineKind &&
|
||||
!RHS.twine->isBinary())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// getLHSKind - Get the NodeKind of the left-hand side.
|
||||
NodeKind getLHSKind() const { return (NodeKind) LHSKind; }
|
||||
|
||||
/// getRHSKind - Get the NodeKind of the right-hand side.
|
||||
NodeKind getRHSKind() const { return (NodeKind) RHSKind; }
|
||||
|
||||
/// printOneChild - Print one child from a twine.
|
||||
void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
|
||||
|
||||
/// printOneChildRepr - Print the representation of one child from a twine.
|
||||
void printOneChildRepr(raw_ostream &OS, Child Ptr,
|
||||
NodeKind Kind) const;
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
/// Construct from an empty string.
|
||||
/*implicit*/ Twine() : LHSKind(EmptyKind), RHSKind(EmptyKind) {
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct from a C string.
|
||||
///
|
||||
/// We take care here to optimize "" into the empty twine -- this will be
|
||||
/// optimized out for string constants. This allows Twine arguments have
|
||||
/// default "" values, without introducing unnecessary string constants.
|
||||
/*implicit*/ Twine(const char *Str)
|
||||
: RHSKind(EmptyKind) {
|
||||
if (Str[0] != '\0') {
|
||||
LHS.cString = Str;
|
||||
LHSKind = CStringKind;
|
||||
} else
|
||||
LHSKind = EmptyKind;
|
||||
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct from an std::string.
|
||||
/*implicit*/ Twine(const std::string &Str)
|
||||
: LHSKind(StdStringKind), RHSKind(EmptyKind) {
|
||||
LHS.stdString = &Str;
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct from a StringRef.
|
||||
/*implicit*/ Twine(const StringRef &Str)
|
||||
: LHSKind(StringRefKind), RHSKind(EmptyKind) {
|
||||
LHS.stringRef = &Str;
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct from a char.
|
||||
explicit Twine(char Val)
|
||||
: LHSKind(CharKind), RHSKind(EmptyKind) {
|
||||
LHS.character = Val;
|
||||
}
|
||||
|
||||
/// Construct from a signed char.
|
||||
explicit Twine(signed char Val)
|
||||
: LHSKind(CharKind), RHSKind(EmptyKind) {
|
||||
LHS.character = static_cast<char>(Val);
|
||||
}
|
||||
|
||||
/// Construct from an unsigned char.
|
||||
explicit Twine(unsigned char Val)
|
||||
: LHSKind(CharKind), RHSKind(EmptyKind) {
|
||||
LHS.character = static_cast<char>(Val);
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as an unsigned decimal integer.
|
||||
explicit Twine(unsigned Val)
|
||||
: LHSKind(DecUIKind), RHSKind(EmptyKind) {
|
||||
LHS.decUI = Val;
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as a signed decimal integer.
|
||||
explicit Twine(int Val)
|
||||
: LHSKind(DecIKind), RHSKind(EmptyKind) {
|
||||
LHS.decI = Val;
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as an unsigned decimal integer.
|
||||
explicit Twine(const unsigned long &Val)
|
||||
: LHSKind(DecULKind), RHSKind(EmptyKind) {
|
||||
LHS.decUL = &Val;
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as a signed decimal integer.
|
||||
explicit Twine(const long &Val)
|
||||
: LHSKind(DecLKind), RHSKind(EmptyKind) {
|
||||
LHS.decL = &Val;
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as an unsigned decimal integer.
|
||||
explicit Twine(const unsigned long long &Val)
|
||||
: LHSKind(DecULLKind), RHSKind(EmptyKind) {
|
||||
LHS.decULL = &Val;
|
||||
}
|
||||
|
||||
/// Construct a twine to print \p Val as a signed decimal integer.
|
||||
explicit Twine(const long long &Val)
|
||||
: LHSKind(DecLLKind), RHSKind(EmptyKind) {
|
||||
LHS.decLL = &Val;
|
||||
}
|
||||
|
||||
// FIXME: Unfortunately, to make sure this is as efficient as possible we
|
||||
// need extra binary constructors from particular types. We can't rely on
|
||||
// the compiler to be smart enough to fold operator+()/concat() down to the
|
||||
// right thing. Yet.
|
||||
|
||||
/// Construct as the concatenation of a C string and a StringRef.
|
||||
/*implicit*/ Twine(const char *_LHS, const StringRef &_RHS)
|
||||
: LHSKind(CStringKind), RHSKind(StringRefKind) {
|
||||
LHS.cString = _LHS;
|
||||
RHS.stringRef = &_RHS;
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Construct as the concatenation of a StringRef and a C string.
|
||||
/*implicit*/ Twine(const StringRef &_LHS, const char *_RHS)
|
||||
: LHSKind(StringRefKind), RHSKind(CStringKind) {
|
||||
LHS.stringRef = &_LHS;
|
||||
RHS.cString = _RHS;
|
||||
assert(isValid() && "Invalid twine!");
|
||||
}
|
||||
|
||||
/// Create a 'null' string, which is an empty string that always
|
||||
/// concatenates to form another empty string.
|
||||
static Twine createNull() {
|
||||
return Twine(NullKind);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Numeric Conversions
|
||||
/// @{
|
||||
|
||||
// Construct a twine to print \p Val as an unsigned hexadecimal integer.
|
||||
static Twine utohexstr(const uint64_t &Val) {
|
||||
Child LHS, RHS;
|
||||
LHS.uHex = &Val;
|
||||
RHS.twine = 0;
|
||||
return Twine(LHS, UHexKind, RHS, EmptyKind);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Predicate Operations
|
||||
/// @{
|
||||
|
||||
/// isTriviallyEmpty - Check if this twine is trivially empty; a false
|
||||
/// return value does not necessarily mean the twine is empty.
|
||||
bool isTriviallyEmpty() const {
|
||||
return isNullary();
|
||||
}
|
||||
|
||||
/// isSingleStringRef - Return true if this twine can be dynamically
|
||||
/// accessed as a single StringRef value with getSingleStringRef().
|
||||
bool isSingleStringRef() const {
|
||||
if (getRHSKind() != EmptyKind) return false;
|
||||
|
||||
switch (getLHSKind()) {
|
||||
case EmptyKind:
|
||||
case CStringKind:
|
||||
case StdStringKind:
|
||||
case StringRefKind:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
Twine concat(const Twine &Suffix) const;
|
||||
|
||||
/// @}
|
||||
/// @name Output & Conversion.
|
||||
/// @{
|
||||
|
||||
/// str - Return the twine contents as a std::string.
|
||||
std::string str() const;
|
||||
|
||||
/// toVector - Write the concatenated string into the given SmallString or
|
||||
/// SmallVector.
|
||||
void toVector(SmallVectorImpl<char> &Out) const;
|
||||
|
||||
/// getSingleStringRef - This returns the twine as a single StringRef. This
|
||||
/// method is only valid if isSingleStringRef() is true.
|
||||
StringRef getSingleStringRef() const {
|
||||
assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
|
||||
switch (getLHSKind()) {
|
||||
default: llvm_unreachable("Out of sync with isSingleStringRef");
|
||||
case EmptyKind: return StringRef();
|
||||
case CStringKind: return StringRef(LHS.cString);
|
||||
case StdStringKind: return StringRef(*LHS.stdString);
|
||||
case StringRefKind: return *LHS.stringRef;
|
||||
}
|
||||
}
|
||||
|
||||
/// toStringRef - This returns the twine as a single StringRef if it can be
|
||||
/// represented as such. Otherwise the twine is written into the given
|
||||
/// SmallVector and a StringRef to the SmallVector's data is returned.
|
||||
StringRef toStringRef(SmallVectorImpl<char> &Out) const;
|
||||
|
||||
/// toNullTerminatedStringRef - This returns the twine as a single null
|
||||
/// terminated StringRef if it can be represented as such. Otherwise the
|
||||
/// twine is written into the given SmallVector and a StringRef to the
|
||||
/// SmallVector's data is returned.
|
||||
///
|
||||
/// The returned StringRef's size does not include the null terminator.
|
||||
StringRef toNullTerminatedStringRef(SmallVectorImpl<char> &Out) const;
|
||||
|
||||
/// Write the concatenated string represented by this twine to the
|
||||
/// stream \p OS.
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
/// Dump the concatenated string represented by this twine to stderr.
|
||||
void dump() const;
|
||||
|
||||
/// Write the representation of this twine to the stream \p OS.
|
||||
void printRepr(raw_ostream &OS) const;
|
||||
|
||||
/// Dump the representation of this twine to stderr.
|
||||
void dumpRepr() const;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// @name Twine Inline Implementations
|
||||
/// @{
|
||||
|
||||
inline Twine Twine::concat(const Twine &Suffix) const {
|
||||
// Concatenation with null is null.
|
||||
if (isNull() || Suffix.isNull())
|
||||
return Twine(NullKind);
|
||||
|
||||
// Concatenation with empty yields the other side.
|
||||
if (isEmpty())
|
||||
return Suffix;
|
||||
if (Suffix.isEmpty())
|
||||
return *this;
|
||||
|
||||
// Otherwise we need to create a new node, taking care to fold in unary
|
||||
// twines.
|
||||
Child NewLHS, NewRHS;
|
||||
NewLHS.twine = this;
|
||||
NewRHS.twine = &Suffix;
|
||||
NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
|
||||
if (isUnary()) {
|
||||
NewLHS = LHS;
|
||||
NewLHSKind = getLHSKind();
|
||||
}
|
||||
if (Suffix.isUnary()) {
|
||||
NewRHS = Suffix.LHS;
|
||||
NewRHSKind = Suffix.getLHSKind();
|
||||
}
|
||||
|
||||
return Twine(NewLHS, NewLHSKind, NewRHS, NewRHSKind);
|
||||
}
|
||||
|
||||
inline Twine operator+(const Twine &LHS, const Twine &RHS) {
|
||||
return LHS.concat(RHS);
|
||||
}
|
||||
|
||||
/// Additional overload to guarantee simplified codegen; this is equivalent to
|
||||
/// concat().
|
||||
|
||||
inline Twine operator+(const char *LHS, const StringRef &RHS) {
|
||||
return Twine(LHS, RHS);
|
||||
}
|
||||
|
||||
/// Additional overload to guarantee simplified codegen; this is equivalent to
|
||||
/// concat().
|
||||
|
||||
inline Twine operator+(const StringRef &LHS, const char *RHS) {
|
||||
return Twine(LHS, RHS);
|
||||
}
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const Twine &RHS) {
|
||||
RHS.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
/// @}
|
||||
}
|
||||
|
||||
#endif
|
||||
89
thirdparty/clang/include/llvm/ADT/UniqueVector.h
vendored
Normal file
89
thirdparty/clang/include/llvm/ADT/UniqueVector.h
vendored
Normal file
@@ -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
|
||||
377
thirdparty/clang/include/llvm/ADT/ValueMap.h
vendored
Normal file
377
thirdparty/clang/include/llvm/ADT/ValueMap.h
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
//===- llvm/ADT/ValueMap.h - Safe map from Values to data -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the ValueMap class. ValueMap maps Value* or any subclass
|
||||
// to an arbitrary other type. It provides the DenseMap interface but updates
|
||||
// itself to remain safe when keys are RAUWed or deleted. By default, when a
|
||||
// key is RAUWed from V1 to V2, the old mapping V1->target is removed, and a new
|
||||
// mapping V2->target is added. If V2 already existed, its old target is
|
||||
// overwritten. When a key is deleted, its mapping is removed.
|
||||
//
|
||||
// You can override a ValueMap's Config parameter to control exactly what
|
||||
// happens on RAUW and destruction and to get called back on each event. It's
|
||||
// legal to call back into the ValueMap from a Config's callbacks. Config
|
||||
// parameters should inherit from ValueMapConfig<KeyT> to get default
|
||||
// implementations of all the methods ValueMap uses. See ValueMapConfig for
|
||||
// documentation of the functions you can override.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_VALUEMAP_H
|
||||
#define LLVM_ADT_VALUEMAP_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/Mutex.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <iterator>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
class ValueMapCallbackVH;
|
||||
|
||||
template<typename DenseMapT, typename KeyT>
|
||||
class ValueMapIterator;
|
||||
template<typename DenseMapT, typename KeyT>
|
||||
class ValueMapConstIterator;
|
||||
|
||||
/// This class defines the default behavior for configurable aspects of
|
||||
/// ValueMap<>. User Configs should inherit from this class to be as compatible
|
||||
/// as possible with future versions of ValueMap.
|
||||
template<typename KeyT>
|
||||
struct ValueMapConfig {
|
||||
/// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's
|
||||
/// false, the ValueMap will leave the original mapping in place.
|
||||
enum { FollowRAUW = true };
|
||||
|
||||
// All methods will be called with a first argument of type ExtraData. The
|
||||
// default implementations in this class take a templated first argument so
|
||||
// that users' subclasses can use any type they want without having to
|
||||
// override all the defaults.
|
||||
struct ExtraData {};
|
||||
|
||||
template<typename ExtraDataT>
|
||||
static void onRAUW(const ExtraDataT & /*Data*/, KeyT /*Old*/, KeyT /*New*/) {}
|
||||
template<typename ExtraDataT>
|
||||
static void onDelete(const ExtraDataT &/*Data*/, KeyT /*Old*/) {}
|
||||
|
||||
/// Returns a mutex that should be acquired around any changes to the map.
|
||||
/// This is only acquired from the CallbackVH (and held around calls to onRAUW
|
||||
/// and onDelete) and not inside other ValueMap methods. NULL means that no
|
||||
/// mutex is necessary.
|
||||
template<typename ExtraDataT>
|
||||
static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return NULL; }
|
||||
};
|
||||
|
||||
/// See the file comment.
|
||||
template<typename KeyT, typename ValueT, typename Config =ValueMapConfig<KeyT> >
|
||||
class ValueMap {
|
||||
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
|
||||
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
|
||||
typedef typename Config::ExtraData ExtraData;
|
||||
MapT Map;
|
||||
ExtraData Data;
|
||||
ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION;
|
||||
ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
typedef KeyT key_type;
|
||||
typedef ValueT mapped_type;
|
||||
typedef std::pair<KeyT, ValueT> value_type;
|
||||
|
||||
explicit ValueMap(unsigned NumInitBuckets = 64)
|
||||
: Map(NumInitBuckets), Data() {}
|
||||
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
|
||||
: Map(NumInitBuckets), Data(Data) {}
|
||||
|
||||
~ValueMap() {}
|
||||
|
||||
typedef ValueMapIterator<MapT, KeyT> iterator;
|
||||
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
|
||||
inline iterator begin() { return iterator(Map.begin()); }
|
||||
inline iterator end() { return iterator(Map.end()); }
|
||||
inline const_iterator begin() const { return const_iterator(Map.begin()); }
|
||||
inline const_iterator end() const { return const_iterator(Map.end()); }
|
||||
|
||||
bool empty() const { return Map.empty(); }
|
||||
unsigned size() const { return Map.size(); }
|
||||
|
||||
/// Grow the map so that it has at least Size buckets. Does not shrink
|
||||
void resize(size_t Size) { Map.resize(Size); }
|
||||
|
||||
void clear() { Map.clear(); }
|
||||
|
||||
/// count - Return true if the specified key is in the map.
|
||||
bool count(const KeyT &Val) const {
|
||||
return Map.find_as(Val) != Map.end();
|
||||
}
|
||||
|
||||
iterator find(const KeyT &Val) {
|
||||
return iterator(Map.find_as(Val));
|
||||
}
|
||||
const_iterator find(const KeyT &Val) const {
|
||||
return const_iterator(Map.find_as(Val));
|
||||
}
|
||||
|
||||
/// lookup - Return the entry for the specified key, or a default
|
||||
/// constructed value if no such entry exists.
|
||||
ValueT lookup(const KeyT &Val) const {
|
||||
typename MapT::const_iterator I = Map.find_as(Val);
|
||||
return I != Map.end() ? I->second : ValueT();
|
||||
}
|
||||
|
||||
// Inserts key,value pair into the map if the key isn't already in the map.
|
||||
// If the key is already in the map, it returns false and doesn't update the
|
||||
// value.
|
||||
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
|
||||
std::pair<typename MapT::iterator, bool> map_result=
|
||||
Map.insert(std::make_pair(Wrap(KV.first), KV.second));
|
||||
return std::make_pair(iterator(map_result.first), map_result.second);
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
typename MapT::iterator I = Map.find_as(Val);
|
||||
if (I == Map.end())
|
||||
return false;
|
||||
|
||||
Map.erase(I);
|
||||
return true;
|
||||
}
|
||||
void erase(iterator I) {
|
||||
return Map.erase(I.base());
|
||||
}
|
||||
|
||||
value_type& FindAndConstruct(const KeyT &Key) {
|
||||
return Map.FindAndConstruct(Wrap(Key));
|
||||
}
|
||||
|
||||
ValueT &operator[](const KeyT &Key) {
|
||||
return Map[Wrap(Key)];
|
||||
}
|
||||
|
||||
/// isPointerIntoBucketsArray - Return true if the specified pointer points
|
||||
/// somewhere into the ValueMap's array of buckets (i.e. either to a key or
|
||||
/// value in the ValueMap).
|
||||
bool isPointerIntoBucketsArray(const void *Ptr) const {
|
||||
return Map.isPointerIntoBucketsArray(Ptr);
|
||||
}
|
||||
|
||||
/// 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 ValueMap to reallocate.
|
||||
const void *getPointerIntoBucketsArray() const {
|
||||
return Map.getPointerIntoBucketsArray();
|
||||
}
|
||||
|
||||
private:
|
||||
// Takes a key being looked up in the map and wraps it into a
|
||||
// ValueMapCallbackVH, the actual key type of the map. We use a helper
|
||||
// function because ValueMapCVH is constructed with a second parameter.
|
||||
ValueMapCVH Wrap(KeyT key) const {
|
||||
// The only way the resulting CallbackVH could try to modify *this (making
|
||||
// the const_cast incorrect) is if it gets inserted into the map. But then
|
||||
// this function must have been called from a non-const method, making the
|
||||
// const_cast ok.
|
||||
return ValueMapCVH(key, const_cast<ValueMap*>(this));
|
||||
}
|
||||
};
|
||||
|
||||
// This CallbackVH updates its ValueMap when the contained Value changes,
|
||||
// according to the user's preferences expressed through the Config object.
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
class ValueMapCallbackVH : public CallbackVH {
|
||||
friend class ValueMap<KeyT, ValueT, Config>;
|
||||
friend struct DenseMapInfo<ValueMapCallbackVH>;
|
||||
typedef ValueMap<KeyT, ValueT, Config> ValueMapT;
|
||||
typedef typename llvm::remove_pointer<KeyT>::type KeySansPointerT;
|
||||
|
||||
ValueMapT *Map;
|
||||
|
||||
ValueMapCallbackVH(KeyT Key, ValueMapT *Map)
|
||||
: CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))),
|
||||
Map(Map) {}
|
||||
|
||||
public:
|
||||
KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); }
|
||||
|
||||
virtual void deleted() {
|
||||
// Make a copy that won't get changed even when *this is destroyed.
|
||||
ValueMapCallbackVH Copy(*this);
|
||||
sys::Mutex *M = Config::getMutex(Copy.Map->Data);
|
||||
if (M)
|
||||
M->acquire();
|
||||
Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
|
||||
Copy.Map->Map.erase(Copy); // Definitely destroys *this.
|
||||
if (M)
|
||||
M->release();
|
||||
}
|
||||
virtual void allUsesReplacedWith(Value *new_key) {
|
||||
assert(isa<KeySansPointerT>(new_key) &&
|
||||
"Invalid RAUW on key of ValueMap<>");
|
||||
// Make a copy that won't get changed even when *this is destroyed.
|
||||
ValueMapCallbackVH Copy(*this);
|
||||
sys::Mutex *M = Config::getMutex(Copy.Map->Data);
|
||||
if (M)
|
||||
M->acquire();
|
||||
|
||||
KeyT typed_new_key = cast<KeySansPointerT>(new_key);
|
||||
// Can destroy *this:
|
||||
Config::onRAUW(Copy.Map->Data, Copy.Unwrap(), typed_new_key);
|
||||
if (Config::FollowRAUW) {
|
||||
typename ValueMapT::MapT::iterator I = Copy.Map->Map.find(Copy);
|
||||
// I could == Copy.Map->Map.end() if the onRAUW callback already
|
||||
// removed the old mapping.
|
||||
if (I != Copy.Map->Map.end()) {
|
||||
ValueT Target(I->second);
|
||||
Copy.Map->Map.erase(I); // Definitely destroys *this.
|
||||
Copy.Map->insert(std::make_pair(typed_new_key, Target));
|
||||
}
|
||||
}
|
||||
if (M)
|
||||
M->release();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > {
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH;
|
||||
typedef DenseMapInfo<KeyT> PointerInfo;
|
||||
|
||||
static inline VH getEmptyKey() {
|
||||
return VH(PointerInfo::getEmptyKey(), NULL);
|
||||
}
|
||||
static inline VH getTombstoneKey() {
|
||||
return VH(PointerInfo::getTombstoneKey(), NULL);
|
||||
}
|
||||
static unsigned getHashValue(const VH &Val) {
|
||||
return PointerInfo::getHashValue(Val.Unwrap());
|
||||
}
|
||||
static unsigned getHashValue(const KeyT &Val) {
|
||||
return PointerInfo::getHashValue(Val);
|
||||
}
|
||||
static bool isEqual(const VH &LHS, const VH &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isEqual(const KeyT &LHS, const VH &RHS) {
|
||||
return LHS == RHS.getValPtr();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename DenseMapT, typename KeyT>
|
||||
class ValueMapIterator :
|
||||
public std::iterator<std::forward_iterator_tag,
|
||||
std::pair<KeyT, typename DenseMapT::mapped_type>,
|
||||
ptrdiff_t> {
|
||||
typedef typename DenseMapT::iterator BaseT;
|
||||
typedef typename DenseMapT::mapped_type ValueT;
|
||||
BaseT I;
|
||||
public:
|
||||
ValueMapIterator() : I() {}
|
||||
|
||||
ValueMapIterator(BaseT I) : I(I) {}
|
||||
|
||||
BaseT base() const { return I; }
|
||||
|
||||
struct ValueTypeProxy {
|
||||
const KeyT first;
|
||||
ValueT& second;
|
||||
ValueTypeProxy *operator->() { return this; }
|
||||
operator std::pair<KeyT, ValueT>() const {
|
||||
return std::make_pair(first, second);
|
||||
}
|
||||
};
|
||||
|
||||
ValueTypeProxy operator*() const {
|
||||
ValueTypeProxy Result = {I->first.Unwrap(), I->second};
|
||||
return Result;
|
||||
}
|
||||
|
||||
ValueTypeProxy operator->() const {
|
||||
return operator*();
|
||||
}
|
||||
|
||||
bool operator==(const ValueMapIterator &RHS) const {
|
||||
return I == RHS.I;
|
||||
}
|
||||
bool operator!=(const ValueMapIterator &RHS) const {
|
||||
return I != RHS.I;
|
||||
}
|
||||
|
||||
inline ValueMapIterator& operator++() { // Preincrement
|
||||
++I;
|
||||
return *this;
|
||||
}
|
||||
ValueMapIterator operator++(int) { // Postincrement
|
||||
ValueMapIterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DenseMapT, typename KeyT>
|
||||
class ValueMapConstIterator :
|
||||
public std::iterator<std::forward_iterator_tag,
|
||||
std::pair<KeyT, typename DenseMapT::mapped_type>,
|
||||
ptrdiff_t> {
|
||||
typedef typename DenseMapT::const_iterator BaseT;
|
||||
typedef typename DenseMapT::mapped_type ValueT;
|
||||
BaseT I;
|
||||
public:
|
||||
ValueMapConstIterator() : I() {}
|
||||
ValueMapConstIterator(BaseT I) : I(I) {}
|
||||
ValueMapConstIterator(ValueMapIterator<DenseMapT, KeyT> Other)
|
||||
: I(Other.base()) {}
|
||||
|
||||
BaseT base() const { return I; }
|
||||
|
||||
struct ValueTypeProxy {
|
||||
const KeyT first;
|
||||
const ValueT& second;
|
||||
ValueTypeProxy *operator->() { return this; }
|
||||
operator std::pair<KeyT, ValueT>() const {
|
||||
return std::make_pair(first, second);
|
||||
}
|
||||
};
|
||||
|
||||
ValueTypeProxy operator*() const {
|
||||
ValueTypeProxy Result = {I->first.Unwrap(), I->second};
|
||||
return Result;
|
||||
}
|
||||
|
||||
ValueTypeProxy operator->() const {
|
||||
return operator*();
|
||||
}
|
||||
|
||||
bool operator==(const ValueMapConstIterator &RHS) const {
|
||||
return I == RHS.I;
|
||||
}
|
||||
bool operator!=(const ValueMapConstIterator &RHS) const {
|
||||
return I != RHS.I;
|
||||
}
|
||||
|
||||
inline ValueMapConstIterator& operator++() { // Preincrement
|
||||
++I;
|
||||
return *this;
|
||||
}
|
||||
ValueMapConstIterator operator++(int) { // Postincrement
|
||||
ValueMapConstIterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
331
thirdparty/clang/include/llvm/ADT/VariadicFunction.h
vendored
Normal file
331
thirdparty/clang/include/llvm/ADT/VariadicFunction.h
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
//===--- VariadicFunctions.h - Variadic 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 implements compile-time type-safe variadic functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_VARIADICFUNCTION_H
|
||||
#define LLVM_ADT_VARIADICFUNCTION_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Define macros to aid in expanding a comma separated series with the index of
|
||||
// the series pasted onto the last token.
|
||||
#define LLVM_COMMA_JOIN1(x) x ## 0
|
||||
#define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
|
||||
#define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
|
||||
#define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
|
||||
#define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
|
||||
#define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
|
||||
#define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
|
||||
#define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
|
||||
#define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
|
||||
#define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
|
||||
#define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
|
||||
#define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
|
||||
#define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
|
||||
#define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
|
||||
#define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
|
||||
#define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
|
||||
#define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
|
||||
#define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
|
||||
#define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
|
||||
#define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
|
||||
#define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
|
||||
#define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
|
||||
#define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
|
||||
#define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
|
||||
#define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
|
||||
#define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
|
||||
#define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
|
||||
#define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
|
||||
#define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
|
||||
#define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
|
||||
#define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
|
||||
#define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
|
||||
|
||||
/// \brief Class which can simulate a type-safe variadic function.
|
||||
///
|
||||
/// The VariadicFunction class template makes it easy to define
|
||||
/// type-safe variadic functions where all arguments have the same
|
||||
/// type.
|
||||
///
|
||||
/// Suppose we need a variadic function like this:
|
||||
///
|
||||
/// ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
|
||||
///
|
||||
/// Instead of many overloads of Foo(), we only need to define a helper
|
||||
/// function that takes an array of arguments:
|
||||
///
|
||||
/// ResultT FooImpl(ArrayRef<const ArgT *> Args) {
|
||||
/// // 'Args[i]' is a pointer to the i-th argument passed to Foo().
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// and then define Foo() like this:
|
||||
///
|
||||
/// const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
|
||||
///
|
||||
/// VariadicFunction takes care of defining the overloads of Foo().
|
||||
///
|
||||
/// Actually, Foo is a function object (i.e. functor) instead of a plain
|
||||
/// function. This object is stateless and its constructor/destructor
|
||||
/// does nothing, so it's safe to create global objects and call Foo(...) at
|
||||
/// any time.
|
||||
///
|
||||
/// Sometimes we need a variadic function to have some fixed leading
|
||||
/// arguments whose types may be different from that of the optional
|
||||
/// arguments. For example:
|
||||
///
|
||||
/// bool FullMatch(const StringRef &S, const RE &Regex,
|
||||
/// const ArgT &A_0, ..., const ArgT &A_N);
|
||||
///
|
||||
/// VariadicFunctionN is for such cases, where N is the number of fixed
|
||||
/// arguments. It is like VariadicFunction, except that it takes N more
|
||||
/// template arguments for the types of the fixed arguments:
|
||||
///
|
||||
/// bool FullMatchImpl(const StringRef &S, const RE &Regex,
|
||||
/// ArrayRef<const ArgT *> Args) { ... }
|
||||
/// const VariadicFunction2<bool, const StringRef&,
|
||||
/// const RE&, ArgT, FullMatchImpl>
|
||||
/// FullMatch;
|
||||
///
|
||||
/// Currently VariadicFunction and friends support up-to 3
|
||||
/// fixed leading arguments and up-to 32 optional arguments.
|
||||
template <typename ResultT, typename ArgT,
|
||||
ResultT (*Func)(ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction {
|
||||
ResultT operator()() const {
|
||||
return Func(ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction1 {
|
||||
ResultT operator()(Param0T P0) const {
|
||||
return Func(P0, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction2 {
|
||||
ResultT operator()(Param0T P0, Param1T P1) const {
|
||||
return Func(P0, P1, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, Param1T P1, \
|
||||
LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, P1, makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename Param1T,
|
||||
typename Param2T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction3 {
|
||||
ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
|
||||
return Func(P0, P1, P2, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
|
||||
LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, P1, P2, makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
// Cleanup the macro namespace.
|
||||
#undef LLVM_COMMA_JOIN1
|
||||
#undef LLVM_COMMA_JOIN2
|
||||
#undef LLVM_COMMA_JOIN3
|
||||
#undef LLVM_COMMA_JOIN4
|
||||
#undef LLVM_COMMA_JOIN5
|
||||
#undef LLVM_COMMA_JOIN6
|
||||
#undef LLVM_COMMA_JOIN7
|
||||
#undef LLVM_COMMA_JOIN8
|
||||
#undef LLVM_COMMA_JOIN9
|
||||
#undef LLVM_COMMA_JOIN10
|
||||
#undef LLVM_COMMA_JOIN11
|
||||
#undef LLVM_COMMA_JOIN12
|
||||
#undef LLVM_COMMA_JOIN13
|
||||
#undef LLVM_COMMA_JOIN14
|
||||
#undef LLVM_COMMA_JOIN15
|
||||
#undef LLVM_COMMA_JOIN16
|
||||
#undef LLVM_COMMA_JOIN17
|
||||
#undef LLVM_COMMA_JOIN18
|
||||
#undef LLVM_COMMA_JOIN19
|
||||
#undef LLVM_COMMA_JOIN20
|
||||
#undef LLVM_COMMA_JOIN21
|
||||
#undef LLVM_COMMA_JOIN22
|
||||
#undef LLVM_COMMA_JOIN23
|
||||
#undef LLVM_COMMA_JOIN24
|
||||
#undef LLVM_COMMA_JOIN25
|
||||
#undef LLVM_COMMA_JOIN26
|
||||
#undef LLVM_COMMA_JOIN27
|
||||
#undef LLVM_COMMA_JOIN28
|
||||
#undef LLVM_COMMA_JOIN29
|
||||
#undef LLVM_COMMA_JOIN30
|
||||
#undef LLVM_COMMA_JOIN31
|
||||
#undef LLVM_COMMA_JOIN32
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ADT_VARIADICFUNCTION_H
|
||||
102
thirdparty/clang/include/llvm/ADT/edit_distance.h
vendored
Normal file
102
thirdparty/clang/include/llvm/ADT/edit_distance.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
//===-- llvm/ADT/edit_distance.h - Array edit distance function --- 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 Levenshtein distance function that works for any two
|
||||
// sequences, with each element of each sequence being analogous to a character
|
||||
// in a string.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_EDIT_DISTANCE_H
|
||||
#define LLVM_ADT_EDIT_DISTANCE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Determine the edit distance between two sequences.
|
||||
///
|
||||
/// \param FromArray the first sequence to compare.
|
||||
///
|
||||
/// \param ToArray the second sequence to compare.
|
||||
///
|
||||
/// \param AllowReplacements whether to allow element replacements (change one
|
||||
/// element into another) as a single operation, rather than as two operations
|
||||
/// (an insertion and a removal).
|
||||
///
|
||||
/// \param MaxEditDistance If non-zero, the maximum edit distance that this
|
||||
/// routine is allowed to compute. If the edit distance will exceed that
|
||||
/// maximum, returns \c MaxEditDistance+1.
|
||||
///
|
||||
/// \returns the minimum number of element insertions, removals, or (if
|
||||
/// \p AllowReplacements is \c true) replacements needed to transform one of
|
||||
/// the given sequences into the other. If zero, the sequences are identical.
|
||||
template<typename T>
|
||||
unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
|
||||
bool AllowReplacements = true,
|
||||
unsigned MaxEditDistance = 0) {
|
||||
// The algorithm implemented below is the "classic"
|
||||
// dynamic-programming algorithm for computing the Levenshtein
|
||||
// distance, which is described here:
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Levenshtein_distance
|
||||
//
|
||||
// Although the algorithm is typically described using an m x n
|
||||
// array, only two rows are used at a time, so this implemenation
|
||||
// just keeps two separate vectors for those two rows.
|
||||
typename ArrayRef<T>::size_type m = FromArray.size();
|
||||
typename ArrayRef<T>::size_type n = ToArray.size();
|
||||
|
||||
const unsigned SmallBufferSize = 64;
|
||||
unsigned SmallBuffer[SmallBufferSize];
|
||||
llvm::OwningArrayPtr<unsigned> Allocated;
|
||||
unsigned *Previous = SmallBuffer;
|
||||
if (2*(n + 1) > SmallBufferSize) {
|
||||
Previous = new unsigned [2*(n+1)];
|
||||
Allocated.reset(Previous);
|
||||
}
|
||||
unsigned *Current = Previous + (n + 1);
|
||||
|
||||
for (unsigned i = 0; i <= n; ++i)
|
||||
Previous[i] = i;
|
||||
|
||||
for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
|
||||
Current[0] = y;
|
||||
unsigned BestThisRow = Current[0];
|
||||
|
||||
for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
|
||||
if (AllowReplacements) {
|
||||
Current[x] = std::min(
|
||||
Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
|
||||
std::min(Current[x-1], Previous[x])+1);
|
||||
}
|
||||
else {
|
||||
if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1];
|
||||
else Current[x] = std::min(Current[x-1], Previous[x]) + 1;
|
||||
}
|
||||
BestThisRow = std::min(BestThisRow, Current[x]);
|
||||
}
|
||||
|
||||
if (MaxEditDistance && BestThisRow > MaxEditDistance)
|
||||
return MaxEditDistance + 1;
|
||||
|
||||
unsigned *tmp = Current;
|
||||
Current = Previous;
|
||||
Previous = tmp;
|
||||
}
|
||||
|
||||
unsigned Result = Previous[n];
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
720
thirdparty/clang/include/llvm/ADT/ilist.h
vendored
Normal file
720
thirdparty/clang/include/llvm/ADT/ilist.h
vendored
Normal file
@@ -0,0 +1,720 @@
|
||||
//==-- 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/Support/Compiler.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
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 : public ilist_nextprev_traits<NodeTy>,
|
||||
public ilist_sentinel_traits<NodeTy>,
|
||||
public 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 : public 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 std::iterator<std::bidirectional_iterator_tag, NodeTy, ptrdiff_t> {
|
||||
|
||||
public:
|
||||
typedef ilist_traits<NodeTy> Traits;
|
||||
typedef std::iterator<std::bidirectional_iterator_tag,
|
||||
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 {
|
||||
return NodePtr;
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
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);
|
||||
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; }
|
||||
};
|
||||
|
||||
// These are to catch errors when people try to use them as random access
|
||||
// iterators.
|
||||
template<typename T>
|
||||
void operator-(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
|
||||
template<typename T>
|
||||
void operator-(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
|
||||
|
||||
template<typename T>
|
||||
void operator+(int, ilist_iterator<T>) LLVM_DELETED_FUNCTION;
|
||||
template<typename T>
|
||||
void operator+(ilist_iterator<T>,int) LLVM_DELETED_FUNCTION;
|
||||
|
||||
// operator!=/operator== - Allow mixed comparisons without dereferencing
|
||||
// the iterator, which could very likely be pointing to end().
|
||||
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(ilist_iterator<NodeTy> &Node) {
|
||||
return &*Node;
|
||||
}
|
||||
};
|
||||
template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > {
|
||||
typedef /*const*/ 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 heterogeneous 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->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 be copyable, but the default
|
||||
// copy/copy-assign won't do.
|
||||
iplist(const iplist &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const iplist &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
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->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;
|
||||
}
|
||||
|
||||
/// Remove all nodes from the list like clear(), but do not call
|
||||
/// removeNodeFromList() or deleteNode().
|
||||
///
|
||||
/// This should only be used immediately before freeing nodes in bulk to
|
||||
/// avoid traversing the list and bringing all the nodes into cache.
|
||||
void clearAndLeakNodesUnsafely() {
|
||||
if (Head) {
|
||||
Head = getTail();
|
||||
this->setPrev(Head, Head);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
// Position cannot be contained in the range to be transferred.
|
||||
// Check for the most common mistake.
|
||||
assert(position != first &&
|
||||
"Insertion point can't be one of the transferred nodes");
|
||||
|
||||
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 = this->getPrev(First);
|
||||
NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->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 = this->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);
|
||||
|
||||
this->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); }
|
||||
};
|
||||
|
||||
|
||||
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, this->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); }
|
||||
|
||||
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
|
||||
106
thirdparty/clang/include/llvm/ADT/ilist_node.h
vendored
Normal file
106
thirdparty/clang/include/llvm/ADT/ilist_node.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//==-- 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_ILISTNODE_H
|
||||
#define LLVM_ADT_ILISTNODE_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename NodeTy>
|
||||
struct ilist_traits;
|
||||
|
||||
/// ilist_half_node - Base class that provides prev services for sentinels.
|
||||
///
|
||||
template<typename NodeTy>
|
||||
class ilist_half_node {
|
||||
friend struct ilist_traits<NodeTy>;
|
||||
NodeTy *Prev;
|
||||
protected:
|
||||
NodeTy *getPrev() { return Prev; }
|
||||
const NodeTy *getPrev() const { return Prev; }
|
||||
void setPrev(NodeTy *P) { Prev = P; }
|
||||
ilist_half_node() : Prev(0) {}
|
||||
};
|
||||
|
||||
template<typename NodeTy>
|
||||
struct ilist_nextprev_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 ilist_half_node<NodeTy> {
|
||||
friend struct ilist_nextprev_traits<NodeTy>;
|
||||
friend struct ilist_traits<NodeTy>;
|
||||
NodeTy *Next;
|
||||
NodeTy *getNext() { return Next; }
|
||||
const NodeTy *getNext() const { return Next; }
|
||||
void setNext(NodeTy *N) { Next = N; }
|
||||
protected:
|
||||
ilist_node() : Next(0) {}
|
||||
|
||||
public:
|
||||
/// @name Adjacent Node Accessors
|
||||
/// @{
|
||||
|
||||
/// \brief Get the previous node, or 0 for the list head.
|
||||
NodeTy *getPrevNode() {
|
||||
NodeTy *Prev = this->getPrev();
|
||||
|
||||
// Check for sentinel.
|
||||
if (!Prev->getNext())
|
||||
return 0;
|
||||
|
||||
return Prev;
|
||||
}
|
||||
|
||||
/// \brief Get the previous node, or 0 for the list head.
|
||||
const NodeTy *getPrevNode() const {
|
||||
const NodeTy *Prev = this->getPrev();
|
||||
|
||||
// Check for sentinel.
|
||||
if (!Prev->getNext())
|
||||
return 0;
|
||||
|
||||
return Prev;
|
||||
}
|
||||
|
||||
/// \brief Get the next node, or 0 for the list tail.
|
||||
NodeTy *getNextNode() {
|
||||
NodeTy *Next = getNext();
|
||||
|
||||
// Check for sentinel.
|
||||
if (!Next->getNext())
|
||||
return 0;
|
||||
|
||||
return Next;
|
||||
}
|
||||
|
||||
/// \brief Get the next node, or 0 for the list tail.
|
||||
const NodeTy *getNextNode() const {
|
||||
const NodeTy *Next = getNext();
|
||||
|
||||
// Check for sentinel.
|
||||
if (!Next->getNext())
|
||||
return 0;
|
||||
|
||||
return Next;
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user