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
|
||||
41
thirdparty/clang/include/llvm/AddressingMode.h
vendored
Normal file
41
thirdparty/clang/include/llvm/AddressingMode.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
//===--------- llvm/AddressingMode.h - Addressing Mode -------*- 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 addressing mode data structures which are shared
|
||||
// between LSR and a number of places in the codegen.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADDRESSING_MODE_H
|
||||
#define LLVM_ADDRESSING_MODE_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class GlobalValue;
|
||||
|
||||
/// AddrMode - This represents an addressing mode of:
|
||||
/// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg
|
||||
/// If BaseGV is null, there is no BaseGV.
|
||||
/// If BaseOffs is zero, there is no base offset.
|
||||
/// If HasBaseReg is false, there is no base register.
|
||||
/// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with
|
||||
/// no scale.
|
||||
///
|
||||
struct AddrMode {
|
||||
GlobalValue *BaseGV;
|
||||
int64_t BaseOffs;
|
||||
bool HasBaseReg;
|
||||
int64_t Scale;
|
||||
AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
598
thirdparty/clang/include/llvm/Analysis/AliasAnalysis.h
vendored
Normal file
598
thirdparty/clang/include/llvm/Analysis/AliasAnalysis.h
vendored
Normal file
@@ -0,0 +1,598 @@
|
||||
//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis 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 generic AliasAnalysis interface, which is used as the
|
||||
// common interface used by all clients of alias analysis information, and
|
||||
// implemented by all alias analysis implementations. Mod/Ref information is
|
||||
// also captured by this interface.
|
||||
//
|
||||
// Implementations of this interface must implement the various virtual methods,
|
||||
// which automatically provides functionality for the entire suite of client
|
||||
// APIs.
|
||||
//
|
||||
// This API identifies memory regions with the Location class. The pointer
|
||||
// component specifies the base memory address of the region. The Size specifies
|
||||
// the maximum size (in address units) of the memory region, or UnknownSize if
|
||||
// the size is not known. The TBAA tag identifies the "type" of the memory
|
||||
// reference; see the TypeBasedAliasAnalysis class for details.
|
||||
//
|
||||
// Some non-obvious details include:
|
||||
// - Pointers that point to two completely different objects in memory never
|
||||
// alias, regardless of the value of the Size component.
|
||||
// - NoAlias doesn't imply inequal pointers. The most obvious example of this
|
||||
// is two pointers to constant memory. Even if they are equal, constant
|
||||
// memory is never stored to, so there will never be any dependencies.
|
||||
// In this and other situations, the pointers may be both NoAlias and
|
||||
// MustAlias at the same time. The current API can only return one result,
|
||||
// though this is rarely a problem in practice.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H
|
||||
#define LLVM_ANALYSIS_ALIASANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Pass;
|
||||
class AnalysisUsage;
|
||||
class MemTransferInst;
|
||||
class MemIntrinsic;
|
||||
class DominatorTree;
|
||||
|
||||
class AliasAnalysis {
|
||||
protected:
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA; // Previous Alias Analysis to chain to.
|
||||
|
||||
protected:
|
||||
/// InitializeAliasAnalysis - Subclasses must call this method to initialize
|
||||
/// the AliasAnalysis interface before any other methods are called. This is
|
||||
/// typically called by the run* methods of these subclasses. This may be
|
||||
/// called multiple times.
|
||||
///
|
||||
void InitializeAliasAnalysis(Pass *P);
|
||||
|
||||
/// getAnalysisUsage - All alias analysis implementations should invoke this
|
||||
/// directly (using AliasAnalysis::getAnalysisUsage(AU)).
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
AliasAnalysis() : TD(0), TLI(0), AA(0) {}
|
||||
virtual ~AliasAnalysis(); // We want to be subclassed
|
||||
|
||||
/// UnknownSize - This is a special value which can be used with the
|
||||
/// size arguments in alias queries to indicate that the caller does not
|
||||
/// know the sizes of the potential memory references.
|
||||
static uint64_t const UnknownSize = ~UINT64_C(0);
|
||||
|
||||
/// getDataLayout - Return a pointer to the current DataLayout object, or
|
||||
/// null if no DataLayout object is available.
|
||||
///
|
||||
const DataLayout *getDataLayout() const { return TD; }
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
///
|
||||
const TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
|
||||
|
||||
/// getTypeStoreSize - Return the DataLayout store size for the given type,
|
||||
/// if known, or a conservative value otherwise.
|
||||
///
|
||||
uint64_t getTypeStoreSize(Type *Ty);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Alias Queries...
|
||||
///
|
||||
|
||||
/// Location - A description of a memory location.
|
||||
struct Location {
|
||||
/// Ptr - The address of the start of the location.
|
||||
const Value *Ptr;
|
||||
/// Size - The maximum size of the location, in address-units, or
|
||||
/// UnknownSize if the size is not known. Note that an unknown size does
|
||||
/// not mean the pointer aliases the entire virtual address space, because
|
||||
/// there are restrictions on stepping out of one object and into another.
|
||||
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
|
||||
uint64_t Size;
|
||||
/// TBAATag - The metadata node which describes the TBAA type of
|
||||
/// the location, or null if there is no known unique tag.
|
||||
const MDNode *TBAATag;
|
||||
|
||||
explicit Location(const Value *P = 0, uint64_t S = UnknownSize,
|
||||
const MDNode *N = 0)
|
||||
: Ptr(P), Size(S), TBAATag(N) {}
|
||||
|
||||
Location getWithNewPtr(const Value *NewPtr) const {
|
||||
Location Copy(*this);
|
||||
Copy.Ptr = NewPtr;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithNewSize(uint64_t NewSize) const {
|
||||
Location Copy(*this);
|
||||
Copy.Size = NewSize;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithoutTBAATag() const {
|
||||
Location Copy(*this);
|
||||
Copy.TBAATag = 0;
|
||||
return Copy;
|
||||
}
|
||||
};
|
||||
|
||||
/// getLocation - Fill in Loc with information about the memory reference by
|
||||
/// the given instruction.
|
||||
Location getLocation(const LoadInst *LI);
|
||||
Location getLocation(const StoreInst *SI);
|
||||
Location getLocation(const VAArgInst *VI);
|
||||
Location getLocation(const AtomicCmpXchgInst *CXI);
|
||||
Location getLocation(const AtomicRMWInst *RMWI);
|
||||
static Location getLocationForSource(const MemTransferInst *MTI);
|
||||
static Location getLocationForDest(const MemIntrinsic *MI);
|
||||
|
||||
/// Alias analysis result - Either we know for sure that it does not alias, we
|
||||
/// know for sure it must alias, or we don't know anything: The two pointers
|
||||
/// _might_ alias. This enum is designed so you can do things like:
|
||||
/// if (AA.alias(P1, P2)) { ... }
|
||||
/// to check to see if two pointers might alias.
|
||||
///
|
||||
/// See docs/AliasAnalysis.html for more information on the specific meanings
|
||||
/// of these values.
|
||||
///
|
||||
enum AliasResult {
|
||||
NoAlias = 0, ///< No dependencies.
|
||||
MayAlias, ///< Anything goes.
|
||||
PartialAlias, ///< Pointers differ, but pointees overlap.
|
||||
MustAlias ///< Pointers are equal.
|
||||
};
|
||||
|
||||
/// alias - The main low level interface to the alias analysis implementation.
|
||||
/// Returns an AliasResult indicating whether the two pointers are aliased to
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// alias analysis implementations.
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
AliasResult alias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return alias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
AliasResult alias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, UnknownSize, V2, UnknownSize);
|
||||
}
|
||||
|
||||
/// isNoAlias - A trivial helper function to check to see if the specified
|
||||
/// pointers are no-alias.
|
||||
bool isNoAlias(const Location &LocA, const Location &LocB) {
|
||||
return alias(LocA, LocB) == NoAlias;
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, const Value *V2) {
|
||||
return isNoAlias(Location(V1), Location(V2));
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
bool isMustAlias(const Location &LocA, const Location &LocB) {
|
||||
return alias(LocA, LocB) == MustAlias;
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
bool isMustAlias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, 1, V2, 1) == MustAlias;
|
||||
}
|
||||
|
||||
/// pointsToConstantMemory - If the specified memory location is
|
||||
/// known to be constant, return true. If OrLocal is true and the
|
||||
/// specified memory location is known to be "local" (derived from
|
||||
/// an alloca), return true. Otherwise return false.
|
||||
virtual bool pointsToConstantMemory(const Location &Loc,
|
||||
bool OrLocal = false);
|
||||
|
||||
/// pointsToConstantMemory - A convenient wrapper.
|
||||
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
|
||||
return pointsToConstantMemory(Location(P), OrLocal);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Simple mod/ref information...
|
||||
///
|
||||
|
||||
/// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are
|
||||
/// bits which may be or'd together.
|
||||
///
|
||||
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
|
||||
|
||||
/// These values define additional bits used to define the
|
||||
/// ModRefBehavior values.
|
||||
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
|
||||
|
||||
/// ModRefBehavior - Summary of how a function affects memory in the program.
|
||||
/// Loads from constant globals are not considered memory accesses for this
|
||||
/// interface. Also, functions may freely modify stack space local to their
|
||||
/// invocation without having to report it through these interfaces.
|
||||
enum ModRefBehavior {
|
||||
/// DoesNotAccessMemory - This function does not perform any non-local loads
|
||||
/// or stores to memory.
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readnone' attribute.
|
||||
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
|
||||
DoesNotAccessMemory = Nowhere | NoModRef,
|
||||
|
||||
/// OnlyReadsArgumentPointees - The only memory references in this function
|
||||
/// (if it has any) are non-volatile loads from objects pointed to by its
|
||||
/// pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
|
||||
OnlyReadsArgumentPointees = ArgumentPointees | Ref,
|
||||
|
||||
/// OnlyAccessesArgumentPointees - The only memory references in this
|
||||
/// function (if it has any) are non-volatile loads and stores from objects
|
||||
/// pointed to by its pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
|
||||
OnlyAccessesArgumentPointees = ArgumentPointees | ModRef,
|
||||
|
||||
/// OnlyReadsMemory - This function does not perform any non-local stores or
|
||||
/// volatile loads, but may read from any memory location.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readonly' attribute.
|
||||
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
|
||||
OnlyReadsMemory = Anywhere | Ref,
|
||||
|
||||
/// UnknownModRefBehavior - This indicates that the function could not be
|
||||
/// classified into one of the behaviors above.
|
||||
UnknownModRefBehavior = Anywhere | ModRef
|
||||
};
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given function.
|
||||
/// For use when the call site is not known.
|
||||
virtual ModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// doesNotAccessMemory - If the specified call is known to never read or
|
||||
/// write memory, return true. If the call only reads from known-constant
|
||||
/// memory, it is also legal to return true. Calls that unwind the stack
|
||||
/// are legal for this predicate.
|
||||
///
|
||||
/// Many optimizations (such as CSE and LICM) can be performed on such calls
|
||||
/// without worrying about aliasing properties, and many calls have this
|
||||
/// property (e.g. calls to 'sin' and 'cos').
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
///
|
||||
bool doesNotAccessMemory(ImmutableCallSite CS) {
|
||||
return getModRefBehavior(CS) == DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// doesNotAccessMemory - If the specified function is known to never read or
|
||||
/// write memory, return true. For use when the call site is not known.
|
||||
///
|
||||
bool doesNotAccessMemory(const Function *F) {
|
||||
return getModRefBehavior(F) == DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified call is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. Calls
|
||||
/// that unwind the stack are legal for this predicate.
|
||||
///
|
||||
/// This property allows many common optimizations to be performed in the
|
||||
/// absence of interfering store instructions, such as CSE of strlen calls.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
///
|
||||
bool onlyReadsMemory(ImmutableCallSite CS) {
|
||||
return onlyReadsMemory(getModRefBehavior(CS));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified function is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. For use
|
||||
/// when the call site is not known.
|
||||
///
|
||||
bool onlyReadsMemory(const Function *F) {
|
||||
return onlyReadsMemory(getModRefBehavior(F));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - Return true if functions with the specified behavior are
|
||||
/// known to only read from non-volatile memory (or not access memory at all).
|
||||
///
|
||||
static bool onlyReadsMemory(ModRefBehavior MRB) {
|
||||
return !(MRB & Mod);
|
||||
}
|
||||
|
||||
/// onlyAccessesArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to read and write at most from objects pointed to by
|
||||
/// their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool onlyAccessesArgPointees(ModRefBehavior MRB) {
|
||||
return !(MRB & Anywhere & ~ArgumentPointees);
|
||||
}
|
||||
|
||||
/// doesAccessArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to potentially read or write from objects pointed
|
||||
/// to be their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool doesAccessArgPointees(ModRefBehavior MRB) {
|
||||
return (MRB & ModRef) && (MRB & ArgumentPointees);
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether or not an instruction may
|
||||
/// read or write the specified memory location. An instruction
|
||||
/// that doesn't read or write memory may be trivially LICM'd for example.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Location &Loc) {
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
|
||||
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
|
||||
case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc);
|
||||
case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc);
|
||||
case Instruction::AtomicCmpXchg:
|
||||
return getModRefInfo((const AtomicCmpXchgInst*)I, Loc);
|
||||
case Instruction::AtomicRMW:
|
||||
return getModRefInfo((const AtomicRMWInst*)I, Loc);
|
||||
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
|
||||
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
|
||||
default: return NoModRef;
|
||||
}
|
||||
}
|
||||
|
||||
/// getModRefInfo - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for call sites) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(CS, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - Return information about whether
|
||||
/// a particular call modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(C), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(C, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - Return information about whether
|
||||
/// a particular invoke modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(I), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for loads) - Return information about whether
|
||||
/// a particular load modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for loads) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(L, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for stores) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for stores) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
|
||||
// Conservatively correct. (We could possibly be a bit smarter if
|
||||
// Loc is a alloca that doesn't escape.)
|
||||
return ModRef;
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - Return information about whether
|
||||
/// a particular cmpxchg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(CX, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - Return information about whether
|
||||
/// a particular atomicrmw modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(RMW, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for va_args) - Return information about whether
|
||||
/// a particular va_arg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for va_args) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether two call sites may refer
|
||||
/// to the same set of memory locations. See
|
||||
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
|
||||
/// for details.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2);
|
||||
|
||||
/// callCapturesBefore - Return information about whether a particular call
|
||||
/// site modifies or reads the specified memory location.
|
||||
ModRefResult callCapturesBefore(const Instruction *I,
|
||||
const AliasAnalysis::Location &MemLoc,
|
||||
DominatorTree *DT);
|
||||
|
||||
/// callCapturesBefore - A convenience wrapper.
|
||||
ModRefResult callCapturesBefore(const Instruction *I, const Value *P,
|
||||
uint64_t Size, DominatorTree *DT) {
|
||||
return callCapturesBefore(I, Location(P, Size), DT);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Higher level methods for querying mod/ref information.
|
||||
///
|
||||
|
||||
/// canBasicBlockModify - Return true if it is possible for execution of the
|
||||
/// specified basic block to modify the value pointed to by Ptr.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
|
||||
|
||||
/// canBasicBlockModify - A convenience wrapper.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){
|
||||
return canBasicBlockModify(BB, Location(P, Size));
|
||||
}
|
||||
|
||||
/// canInstructionRangeModify - Return true if it is possible for the
|
||||
/// execution of the specified instructions to modify the value pointed to by
|
||||
/// Ptr. The instructions to consider are all of the instructions in the
|
||||
/// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
|
||||
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
|
||||
const Location &Loc);
|
||||
|
||||
/// canInstructionRangeModify - A convenience wrapper.
|
||||
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
|
||||
const Value *Ptr, uint64_t Size) {
|
||||
return canInstructionRangeModify(I1, I2, Location(Ptr, Size));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Methods that clients should call when they transform the program to allow
|
||||
/// alias analyses to update their internal data structures. Note that these
|
||||
/// methods may be called on any instruction, regardless of whether or not
|
||||
/// they have pointer-analysis implications.
|
||||
///
|
||||
|
||||
/// deleteValue - This method should be called whenever an LLVM Value is
|
||||
/// deleted from the program, for example when an instruction is found to be
|
||||
/// redundant and is eliminated.
|
||||
///
|
||||
virtual void deleteValue(Value *V);
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in the
|
||||
/// program is copied or cloned, introducing a new value. Note that analysis
|
||||
/// implementations should tolerate clients that use this method to introduce
|
||||
/// the same value multiple times: if the analysis already knows about a
|
||||
/// value, it should ignore the request.
|
||||
///
|
||||
virtual void copyValue(Value *From, Value *To);
|
||||
|
||||
/// addEscapingUse - This method should be used whenever an escaping use is
|
||||
/// added to a pointer value. Analysis implementations may either return
|
||||
/// conservative responses for that value in the future, or may recompute
|
||||
/// some or all internal state to continue providing precise responses.
|
||||
///
|
||||
/// Escaping uses are considered by anything _except_ the following:
|
||||
/// - GEPs or bitcasts of the pointer
|
||||
/// - Loads through the pointer
|
||||
/// - Stores through (but not of) the pointer
|
||||
virtual void addEscapingUse(Use &U);
|
||||
|
||||
/// replaceWithNewValue - This method is the obvious combination of the two
|
||||
/// above, and it provided as a helper to simplify client code.
|
||||
///
|
||||
void replaceWithNewValue(Value *Old, Value *New) {
|
||||
copyValue(Old, New);
|
||||
deleteValue(Old);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize DenseMapInfo for Location.
|
||||
template<>
|
||||
struct DenseMapInfo<AliasAnalysis::Location> {
|
||||
static inline AliasAnalysis::Location getEmptyKey() {
|
||||
return
|
||||
AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
|
||||
0, 0);
|
||||
}
|
||||
static inline AliasAnalysis::Location getTombstoneKey() {
|
||||
return
|
||||
AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(),
|
||||
0, 0);
|
||||
}
|
||||
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
|
||||
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
|
||||
DenseMapInfo<const MDNode *>::getHashValue(Val.TBAATag);
|
||||
}
|
||||
static bool isEqual(const AliasAnalysis::Location &LHS,
|
||||
const AliasAnalysis::Location &RHS) {
|
||||
return LHS.Ptr == RHS.Ptr &&
|
||||
LHS.Size == RHS.Size &&
|
||||
LHS.TBAATag == RHS.TBAATag;
|
||||
}
|
||||
};
|
||||
|
||||
/// isNoAliasCall - Return true if this pointer is returned by a noalias
|
||||
/// function.
|
||||
bool isNoAliasCall(const Value *V);
|
||||
|
||||
/// isIdentifiedObject - Return true if this pointer refers to a distinct and
|
||||
/// identifiable object. This returns true for:
|
||||
/// Global Variables and Functions (but not Global Aliases)
|
||||
/// Allocas
|
||||
/// ByVal and NoAlias Arguments
|
||||
/// NoAlias returns (e.g. calls to malloc)
|
||||
///
|
||||
bool isIdentifiedObject(const Value *V);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
437
thirdparty/clang/include/llvm/Analysis/AliasSetTracker.h
vendored
Normal file
437
thirdparty/clang/include/llvm/Analysis/AliasSetTracker.h
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
//===- llvm/Analysis/AliasSetTracker.h - Build Alias 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 two classes: AliasSetTracker and AliasSet. These interface
|
||||
// are used to classify a collection of pointer references into a maximal number
|
||||
// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
|
||||
// object refers to memory disjoint from the other sets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
|
||||
#define LLVM_ANALYSIS_ALIASSETTRACKER_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
class AliasSetTracker;
|
||||
class AliasSet;
|
||||
|
||||
class AliasSet : public ilist_node<AliasSet> {
|
||||
friend class AliasSetTracker;
|
||||
|
||||
class PointerRec {
|
||||
Value *Val; // The pointer this record corresponds to.
|
||||
PointerRec **PrevInList, *NextInList;
|
||||
AliasSet *AS;
|
||||
uint64_t Size;
|
||||
const MDNode *TBAAInfo;
|
||||
public:
|
||||
PointerRec(Value *V)
|
||||
: Val(V), PrevInList(0), NextInList(0), AS(0), Size(0),
|
||||
TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {}
|
||||
|
||||
Value *getValue() const { return Val; }
|
||||
|
||||
PointerRec *getNext() const { return NextInList; }
|
||||
bool hasAliasSet() const { return AS != 0; }
|
||||
|
||||
PointerRec** setPrevInList(PointerRec **PIL) {
|
||||
PrevInList = PIL;
|
||||
return &NextInList;
|
||||
}
|
||||
|
||||
void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) {
|
||||
if (NewSize > Size) Size = NewSize;
|
||||
|
||||
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey())
|
||||
// We don't have a TBAAInfo yet. Set it to NewTBAAInfo.
|
||||
TBAAInfo = NewTBAAInfo;
|
||||
else if (TBAAInfo != NewTBAAInfo)
|
||||
// NewTBAAInfo conflicts with TBAAInfo.
|
||||
TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey();
|
||||
}
|
||||
|
||||
uint64_t getSize() const { return Size; }
|
||||
|
||||
/// getTBAAInfo - Return the TBAAInfo, or null if there is no
|
||||
/// information or conflicting information.
|
||||
const MDNode *getTBAAInfo() const {
|
||||
// If we have missing or conflicting TBAAInfo, return null.
|
||||
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() ||
|
||||
TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey())
|
||||
return 0;
|
||||
return TBAAInfo;
|
||||
}
|
||||
|
||||
AliasSet *getAliasSet(AliasSetTracker &AST) {
|
||||
assert(AS && "No AliasSet yet!");
|
||||
if (AS->Forward) {
|
||||
AliasSet *OldAS = AS;
|
||||
AS = OldAS->getForwardedTarget(AST);
|
||||
AS->addRef();
|
||||
OldAS->dropRef(AST);
|
||||
}
|
||||
return AS;
|
||||
}
|
||||
|
||||
void setAliasSet(AliasSet *as) {
|
||||
assert(AS == 0 && "Already have an alias set!");
|
||||
AS = as;
|
||||
}
|
||||
|
||||
void eraseFromList() {
|
||||
if (NextInList) NextInList->PrevInList = PrevInList;
|
||||
*PrevInList = NextInList;
|
||||
if (AS->PtrListEnd == &NextInList) {
|
||||
AS->PtrListEnd = PrevInList;
|
||||
assert(*AS->PtrListEnd == 0 && "List not terminated right!");
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes.
|
||||
AliasSet *Forward; // Forwarding pointer.
|
||||
|
||||
// All instructions without a specific address in this alias set.
|
||||
std::vector<AssertingVH<Instruction> > UnknownInsts;
|
||||
|
||||
// RefCount - Number of nodes pointing to this AliasSet plus the number of
|
||||
// AliasSets forwarding to it.
|
||||
unsigned RefCount : 28;
|
||||
|
||||
/// AccessType - Keep track of whether this alias set merely refers to the
|
||||
/// locations of memory, whether it modifies the memory, or whether it does
|
||||
/// both. The lattice goes from "NoModRef" to either Refs or Mods, then to
|
||||
/// ModRef as necessary.
|
||||
///
|
||||
enum AccessType {
|
||||
NoModRef = 0, Refs = 1, // Ref = bit 1
|
||||
Mods = 2, ModRef = 3 // Mod = bit 2
|
||||
};
|
||||
unsigned AccessTy : 2;
|
||||
|
||||
/// AliasType - Keep track the relationships between the pointers in the set.
|
||||
/// Lattice goes from MustAlias to MayAlias.
|
||||
///
|
||||
enum AliasType {
|
||||
MustAlias = 0, MayAlias = 1
|
||||
};
|
||||
unsigned AliasTy : 1;
|
||||
|
||||
// Volatile - True if this alias set contains volatile loads or stores.
|
||||
bool Volatile : 1;
|
||||
|
||||
void addRef() { ++RefCount; }
|
||||
void dropRef(AliasSetTracker &AST) {
|
||||
assert(RefCount >= 1 && "Invalid reference count detected!");
|
||||
if (--RefCount == 0)
|
||||
removeFromTracker(AST);
|
||||
}
|
||||
|
||||
Instruction *getUnknownInst(unsigned i) const {
|
||||
assert(i < UnknownInsts.size());
|
||||
return UnknownInsts[i];
|
||||
}
|
||||
|
||||
public:
|
||||
/// Accessors...
|
||||
bool isRef() const { return AccessTy & Refs; }
|
||||
bool isMod() const { return AccessTy & Mods; }
|
||||
bool isMustAlias() const { return AliasTy == MustAlias; }
|
||||
bool isMayAlias() const { return AliasTy == MayAlias; }
|
||||
|
||||
// isVolatile - Return true if this alias set contains volatile loads or
|
||||
// stores.
|
||||
bool isVolatile() const { return Volatile; }
|
||||
|
||||
/// isForwardingAliasSet - Return true if this alias set should be ignored as
|
||||
/// part of the AliasSetTracker object.
|
||||
bool isForwardingAliasSet() const { return Forward; }
|
||||
|
||||
/// mergeSetIn - Merge the specified alias set into this alias set...
|
||||
///
|
||||
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST);
|
||||
|
||||
// Alias Set iteration - Allow access to all of the pointer which are part of
|
||||
// this alias set...
|
||||
class iterator;
|
||||
iterator begin() const { return iterator(PtrList); }
|
||||
iterator end() const { return iterator(); }
|
||||
bool empty() const { return PtrList == 0; }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
/// Define an iterator for alias sets... this is just a forward iterator.
|
||||
class iterator : public std::iterator<std::forward_iterator_tag,
|
||||
PointerRec, ptrdiff_t> {
|
||||
PointerRec *CurNode;
|
||||
public:
|
||||
explicit iterator(PointerRec *CN = 0) : CurNode(CN) {}
|
||||
|
||||
bool operator==(const iterator& x) const {
|
||||
return CurNode == x.CurNode;
|
||||
}
|
||||
bool operator!=(const iterator& x) const { return !operator==(x); }
|
||||
|
||||
const iterator &operator=(const iterator &I) {
|
||||
CurNode = I.CurNode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type &operator*() const {
|
||||
assert(CurNode && "Dereferencing AliasSet.end()!");
|
||||
return *CurNode;
|
||||
}
|
||||
value_type *operator->() const { return &operator*(); }
|
||||
|
||||
Value *getPointer() const { return CurNode->getValue(); }
|
||||
uint64_t getSize() const { return CurNode->getSize(); }
|
||||
const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); }
|
||||
|
||||
iterator& operator++() { // Preincrement
|
||||
assert(CurNode && "Advancing past AliasSet.end()!");
|
||||
CurNode = CurNode->getNext();
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) { // Postincrement
|
||||
iterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// Can only be created by AliasSetTracker. Also, ilist creates one
|
||||
// to serve as a sentinel.
|
||||
friend struct ilist_sentinel_traits<AliasSet>;
|
||||
AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0),
|
||||
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
|
||||
}
|
||||
|
||||
AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION;
|
||||
|
||||
PointerRec *getSomePointer() const {
|
||||
return PtrList;
|
||||
}
|
||||
|
||||
/// getForwardedTarget - Return the real alias set this represents. If this
|
||||
/// has been merged with another set and is forwarding, return the ultimate
|
||||
/// destination set. This also implements the union-find collapsing as well.
|
||||
AliasSet *getForwardedTarget(AliasSetTracker &AST) {
|
||||
if (!Forward) return this;
|
||||
|
||||
AliasSet *Dest = Forward->getForwardedTarget(AST);
|
||||
if (Dest != Forward) {
|
||||
Dest->addRef();
|
||||
Forward->dropRef(AST);
|
||||
Forward = Dest;
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
void removeFromTracker(AliasSetTracker &AST);
|
||||
|
||||
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
|
||||
const MDNode *TBAAInfo,
|
||||
bool KnownMustAlias = false);
|
||||
void addUnknownInst(Instruction *I, AliasAnalysis &AA);
|
||||
void removeUnknownInst(Instruction *I) {
|
||||
for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i)
|
||||
if (UnknownInsts[i] == I) {
|
||||
UnknownInsts[i] = UnknownInsts.back();
|
||||
UnknownInsts.pop_back();
|
||||
--i; --e; // Revisit the moved entry.
|
||||
}
|
||||
}
|
||||
void setVolatile() { Volatile = true; }
|
||||
|
||||
public:
|
||||
/// aliasesPointer - Return true if the specified pointer "may" (or must)
|
||||
/// alias one of the members in the set.
|
||||
///
|
||||
bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
|
||||
AliasAnalysis &AA) const;
|
||||
bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
|
||||
};
|
||||
|
||||
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
|
||||
AS.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
||||
class AliasSetTracker {
|
||||
/// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be
|
||||
/// notified whenever a Value is deleted.
|
||||
class ASTCallbackVH : public CallbackVH {
|
||||
AliasSetTracker *AST;
|
||||
virtual void deleted();
|
||||
virtual void allUsesReplacedWith(Value *);
|
||||
public:
|
||||
ASTCallbackVH(Value *V, AliasSetTracker *AST = 0);
|
||||
ASTCallbackVH &operator=(Value *V);
|
||||
};
|
||||
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
|
||||
/// compare and hash the value handle.
|
||||
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {};
|
||||
|
||||
AliasAnalysis &AA;
|
||||
ilist<AliasSet> AliasSets;
|
||||
|
||||
typedef DenseMap<ASTCallbackVH, AliasSet::PointerRec*,
|
||||
ASTCallbackVHDenseMapInfo>
|
||||
PointerMapType;
|
||||
|
||||
// Map from pointers to their node
|
||||
PointerMapType PointerMap;
|
||||
|
||||
public:
|
||||
/// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
|
||||
/// the specified alias analysis object to disambiguate load and store
|
||||
/// addresses.
|
||||
explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {}
|
||||
~AliasSetTracker() { clear(); }
|
||||
|
||||
/// add methods - These methods are used to add different types of
|
||||
/// instructions to the alias sets. Adding a new instruction can result in
|
||||
/// one of three actions happening:
|
||||
///
|
||||
/// 1. If the instruction doesn't alias any other sets, create a new set.
|
||||
/// 2. If the instruction aliases exactly one set, add it to the set
|
||||
/// 3. If the instruction aliases multiple sets, merge the sets, and add
|
||||
/// the instruction to the result.
|
||||
///
|
||||
/// These methods return true if inserting the instruction resulted in the
|
||||
/// addition of a new alias set (i.e., the pointer did not alias anything).
|
||||
///
|
||||
bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location
|
||||
bool add(LoadInst *LI);
|
||||
bool add(StoreInst *SI);
|
||||
bool add(VAArgInst *VAAI);
|
||||
bool add(Instruction *I); // Dispatch to one of the other add methods...
|
||||
void add(BasicBlock &BB); // Add all instructions in basic block
|
||||
void add(const AliasSetTracker &AST); // Add alias relations from another AST
|
||||
bool addUnknown(Instruction *I);
|
||||
|
||||
/// remove methods - These methods are used to remove all entries that might
|
||||
/// be aliased by the specified instruction. These methods return true if any
|
||||
/// alias sets were eliminated.
|
||||
// Remove a location
|
||||
bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo);
|
||||
bool remove(LoadInst *LI);
|
||||
bool remove(StoreInst *SI);
|
||||
bool remove(VAArgInst *VAAI);
|
||||
bool remove(Instruction *I);
|
||||
void remove(AliasSet &AS);
|
||||
bool removeUnknown(Instruction *I);
|
||||
|
||||
void clear();
|
||||
|
||||
/// getAliasSets - Return the alias sets that are active.
|
||||
///
|
||||
const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
|
||||
|
||||
/// getAliasSetForPointer - Return the alias set that the specified pointer
|
||||
/// lives in. If the New argument is non-null, this method sets the value to
|
||||
/// true if a new alias set is created to contain the pointer (because the
|
||||
/// pointer didn't alias anything).
|
||||
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
|
||||
const MDNode *TBAAInfo,
|
||||
bool *New = 0);
|
||||
|
||||
/// getAliasSetForPointerIfExists - Return the alias set containing the
|
||||
/// location specified if one exists, otherwise return null.
|
||||
AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
|
||||
const MDNode *TBAAInfo) {
|
||||
return findAliasSetForPointer(P, Size, TBAAInfo);
|
||||
}
|
||||
|
||||
/// containsPointer - Return true if the specified location is represented by
|
||||
/// this alias set, false otherwise. This does not modify the AST object or
|
||||
/// alias sets.
|
||||
bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const;
|
||||
|
||||
/// getAliasAnalysis - Return the underlying alias analysis object used by
|
||||
/// this tracker.
|
||||
AliasAnalysis &getAliasAnalysis() const { return AA; }
|
||||
|
||||
/// deleteValue method - This method is used to remove a pointer value from
|
||||
/// the AliasSetTracker entirely. It should be used when an instruction is
|
||||
/// deleted from the program to update the AST. If you don't use this, you
|
||||
/// would have dangling pointers to deleted instructions.
|
||||
///
|
||||
void deleteValue(Value *PtrVal);
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in the
|
||||
/// program is copied or cloned, introducing a new value. Note that it is ok
|
||||
/// for clients that use this method to introduce the same value multiple
|
||||
/// times: if the tracker already knows about a value, it will ignore the
|
||||
/// request.
|
||||
///
|
||||
void copyValue(Value *From, Value *To);
|
||||
|
||||
|
||||
typedef ilist<AliasSet>::iterator iterator;
|
||||
typedef ilist<AliasSet>::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return AliasSets.begin(); }
|
||||
const_iterator end() const { return AliasSets.end(); }
|
||||
|
||||
iterator begin() { return AliasSets.begin(); }
|
||||
iterator end() { return AliasSets.end(); }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
friend class AliasSet;
|
||||
void removeAliasSet(AliasSet *AS);
|
||||
|
||||
// getEntryFor - Just like operator[] on the map, except that it creates an
|
||||
// entry for the pointer if it doesn't already exist.
|
||||
AliasSet::PointerRec &getEntryFor(Value *V) {
|
||||
AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)];
|
||||
if (Entry == 0)
|
||||
Entry = new AliasSet::PointerRec(V);
|
||||
return *Entry;
|
||||
}
|
||||
|
||||
AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo,
|
||||
AliasSet::AccessType E,
|
||||
bool &NewSet) {
|
||||
NewSet = false;
|
||||
AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet);
|
||||
AS.AccessTy |= E;
|
||||
return AS;
|
||||
}
|
||||
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
|
||||
const MDNode *TBAAInfo);
|
||||
|
||||
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
|
||||
};
|
||||
|
||||
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) {
|
||||
AST.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
342
thirdparty/clang/include/llvm/Analysis/BlockFrequencyImpl.h
vendored
Normal file
342
thirdparty/clang/include/llvm/Analysis/BlockFrequencyImpl.h
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Shared implementation of BlockFrequency for IR and Machine Instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
|
||||
#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/Support/BlockFrequency.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
class BlockFrequencyInfo;
|
||||
class MachineBlockFrequencyInfo;
|
||||
|
||||
/// BlockFrequencyImpl implements block frequency algorithm for IR and
|
||||
/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ)
|
||||
/// for the entry block and then propagates frequencies using branch weights
|
||||
/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because
|
||||
/// algorithm can find "backedges" by itself.
|
||||
template<class BlockT, class FunctionT, class BlockProbInfoT>
|
||||
class BlockFrequencyImpl {
|
||||
|
||||
DenseMap<const BlockT *, BlockFrequency> Freqs;
|
||||
|
||||
BlockProbInfoT *BPI;
|
||||
|
||||
FunctionT *Fn;
|
||||
|
||||
typedef GraphTraits< Inverse<BlockT *> > GT;
|
||||
|
||||
const uint32_t EntryFreq;
|
||||
|
||||
std::string getBlockName(BasicBlock *BB) const {
|
||||
return BB->getName().str();
|
||||
}
|
||||
|
||||
std::string getBlockName(MachineBasicBlock *MBB) const {
|
||||
std::string str;
|
||||
raw_string_ostream ss(str);
|
||||
ss << "BB#" << MBB->getNumber();
|
||||
|
||||
if (const BasicBlock *BB = MBB->getBasicBlock())
|
||||
ss << " derived from LLVM BB " << BB->getName();
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void setBlockFreq(BlockT *BB, BlockFrequency Freq) {
|
||||
Freqs[BB] = Freq;
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n");
|
||||
}
|
||||
|
||||
/// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst
|
||||
/// edge probability.
|
||||
BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const {
|
||||
BranchProbability Prob = BPI->getEdgeProbability(Src, Dst);
|
||||
return getBlockFreq(Src) * Prob;
|
||||
}
|
||||
|
||||
/// incBlockFreq - Increase BB block frequency by FREQ.
|
||||
///
|
||||
void incBlockFreq(BlockT *BB, BlockFrequency Freq) {
|
||||
Freqs[BB] += Freq;
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq
|
||||
<< " --> " << Freqs[BB] << "\n");
|
||||
}
|
||||
|
||||
/// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing.
|
||||
///
|
||||
void divBlockFreq(BlockT *BB, BranchProbability Prob) {
|
||||
uint64_t N = Prob.getNumerator();
|
||||
assert(N && "Illegal division by zero!");
|
||||
uint64_t D = Prob.getDenominator();
|
||||
uint64_t Freq = (Freqs[BB].getFrequency() * D) / N;
|
||||
|
||||
// Should we assert it?
|
||||
if (Freq > UINT32_MAX)
|
||||
Freq = UINT32_MAX;
|
||||
|
||||
Freqs[BB] = BlockFrequency(Freq);
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob
|
||||
<< ") --> " << Freqs[BB] << "\n");
|
||||
}
|
||||
|
||||
// All blocks in postorder.
|
||||
std::vector<BlockT *> POT;
|
||||
|
||||
// Map Block -> Position in reverse-postorder list.
|
||||
DenseMap<BlockT *, unsigned> RPO;
|
||||
|
||||
// Cycle Probability for each bloch.
|
||||
DenseMap<BlockT *, uint32_t> CycleProb;
|
||||
|
||||
// (reverse-)postorder traversal iterators.
|
||||
typedef typename std::vector<BlockT *>::iterator pot_iterator;
|
||||
typedef typename std::vector<BlockT *>::reverse_iterator rpot_iterator;
|
||||
|
||||
pot_iterator pot_begin() { return POT.begin(); }
|
||||
pot_iterator pot_end() { return POT.end(); }
|
||||
|
||||
rpot_iterator rpot_begin() { return POT.rbegin(); }
|
||||
rpot_iterator rpot_end() { return POT.rend(); }
|
||||
|
||||
rpot_iterator rpot_at(BlockT *BB) {
|
||||
rpot_iterator I = rpot_begin();
|
||||
unsigned idx = RPO[BB];
|
||||
assert(idx);
|
||||
std::advance(I, idx - 1);
|
||||
|
||||
assert(*I == BB);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
/// isReachable - Returns if BB block is reachable from the entry.
|
||||
///
|
||||
bool isReachable(BlockT *BB) {
|
||||
return RPO.count(BB);
|
||||
}
|
||||
|
||||
/// isBackedge - Return if edge Src -> Dst is a backedge.
|
||||
///
|
||||
bool isBackedge(BlockT *Src, BlockT *Dst) {
|
||||
assert(isReachable(Src));
|
||||
assert(isReachable(Dst));
|
||||
|
||||
unsigned a = RPO[Src];
|
||||
unsigned b = RPO[Dst];
|
||||
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
/// getSingleBlockPred - return single BB block predecessor or NULL if
|
||||
/// BB has none or more predecessors.
|
||||
BlockT *getSingleBlockPred(BlockT *BB) {
|
||||
typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
|
||||
if (PI == PE)
|
||||
return 0;
|
||||
|
||||
BlockT *Pred = *PI;
|
||||
|
||||
++PI;
|
||||
if (PI != PE)
|
||||
return 0;
|
||||
|
||||
return Pred;
|
||||
}
|
||||
|
||||
void doBlock(BlockT *BB, BlockT *LoopHead,
|
||||
SmallPtrSet<BlockT *, 8> &BlocksInLoop) {
|
||||
|
||||
DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n");
|
||||
setBlockFreq(BB, 0);
|
||||
|
||||
if (BB == LoopHead) {
|
||||
setBlockFreq(BB, EntryFreq);
|
||||
return;
|
||||
}
|
||||
|
||||
if(BlockT *Pred = getSingleBlockPred(BB)) {
|
||||
if (BlocksInLoop.count(Pred))
|
||||
setBlockFreq(BB, getEdgeFreq(Pred, BB));
|
||||
// TODO: else? irreducible, ignore it for now.
|
||||
return;
|
||||
}
|
||||
|
||||
bool isInLoop = false;
|
||||
bool isLoopHead = false;
|
||||
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *Pred = *PI;
|
||||
|
||||
if (isReachable(Pred) && isBackedge(Pred, BB)) {
|
||||
isLoopHead = true;
|
||||
} else if (BlocksInLoop.count(Pred)) {
|
||||
incBlockFreq(BB, getEdgeFreq(Pred, BB));
|
||||
isInLoop = true;
|
||||
}
|
||||
// TODO: else? irreducible.
|
||||
}
|
||||
|
||||
if (!isInLoop)
|
||||
return;
|
||||
|
||||
if (!isLoopHead)
|
||||
return;
|
||||
|
||||
assert(EntryFreq >= CycleProb[BB]);
|
||||
uint32_t CProb = CycleProb[BB];
|
||||
uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1;
|
||||
divBlockFreq(BB, BranchProbability(Numerator, EntryFreq));
|
||||
}
|
||||
|
||||
/// doLoop - Propagate block frequency down through the loop.
|
||||
void doLoop(BlockT *Head, BlockT *Tail) {
|
||||
DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", "
|
||||
<< getBlockName(Tail) << ")\n");
|
||||
|
||||
SmallPtrSet<BlockT *, 8> BlocksInLoop;
|
||||
|
||||
for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) {
|
||||
BlockT *BB = *I;
|
||||
doBlock(BB, Head, BlocksInLoop);
|
||||
|
||||
BlocksInLoop.insert(BB);
|
||||
if (I == E)
|
||||
break;
|
||||
}
|
||||
|
||||
// Compute loop's cyclic probability using backedges probabilities.
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(Head);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *Pred = *PI;
|
||||
assert(Pred);
|
||||
if (isReachable(Pred) && isBackedge(Pred, Head)) {
|
||||
uint64_t N = getEdgeFreq(Pred, Head).getFrequency();
|
||||
uint64_t D = getBlockFreq(Head).getFrequency();
|
||||
assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!");
|
||||
uint64_t Res = (N * EntryFreq) / D;
|
||||
|
||||
assert(Res <= UINT32_MAX);
|
||||
CycleProb[Head] += (uint32_t) Res;
|
||||
DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res
|
||||
<< " --> " << CycleProb[Head] << "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend class BlockFrequencyInfo;
|
||||
friend class MachineBlockFrequencyInfo;
|
||||
|
||||
BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { }
|
||||
|
||||
void doFunction(FunctionT *fn, BlockProbInfoT *bpi) {
|
||||
Fn = fn;
|
||||
BPI = bpi;
|
||||
|
||||
// Clear everything.
|
||||
RPO.clear();
|
||||
POT.clear();
|
||||
CycleProb.clear();
|
||||
Freqs.clear();
|
||||
|
||||
BlockT *EntryBlock = fn->begin();
|
||||
|
||||
std::copy(po_begin(EntryBlock), po_end(EntryBlock), std::back_inserter(POT));
|
||||
|
||||
unsigned RPOidx = 0;
|
||||
for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
|
||||
BlockT *BB = *I;
|
||||
RPO[BB] = ++RPOidx;
|
||||
DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n");
|
||||
}
|
||||
|
||||
// Travel over all blocks in postorder.
|
||||
for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) {
|
||||
BlockT *BB = *I;
|
||||
BlockT *LastTail = 0;
|
||||
DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n");
|
||||
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
|
||||
BlockT *Pred = *PI;
|
||||
if (isReachable(Pred) && isBackedge(Pred, BB)
|
||||
&& (!LastTail || RPO[Pred] > RPO[LastTail]))
|
||||
LastTail = Pred;
|
||||
}
|
||||
|
||||
if (LastTail)
|
||||
doLoop(BB, LastTail);
|
||||
}
|
||||
|
||||
// At the end assume the whole function as a loop, and travel over it once
|
||||
// again.
|
||||
doLoop(*(rpot_begin()), *(pot_begin()));
|
||||
}
|
||||
|
||||
public:
|
||||
/// getBlockFreq - Return block frequency. Return 0 if we don't have it.
|
||||
BlockFrequency getBlockFreq(const BlockT *BB) const {
|
||||
typename DenseMap<const BlockT *, BlockFrequency>::const_iterator
|
||||
I = Freqs.find(BB);
|
||||
if (I != Freqs.end())
|
||||
return I->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS) const {
|
||||
OS << "\n\n---- Block Freqs ----\n";
|
||||
for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) {
|
||||
BlockT *BB = I++;
|
||||
OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n";
|
||||
|
||||
for (typename GraphTraits<BlockT *>::ChildIteratorType
|
||||
SI = GraphTraits<BlockT *>::child_begin(BB),
|
||||
SE = GraphTraits<BlockT *>::child_end(BB); SI != SE; ++SI) {
|
||||
BlockT *Succ = *SI;
|
||||
OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ)
|
||||
<< " = " << getEdgeFreq(BB, Succ) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump() const {
|
||||
print(dbgs());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
55
thirdparty/clang/include/llvm/Analysis/BlockFrequencyInfo.h
vendored
Normal file
55
thirdparty/clang/include/llvm/Analysis/BlockFrequencyInfo.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Loops should be simplified before this analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
|
||||
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/BlockFrequency.h"
|
||||
#include <climits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BranchProbabilityInfo;
|
||||
template<class BlockT, class FunctionT, class BranchProbInfoT>
|
||||
class BlockFrequencyImpl;
|
||||
|
||||
/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
|
||||
/// IR basic block frequencies.
|
||||
class BlockFrequencyInfo : public FunctionPass {
|
||||
|
||||
BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BlockFrequencyInfo();
|
||||
|
||||
~BlockFrequencyInfo();
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
void print(raw_ostream &O, const Module *M) const;
|
||||
|
||||
/// getblockFreq - Return block frequency. Return 0 if we don't have the
|
||||
/// information. Please note that initial frequency is equal to 1024. It means
|
||||
/// that we should not rely on the value itself, but only on the comparison to
|
||||
/// the other block frequencies. We do this to avoid using of floating points.
|
||||
///
|
||||
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
148
thirdparty/clang/include/llvm/Analysis/BranchProbabilityInfo.h
vendored
Normal file
148
thirdparty/clang/include/llvm/Analysis/BranchProbabilityInfo.h
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
//===--- BranchProbabilityInfo.h - Branch Probability Analysis --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass is used to evaluate branch probabilties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
|
||||
#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
|
||||
namespace llvm {
|
||||
class LoopInfo;
|
||||
class raw_ostream;
|
||||
|
||||
/// \brief Analysis pass providing branch probability information.
|
||||
///
|
||||
/// This is a function analysis pass which provides information on the relative
|
||||
/// probabilities of each "edge" in the function's CFG where such an edge is
|
||||
/// defined by a pair (PredBlock and an index in the successors). The
|
||||
/// probability of an edge from one block is always relative to the
|
||||
/// probabilities of other edges from the block. The probabilites of all edges
|
||||
/// from a block sum to exactly one (100%).
|
||||
/// We use a pair (PredBlock and an index in the successors) to uniquely
|
||||
/// identify an edge, since we can have multiple edges from Src to Dst.
|
||||
/// As an example, we can have a switch which jumps to Dst with value 0 and
|
||||
/// value 10.
|
||||
class BranchProbabilityInfo : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BranchProbabilityInfo() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
bool runOnFunction(Function &F);
|
||||
void print(raw_ostream &OS, const Module *M = 0) const;
|
||||
|
||||
/// \brief Get an edge's probability, relative to other out-edges of the Src.
|
||||
///
|
||||
/// This routine provides access to the fractional probability between zero
|
||||
/// (0%) and one (100%) of this edge executing, relative to other edges
|
||||
/// leaving the 'Src' block. The returned probability is never zero, and can
|
||||
/// only be one if the source block has only one successor.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
unsigned IndexInSuccessors) const;
|
||||
|
||||
/// \brief Get the probability of going from Src to Dst.
|
||||
///
|
||||
/// It returns the sum of all probabilities for edges from Src to Dst.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Test if an edge is hot relative to other out-edges of the Src.
|
||||
///
|
||||
/// Check whether this edge out of the source block is 'hot'. We define hot
|
||||
/// as having a relative probability >= 80%.
|
||||
bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Retrieve the hot successor of a block if one exists.
|
||||
///
|
||||
/// Given a basic block, look through its successors and if one exists for
|
||||
/// which \see isEdgeHot would return true, return that successor block.
|
||||
BasicBlock *getHotSucc(BasicBlock *BB) const;
|
||||
|
||||
/// \brief Print an edge's probability.
|
||||
///
|
||||
/// Retrieves an edge's probability similarly to \see getEdgeProbability, but
|
||||
/// then prints that probability to the provided stream. That stream is then
|
||||
/// returned.
|
||||
raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Get the raw edge weight calculated for the edge.
|
||||
///
|
||||
/// This returns the raw edge weight. It is guaranteed to fall between 1 and
|
||||
/// UINT32_MAX. Note that the raw edge weight is not meaningful in isolation.
|
||||
/// This interface should be very carefully, and primarily by routines that
|
||||
/// are updating the analysis by later calling setEdgeWeight.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src,
|
||||
unsigned IndexInSuccessors) const;
|
||||
|
||||
/// \brief Get the raw edge weight calculated for the block pair.
|
||||
///
|
||||
/// This returns the sum of all raw edge weights from Src to Dst.
|
||||
/// It is guaranteed to fall between 1 and UINT32_MAX.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Set the raw edge weight for a given edge.
|
||||
///
|
||||
/// This allows a pass to explicitly set the edge weight for an edge. It can
|
||||
/// be used when updating the CFG to update and preserve the branch
|
||||
/// probability information. Read the implementation of how these edge
|
||||
/// weights are calculated carefully before using!
|
||||
void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors,
|
||||
uint32_t Weight);
|
||||
|
||||
private:
|
||||
// Since we allow duplicate edges from one basic block to another, we use
|
||||
// a pair (PredBlock and an index in the successors) to specify an edge.
|
||||
typedef std::pair<const BasicBlock *, unsigned> Edge;
|
||||
|
||||
// Default weight value. Used when we don't have information about the edge.
|
||||
// TODO: DEFAULT_WEIGHT makes sense during static predication, when none of
|
||||
// the successors have a weight yet. But it doesn't make sense when providing
|
||||
// weight to an edge that may have siblings with non-zero weights. This can
|
||||
// be handled various ways, but it's probably fine for an edge with unknown
|
||||
// weight to just "inherit" the non-zero weight of an adjacent successor.
|
||||
static const uint32_t DEFAULT_WEIGHT = 16;
|
||||
|
||||
DenseMap<Edge, uint32_t> Weights;
|
||||
|
||||
/// \brief Handle to the LoopInfo analysis.
|
||||
LoopInfo *LI;
|
||||
|
||||
/// \brief Track the last function we run over for printing.
|
||||
Function *LastF;
|
||||
|
||||
/// \brief Track the set of blocks directly succeeded by a returning block.
|
||||
SmallPtrSet<BasicBlock *, 16> PostDominatedByUnreachable;
|
||||
|
||||
/// \brief Get sum of the block successors' weights.
|
||||
uint32_t getSumForBlock(const BasicBlock *BB) const;
|
||||
|
||||
bool calcUnreachableHeuristics(BasicBlock *BB);
|
||||
bool calcMetadataWeights(BasicBlock *BB);
|
||||
bool calcPointerHeuristics(BasicBlock *BB);
|
||||
bool calcLoopBranchHeuristics(BasicBlock *BB);
|
||||
bool calcZeroHeuristics(BasicBlock *BB);
|
||||
bool calcFloatingPointHeuristics(BasicBlock *BB);
|
||||
bool calcInvokeHeuristics(BasicBlock *BB);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
114
thirdparty/clang/include/llvm/Analysis/CFGPrinter.h
vendored
Normal file
114
thirdparty/clang/include/llvm/Analysis/CFGPrinter.h
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines external functions that can be called to explicitly
|
||||
// instantiate the CFG printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CFGPRINTER_H
|
||||
#define LLVM_ANALYSIS_CFGPRINTER_H
|
||||
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
|
||||
namespace llvm {
|
||||
template<>
|
||||
struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
||||
|
||||
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
static std::string getGraphName(const Function *F) {
|
||||
return "CFG for '" + F->getName().str() + "' function";
|
||||
}
|
||||
|
||||
static std::string getSimpleNodeLabel(const BasicBlock *Node,
|
||||
const Function *) {
|
||||
if (!Node->getName().empty())
|
||||
return Node->getName().str();
|
||||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
WriteAsOperand(OS, Node, false);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
static std::string getCompleteNodeLabel(const BasicBlock *Node,
|
||||
const Function *) {
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
if (Node->getName().empty()) {
|
||||
WriteAsOperand(OS, Node, false);
|
||||
OS << ":";
|
||||
}
|
||||
|
||||
OS << *Node;
|
||||
std::string OutStr = OS.str();
|
||||
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
|
||||
|
||||
// Process string output to make it nicer...
|
||||
for (unsigned i = 0; i != OutStr.length(); ++i)
|
||||
if (OutStr[i] == '\n') { // Left justify
|
||||
OutStr[i] = '\\';
|
||||
OutStr.insert(OutStr.begin()+i+1, 'l');
|
||||
} else if (OutStr[i] == ';') { // Delete comments!
|
||||
unsigned Idx = OutStr.find('\n', i+1); // Find end of line
|
||||
OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
|
||||
--i;
|
||||
}
|
||||
|
||||
return OutStr;
|
||||
}
|
||||
|
||||
std::string getNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
if (isSimple())
|
||||
return getSimpleNodeLabel(Node, Graph);
|
||||
else
|
||||
return getCompleteNodeLabel(Node, Graph);
|
||||
}
|
||||
|
||||
static std::string getEdgeSourceLabel(const BasicBlock *Node,
|
||||
succ_const_iterator I) {
|
||||
// Label source of conditional branches with "T" or "F"
|
||||
if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
|
||||
if (BI->isConditional())
|
||||
return (I == succ_begin(Node)) ? "T" : "F";
|
||||
|
||||
// Label source of switch edges with the associated value.
|
||||
if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
|
||||
unsigned SuccNo = I.getSuccessorIndex();
|
||||
|
||||
if (SuccNo == 0) return "def";
|
||||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
SwitchInst::ConstCaseIt Case =
|
||||
SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
|
||||
OS << Case.getCaseValue()->getValue();
|
||||
return OS.str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
FunctionPass *createCFGPrinterPass ();
|
||||
FunctionPass *createCFGOnlyPrinterPass ();
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
378
thirdparty/clang/include/llvm/Analysis/CallGraph.h
vendored
Normal file
378
thirdparty/clang/include/llvm/Analysis/CallGraph.h
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This interface is used to build and manipulate a call graph, which is a very
|
||||
// useful tool for interprocedural optimization.
|
||||
//
|
||||
// Every function in a module is represented as a node in the call graph. The
|
||||
// callgraph node keeps track of which functions the are called by the function
|
||||
// corresponding to the node.
|
||||
//
|
||||
// A call graph may contain nodes where the function that they correspond to is
|
||||
// null. These 'external' nodes are used to represent control flow that is not
|
||||
// represented (or analyzable) in the module. In particular, this analysis
|
||||
// builds one external node such that:
|
||||
// 1. All functions in the module without internal linkage will have edges
|
||||
// from this external node, indicating that they could be called by
|
||||
// functions outside of the module.
|
||||
// 2. All functions whose address is used for something more than a direct
|
||||
// call, for example being stored into a memory location will also have an
|
||||
// edge from this external node. Since they may be called by an unknown
|
||||
// caller later, they must be tracked as such.
|
||||
//
|
||||
// There is a second external node added for calls that leave this module.
|
||||
// Functions have a call edge to the external node iff:
|
||||
// 1. The function is external, reflecting the fact that they could call
|
||||
// anything without internal linkage or that has its address taken.
|
||||
// 2. The function contains an indirect function call.
|
||||
//
|
||||
// As an extension in the future, there may be multiple nodes with a null
|
||||
// function. These will be used when we can prove (through pointer analysis)
|
||||
// that an indirect call site can call only a specific set of functions.
|
||||
//
|
||||
// Because of these properties, the CallGraph captures a conservative superset
|
||||
// of all of the caller-callee relationships, which is useful for
|
||||
// transformations.
|
||||
//
|
||||
// The CallGraph class also attempts to figure out what the root of the
|
||||
// CallGraph is, which it currently does by looking for a function named 'main'.
|
||||
// If no function named 'main' is found, the external node is used as the entry
|
||||
// node, reflecting the fact that any function without internal linkage could
|
||||
// be called into (which is common for libraries).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLGRAPH_H
|
||||
#define LLVM_ANALYSIS_CALLGRAPH_H
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include "llvm/Support/IncludeFile.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
class CallGraphNode;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallGraph class definition
|
||||
//
|
||||
class CallGraph {
|
||||
protected:
|
||||
Module *Mod; // The module this call graph represents
|
||||
|
||||
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
|
||||
FunctionMapTy FunctionMap; // Map from a function to its node
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
//===---------------------------------------------------------------------
|
||||
// Accessors.
|
||||
//
|
||||
typedef FunctionMapTy::iterator iterator;
|
||||
typedef FunctionMapTy::const_iterator const_iterator;
|
||||
|
||||
/// getModule - Return the module the call graph corresponds to.
|
||||
///
|
||||
Module &getModule() const { return *Mod; }
|
||||
|
||||
inline iterator begin() { return FunctionMap.begin(); }
|
||||
inline iterator end() { return FunctionMap.end(); }
|
||||
inline const_iterator begin() const { return FunctionMap.begin(); }
|
||||
inline const_iterator end() const { return FunctionMap.end(); }
|
||||
|
||||
// Subscripting operators, return the call graph node for the provided
|
||||
// function
|
||||
inline const CallGraphNode *operator[](const Function *F) const {
|
||||
const_iterator I = FunctionMap.find(F);
|
||||
assert(I != FunctionMap.end() && "Function not in callgraph!");
|
||||
return I->second;
|
||||
}
|
||||
inline CallGraphNode *operator[](const Function *F) {
|
||||
const_iterator I = FunctionMap.find(F);
|
||||
assert(I != FunctionMap.end() && "Function not in callgraph!");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// Returns the CallGraphNode which is used to represent undetermined calls
|
||||
/// into the callgraph. Override this if you want behavioral inheritance.
|
||||
virtual CallGraphNode* getExternalCallingNode() const { return 0; }
|
||||
virtual CallGraphNode* getCallsExternalNode() const { return 0; }
|
||||
|
||||
/// Return the root/main method in the module, or some other root node, such
|
||||
/// as the externalcallingnode. Overload these if you behavioral
|
||||
/// inheritance.
|
||||
virtual CallGraphNode* getRoot() { return 0; }
|
||||
virtual const CallGraphNode* getRoot() const { return 0; }
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Functions to keep a call graph up to date with a function that has been
|
||||
// modified.
|
||||
//
|
||||
|
||||
/// removeFunctionFromModule - Unlink the function from this module, returning
|
||||
/// it. Because this removes the function from the module, the call graph
|
||||
/// node is destroyed. This is only valid if the function does not call any
|
||||
/// other functions (ie, there are no edges in it's CGN). The easiest way to
|
||||
/// do this is to dropAllReferences before calling this.
|
||||
///
|
||||
Function *removeFunctionFromModule(CallGraphNode *CGN);
|
||||
Function *removeFunctionFromModule(Function *F) {
|
||||
return removeFunctionFromModule((*this)[F]);
|
||||
}
|
||||
|
||||
/// getOrInsertFunction - This method is identical to calling operator[], but
|
||||
/// it will insert a new CallGraphNode for the specified function if one does
|
||||
/// not already exist.
|
||||
CallGraphNode *getOrInsertFunction(const Function *F);
|
||||
|
||||
/// spliceFunction - Replace the function represented by this node by another.
|
||||
/// This does not rescan the body of the function, so it is suitable when
|
||||
/// splicing the body of one function to another while also updating all
|
||||
/// callers from the old function to the new.
|
||||
///
|
||||
void spliceFunction(const Function *From, const Function *To);
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Pass infrastructure interface glue code.
|
||||
//
|
||||
protected:
|
||||
CallGraph() {}
|
||||
|
||||
public:
|
||||
virtual ~CallGraph() { destroy(); }
|
||||
|
||||
/// initialize - Call this method before calling other methods,
|
||||
/// re/initializes the state of the CallGraph.
|
||||
///
|
||||
void initialize(Module &M);
|
||||
|
||||
void print(raw_ostream &o, Module *) const;
|
||||
void dump() const;
|
||||
protected:
|
||||
// destroy - Release memory for the call graph
|
||||
virtual void destroy();
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallGraphNode class definition.
|
||||
//
|
||||
class CallGraphNode {
|
||||
friend class CallGraph;
|
||||
|
||||
AssertingVH<Function> F;
|
||||
|
||||
// CallRecord - This is a pair of the calling instruction (a call or invoke)
|
||||
// and the callgraph node being called.
|
||||
public:
|
||||
typedef std::pair<WeakVH, CallGraphNode*> CallRecord;
|
||||
private:
|
||||
std::vector<CallRecord> CalledFunctions;
|
||||
|
||||
/// NumReferences - This is the number of times that this CallGraphNode occurs
|
||||
/// in the CalledFunctions array of this or other CallGraphNodes.
|
||||
unsigned NumReferences;
|
||||
|
||||
CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
void DropRef() { --NumReferences; }
|
||||
void AddRef() { ++NumReferences; }
|
||||
public:
|
||||
typedef std::vector<CallRecord> CalledFunctionsVector;
|
||||
|
||||
|
||||
// CallGraphNode ctor - Create a node for the specified function.
|
||||
inline CallGraphNode(Function *f) : F(f), NumReferences(0) {}
|
||||
~CallGraphNode() {
|
||||
assert(NumReferences == 0 && "Node deleted while references remain");
|
||||
}
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Accessor methods.
|
||||
//
|
||||
|
||||
typedef std::vector<CallRecord>::iterator iterator;
|
||||
typedef std::vector<CallRecord>::const_iterator const_iterator;
|
||||
|
||||
// getFunction - Return the function that this call graph node represents.
|
||||
Function *getFunction() const { return F; }
|
||||
|
||||
inline iterator begin() { return CalledFunctions.begin(); }
|
||||
inline iterator end() { return CalledFunctions.end(); }
|
||||
inline const_iterator begin() const { return CalledFunctions.begin(); }
|
||||
inline const_iterator end() const { return CalledFunctions.end(); }
|
||||
inline bool empty() const { return CalledFunctions.empty(); }
|
||||
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
|
||||
|
||||
/// getNumReferences - Return the number of other CallGraphNodes in this
|
||||
/// CallGraph that reference this node in their callee list.
|
||||
unsigned getNumReferences() const { return NumReferences; }
|
||||
|
||||
// Subscripting operator - Return the i'th called function.
|
||||
//
|
||||
CallGraphNode *operator[](unsigned i) const {
|
||||
assert(i < CalledFunctions.size() && "Invalid index");
|
||||
return CalledFunctions[i].second;
|
||||
}
|
||||
|
||||
/// dump - Print out this call graph node.
|
||||
///
|
||||
void dump() const;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Methods to keep a call graph up to date with a function that has been
|
||||
// modified
|
||||
//
|
||||
|
||||
/// removeAllCalledFunctions - As the name implies, this removes all edges
|
||||
/// from this CallGraphNode to any functions it calls.
|
||||
void removeAllCalledFunctions() {
|
||||
while (!CalledFunctions.empty()) {
|
||||
CalledFunctions.back().second->DropRef();
|
||||
CalledFunctions.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// stealCalledFunctionsFrom - Move all the callee information from N to this
|
||||
/// node.
|
||||
void stealCalledFunctionsFrom(CallGraphNode *N) {
|
||||
assert(CalledFunctions.empty() &&
|
||||
"Cannot steal callsite information if I already have some");
|
||||
std::swap(CalledFunctions, N->CalledFunctions);
|
||||
}
|
||||
|
||||
|
||||
/// addCalledFunction - Add a function to the list of functions called by this
|
||||
/// one.
|
||||
void addCalledFunction(CallSite CS, CallGraphNode *M) {
|
||||
assert(!CS.getInstruction() ||
|
||||
!CS.getCalledFunction() ||
|
||||
!CS.getCalledFunction()->isIntrinsic());
|
||||
CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M));
|
||||
M->AddRef();
|
||||
}
|
||||
|
||||
void removeCallEdge(iterator I) {
|
||||
I->second->DropRef();
|
||||
*I = CalledFunctions.back();
|
||||
CalledFunctions.pop_back();
|
||||
}
|
||||
|
||||
|
||||
/// removeCallEdgeFor - This method removes the edge in the node for the
|
||||
/// specified call site. Note that this method takes linear time, so it
|
||||
/// should be used sparingly.
|
||||
void removeCallEdgeFor(CallSite CS);
|
||||
|
||||
/// removeAnyCallEdgeTo - This method removes all call edges from this node
|
||||
/// to the specified callee function. This takes more time to execute than
|
||||
/// removeCallEdgeTo, so it should not be used unless necessary.
|
||||
void removeAnyCallEdgeTo(CallGraphNode *Callee);
|
||||
|
||||
/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
|
||||
/// from this node to the specified callee function.
|
||||
void removeOneAbstractEdgeTo(CallGraphNode *Callee);
|
||||
|
||||
/// replaceCallEdge - This method replaces the edge in the node for the
|
||||
/// specified call site with a new one. Note that this method takes linear
|
||||
/// time, so it should be used sparingly.
|
||||
void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode);
|
||||
|
||||
/// allReferencesDropped - This is a special function that should only be
|
||||
/// used by the CallGraph class.
|
||||
void allReferencesDropped() {
|
||||
NumReferences = 0;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GraphTraits specializations for call graphs so that they can be treated as
|
||||
// graphs by the generic graph algorithms.
|
||||
//
|
||||
|
||||
// Provide graph traits for tranversing call graphs using standard graph
|
||||
// traversals.
|
||||
template <> struct GraphTraits<CallGraphNode*> {
|
||||
typedef CallGraphNode NodeType;
|
||||
|
||||
typedef CallGraphNode::CallRecord CGNPairTy;
|
||||
typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun;
|
||||
|
||||
static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; }
|
||||
|
||||
typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
static inline ChildIteratorType child_end (NodeType *N) {
|
||||
return map_iterator(N->end(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
|
||||
static CallGraphNode *CGNDeref(CGNPairTy P) {
|
||||
return P.second;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<const CallGraphNode*> {
|
||||
typedef const CallGraphNode NodeType;
|
||||
typedef NodeType::const_iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
|
||||
static inline ChildIteratorType child_end (NodeType *N) { return N->end(); }
|
||||
};
|
||||
|
||||
template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {
|
||||
static NodeType *getEntryNode(CallGraph *CGN) {
|
||||
return CGN->getExternalCallingNode(); // Start at the external node!
|
||||
}
|
||||
typedef std::pair<const Function*, CallGraphNode*> PairTy;
|
||||
typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun;
|
||||
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef mapped_iterator<CallGraph::iterator, DerefFun> nodes_iterator;
|
||||
static nodes_iterator nodes_begin(CallGraph *CG) {
|
||||
return map_iterator(CG->begin(), DerefFun(CGdereference));
|
||||
}
|
||||
static nodes_iterator nodes_end (CallGraph *CG) {
|
||||
return map_iterator(CG->end(), DerefFun(CGdereference));
|
||||
}
|
||||
|
||||
static CallGraphNode &CGdereference(PairTy P) {
|
||||
return *P.second;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GraphTraits<const CallGraph*> :
|
||||
public GraphTraits<const CallGraphNode*> {
|
||||
static NodeType *getEntryNode(const CallGraph *CGN) {
|
||||
return CGN->getExternalCallingNode();
|
||||
}
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef CallGraph::const_iterator nodes_iterator;
|
||||
static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); }
|
||||
static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); }
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// Make sure that any clients of this file link in CallGraph.cpp
|
||||
FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph)
|
||||
|
||||
#endif
|
||||
107
thirdparty/clang/include/llvm/Analysis/CallGraphSCCPass.h
vendored
Normal file
107
thirdparty/clang/include/llvm/Analysis/CallGraphSCCPass.h
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- 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 CallGraphSCCPass class, which is used for passes which
|
||||
// are implemented as bottom-up traversals on the call graph. Because there may
|
||||
// be cycles in the call graph, passes of this type operate on the call-graph in
|
||||
// SCC order: that is, they process function bottom-up, except for recursive
|
||||
// functions, which they process all at once.
|
||||
//
|
||||
// These passes are inherently interprocedural, and are required to keep the
|
||||
// call graph up-to-date if they do anything which could modify it.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLGRAPHSCCPASS_H
|
||||
#define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H
|
||||
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CallGraphNode;
|
||||
class CallGraph;
|
||||
class PMStack;
|
||||
class CallGraphSCC;
|
||||
|
||||
class CallGraphSCCPass : public Pass {
|
||||
public:
|
||||
explicit CallGraphSCCPass(char &pid) : Pass(PT_CallGraphSCC, pid) {}
|
||||
|
||||
/// createPrinterPass - Get a pass that prints the Module
|
||||
/// corresponding to a CallGraph.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
using llvm::Pass::doInitialization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
/// doInitialization - This method is called before the SCC's of the program
|
||||
/// has been processed, allowing the pass to do initialization as necessary.
|
||||
virtual bool doInitialization(CallGraph &CG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// runOnSCC - This method should be implemented by the subclass to perform
|
||||
/// whatever action is necessary for the specified SCC. Note that
|
||||
/// non-recursive (or only self-recursive) functions will have an SCC size of
|
||||
/// 1, where recursive portions of the call graph will have SCC size > 1.
|
||||
///
|
||||
/// SCC passes that add or delete functions to the SCC are required to update
|
||||
/// the SCC list, otherwise stale pointers may be dereferenced.
|
||||
///
|
||||
virtual bool runOnSCC(CallGraphSCC &SCC) = 0;
|
||||
|
||||
/// doFinalization - This method is called after the SCC's of the program has
|
||||
/// been processed, allowing the pass to do final cleanup as necessary.
|
||||
virtual bool doFinalization(CallGraph &CG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Assign pass manager to manager this pass
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_CallGraphPassManager;
|
||||
}
|
||||
|
||||
/// getAnalysisUsage - For this class, we declare that we require and preserve
|
||||
/// the call graph. If the derived class implements this method, it should
|
||||
/// always explicitly call the implementation here.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||
};
|
||||
|
||||
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
|
||||
class CallGraphSCC {
|
||||
void *Context; // The CGPassManager object that is vending this.
|
||||
std::vector<CallGraphNode*> Nodes;
|
||||
public:
|
||||
CallGraphSCC(void *context) : Context(context) {}
|
||||
|
||||
void initialize(CallGraphNode*const*I, CallGraphNode*const*E) {
|
||||
Nodes.assign(I, E);
|
||||
}
|
||||
|
||||
bool isSingular() const { return Nodes.size() == 1; }
|
||||
unsigned size() const { return Nodes.size(); }
|
||||
|
||||
/// ReplaceNode - This informs the SCC and the pass manager that the specified
|
||||
/// Old node has been deleted, and New is to be used in its place.
|
||||
void ReplaceNode(CallGraphNode *Old, CallGraphNode *New);
|
||||
|
||||
typedef std::vector<CallGraphNode*>::const_iterator iterator;
|
||||
iterator begin() const { return Nodes.begin(); }
|
||||
iterator end() const { return Nodes.end(); }
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
27
thirdparty/clang/include/llvm/Analysis/CallPrinter.h
vendored
Normal file
27
thirdparty/clang/include/llvm/Analysis/CallPrinter.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- CallPrinter.h - Call graph printer external interface ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines external functions that can be called to explicitly
|
||||
// instantiate the call graph printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLPRINTER_H
|
||||
#define LLVM_ANALYSIS_CALLPRINTER_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ModulePass;
|
||||
|
||||
ModulePass *createCallGraphViewerPass();
|
||||
ModulePass *createCallGraphPrinterPass();
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
62
thirdparty/clang/include/llvm/Analysis/CaptureTracking.h
vendored
Normal file
62
thirdparty/clang/include/llvm/Analysis/CaptureTracking.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
//===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- 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 routines that help determine which pointers are captured.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
#define LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
class Use;
|
||||
|
||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
/// be expensive, so consider caching the results. The boolean ReturnCaptures
|
||||
/// specifies whether returning the value (or part of it) from the function
|
||||
/// counts as capturing it or not. The boolean StoreCaptures specified
|
||||
/// whether storing the value (or part of it) into memory anywhere
|
||||
/// automatically counts as capturing it or not.
|
||||
bool PointerMayBeCaptured(const Value *V,
|
||||
bool ReturnCaptures,
|
||||
bool StoreCaptures);
|
||||
|
||||
/// This callback is used in conjunction with PointerMayBeCaptured. In
|
||||
/// addition to the interface here, you'll need to provide your own getters
|
||||
/// to see whether anything was captured.
|
||||
struct CaptureTracker {
|
||||
virtual ~CaptureTracker();
|
||||
|
||||
/// tooManyUses - The depth of traversal has breached a limit. There may be
|
||||
/// capturing instructions that will not be passed into captured().
|
||||
virtual void tooManyUses() = 0;
|
||||
|
||||
/// shouldExplore - This is the use of a value derived from the pointer.
|
||||
/// To prune the search (ie., assume that none of its users could possibly
|
||||
/// capture) return false. To search it, return true.
|
||||
///
|
||||
/// U->getUser() is always an Instruction.
|
||||
virtual bool shouldExplore(Use *U);
|
||||
|
||||
/// captured - Information about the pointer was captured by the user of
|
||||
/// use U. Return true to stop the traversal or false to continue looking
|
||||
/// for more capturing instructions.
|
||||
virtual bool captured(Use *U) = 0;
|
||||
};
|
||||
|
||||
/// PointerMayBeCaptured - Visit the value and the values derived from it and
|
||||
/// find values which appear to be capturing the pointer value. This feeds
|
||||
/// results into and is controlled by the CaptureTracker object.
|
||||
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
93
thirdparty/clang/include/llvm/Analysis/CodeMetrics.h
vendored
Normal file
93
thirdparty/clang/include/llvm/Analysis/CodeMetrics.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
//===- CodeMetrics.h - Code cost measurements -------------------*- 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 various weight measurements for code, helping
|
||||
// the Inliner and other passes decide whether to duplicate its contents.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CODEMETRICS_H
|
||||
#define LLVM_ANALYSIS_CODEMETRICS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class TargetTransformInfo;
|
||||
class Value;
|
||||
|
||||
/// \brief Check whether a call will lower to something small.
|
||||
///
|
||||
/// This tests checks whether this callsite will lower to something
|
||||
/// significantly cheaper than a traditional call, often a single
|
||||
/// instruction. Note that if isInstructionFree(CS.getInstruction()) would
|
||||
/// return true, so will this function.
|
||||
bool callIsSmall(ImmutableCallSite CS);
|
||||
|
||||
/// \brief Utility to calculate the size and a few similar metrics for a set
|
||||
/// of basic blocks.
|
||||
struct CodeMetrics {
|
||||
/// \brief True if this function contains a call to setjmp or other functions
|
||||
/// with attribute "returns twice" without having the attribute itself.
|
||||
bool exposesReturnsTwice;
|
||||
|
||||
/// \brief True if this function calls itself.
|
||||
bool isRecursive;
|
||||
|
||||
/// \brief True if this function cannot be duplicated.
|
||||
///
|
||||
/// True if this function contains one or more indirect branches, or it contains
|
||||
/// one or more 'noduplicate' instructions.
|
||||
bool notDuplicatable;
|
||||
|
||||
/// \brief True if this function calls alloca (in the C sense).
|
||||
bool usesDynamicAlloca;
|
||||
|
||||
/// \brief Number of instructions in the analyzed blocks.
|
||||
unsigned NumInsts;
|
||||
|
||||
/// \brief Number of analyzed blocks.
|
||||
unsigned NumBlocks;
|
||||
|
||||
/// \brief Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// \brief Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
/// \brief The number of calls to internal functions with a single caller.
|
||||
///
|
||||
/// These are likely targets for future inlining, likely exposed by
|
||||
/// interleaved devirtualization.
|
||||
unsigned NumInlineCandidates;
|
||||
|
||||
/// \brief How many instructions produce vector values.
|
||||
///
|
||||
/// The inliner is more aggressive with inlining vector kernels.
|
||||
unsigned NumVectorInsts;
|
||||
|
||||
/// \brief How many 'ret' instructions the blocks contain.
|
||||
unsigned NumRets;
|
||||
|
||||
CodeMetrics()
|
||||
: exposesReturnsTwice(false), isRecursive(false), notDuplicatable(false),
|
||||
usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0),
|
||||
NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {}
|
||||
|
||||
/// \brief Add information about a block to the current state.
|
||||
void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
102
thirdparty/clang/include/llvm/Analysis/ConstantFolding.h
vendored
Normal file
102
thirdparty/clang/include/llvm/Analysis/ConstantFolding.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
//===-- ConstantFolding.h - Fold instructions into constants --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares routines for folding instructions into constants when all
|
||||
// operands are constants, for example "sub i32 1, 0" -> "1".
|
||||
//
|
||||
// Also, to supplement the basic VMCore ConstantExpr simplifications,
|
||||
// this file declares some additional folding routines that can make use of
|
||||
// DataLayout information. These functions cannot go in VMCore due to library
|
||||
// dependency issues.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H
|
||||
#define LLVM_ANALYSIS_CONSTANTFOLDING_H
|
||||
|
||||
namespace llvm {
|
||||
class Constant;
|
||||
class ConstantExpr;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Function;
|
||||
class Type;
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
|
||||
/// ConstantFoldInstruction - Try to constant fold the specified instruction.
|
||||
/// If successful, the constant result is returned, if not, null is returned.
|
||||
/// Note that this fails if not all of the operands are constant. Otherwise,
|
||||
/// this function can only fail when attempting to fold instructions like loads
|
||||
/// and stores, which have no constant expression form.
|
||||
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
|
||||
/// using the specified DataLayout. If successful, the constant result is
|
||||
/// result is returned, if not, null is returned.
|
||||
Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
|
||||
/// specified operands. If successful, the constant result is returned, if not,
|
||||
/// null is returned. Note that this function can fail when attempting to
|
||||
/// fold instructions like loads and stores, which have no constant expression
|
||||
/// form.
|
||||
///
|
||||
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
|
||||
ArrayRef<Constant *> Ops,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
|
||||
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
|
||||
/// returns a constant expression of the specified operands.
|
||||
///
|
||||
Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
|
||||
Constant *LHS, Constant *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
|
||||
/// instruction with the specified operands and indices. The constant result is
|
||||
/// returned if successful; if not, null is returned.
|
||||
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
|
||||
ArrayRef<unsigned> Idxs);
|
||||
|
||||
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
|
||||
/// produce if it is constant and determinable. If this is not determinable,
|
||||
/// return null.
|
||||
Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout *TD = 0);
|
||||
|
||||
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
|
||||
/// getelementptr constantexpr, return the constant value being addressed by the
|
||||
/// constant expression, or null if something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE);
|
||||
|
||||
/// ConstantFoldLoadThroughGEPIndices - Given a constant and getelementptr
|
||||
/// indices (with an *implied* zero pointer index that is not in the list),
|
||||
/// return the constant value being addressed by a virtual load, or null if
|
||||
/// something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
|
||||
ArrayRef<Constant*> Indices);
|
||||
|
||||
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
|
||||
/// the specified function.
|
||||
bool canConstantFoldCallTo(const Function *F);
|
||||
|
||||
/// ConstantFoldCall - Attempt to constant fold a call to the specified function
|
||||
/// with the specified arguments, returning null if unsuccessful.
|
||||
Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
93
thirdparty/clang/include/llvm/Analysis/ConstantsScanner.h
vendored
Normal file
93
thirdparty/clang/include/llvm/Analysis/ConstantsScanner.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class implements an iterator to walk through the constants referenced by
|
||||
// a method. This is used by the Bitcode & Assembly writers to build constant
|
||||
// pools.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H
|
||||
#define LLVM_ANALYSIS_CONSTANTSSCANNER_H
|
||||
|
||||
#include "llvm/Support/InstIterator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Constant;
|
||||
|
||||
class constant_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
const Constant, ptrdiff_t> {
|
||||
const_inst_iterator InstI; // Method instruction iterator
|
||||
unsigned OpIdx; // Operand index
|
||||
|
||||
typedef constant_iterator _Self;
|
||||
|
||||
inline bool isAtConstant() const {
|
||||
assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() &&
|
||||
"isAtConstant called with invalid arguments!");
|
||||
return isa<Constant>(InstI->getOperand(OpIdx));
|
||||
}
|
||||
|
||||
public:
|
||||
inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) {
|
||||
// Advance to first constant... if we are not already at constant or end
|
||||
if (InstI != inst_end(F) && // InstI is valid?
|
||||
(InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant?
|
||||
operator++();
|
||||
}
|
||||
|
||||
inline constant_iterator(const Function *F, bool) // end ctor
|
||||
: InstI(inst_end(F)), OpIdx(0) {
|
||||
}
|
||||
|
||||
inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx &&
|
||||
InstI == x.InstI; }
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
assert(isAtConstant() && "Dereferenced an iterator at the end!");
|
||||
return cast<Constant>(InstI->getOperand(OpIdx));
|
||||
}
|
||||
inline pointer operator->() const { return operator*(); }
|
||||
|
||||
inline _Self& operator++() { // Preincrement implementation
|
||||
++OpIdx;
|
||||
do {
|
||||
unsigned NumOperands = InstI->getNumOperands();
|
||||
while (OpIdx < NumOperands && !isAtConstant()) {
|
||||
++OpIdx;
|
||||
}
|
||||
|
||||
if (OpIdx < NumOperands) return *this; // Found a constant!
|
||||
++InstI;
|
||||
OpIdx = 0;
|
||||
} while (!InstI.atEnd());
|
||||
|
||||
return *this; // At the end of the method
|
||||
}
|
||||
|
||||
inline _Self operator++(int) { // Postincrement
|
||||
_Self tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
inline bool atEnd() const { return InstI.atEnd(); }
|
||||
};
|
||||
|
||||
inline constant_iterator constant_begin(const Function *F) {
|
||||
return constant_iterator(F);
|
||||
}
|
||||
|
||||
inline constant_iterator constant_end(const Function *F) {
|
||||
return constant_iterator(F, true);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
142
thirdparty/clang/include/llvm/Analysis/DOTGraphTraitsPass.h
vendored
Normal file
142
thirdparty/clang/include/llvm/Analysis/DOTGraphTraitsPass.h
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Templates to create dotty viewer and printer passes for GraphTraits graphs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
|
||||
#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
|
||||
|
||||
#include "llvm/Analysis/CFGPrinter.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsViewer : public FunctionPass {
|
||||
public:
|
||||
DOTGraphTraitsViewer(StringRef GraphName, char &ID)
|
||||
: FunctionPass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
|
||||
ViewGraph(Graph, Name, Simple, Title);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsPrinter : public FunctionPass {
|
||||
public:
|
||||
DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
|
||||
: FunctionPass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Filename = Name + "." + F.getName().str() + ".dot";
|
||||
std::string ErrorInfo;
|
||||
|
||||
errs() << "Writing '" << Filename << "'...";
|
||||
|
||||
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
|
||||
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
|
||||
if (ErrorInfo.empty())
|
||||
WriteGraph(File, Graph, Simple, Title);
|
||||
else
|
||||
errs() << " error opening file for writing!";
|
||||
errs() << "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsModuleViewer : public ModulePass {
|
||||
public:
|
||||
DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
|
||||
: ModulePass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnModule(Module &M) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
|
||||
ViewGraph(Graph, Name, Simple, Title);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsModulePrinter : public ModulePass {
|
||||
public:
|
||||
DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
|
||||
: ModulePass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnModule(Module &M) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Filename = Name + ".dot";
|
||||
std::string ErrorInfo;
|
||||
|
||||
errs() << "Writing '" << Filename << "'...";
|
||||
|
||||
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
|
||||
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
|
||||
if (ErrorInfo.empty())
|
||||
WriteGraph(File, Graph, Simple, Title);
|
||||
else
|
||||
errs() << " error opening file for writing!";
|
||||
errs() << "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
895
thirdparty/clang/include/llvm/Analysis/DependenceAnalysis.h
vendored
Normal file
895
thirdparty/clang/include/llvm/Analysis/DependenceAnalysis.h
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
//===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DependenceAnalysis is an LLVM pass that analyses dependences between memory
|
||||
// accesses. Currently, it is an implementation of the approach described in
|
||||
//
|
||||
// Practical Dependence Testing
|
||||
// Goff, Kennedy, Tseng
|
||||
// PLDI 1991
|
||||
//
|
||||
// There's a single entry point that analyzes the dependence between a pair
|
||||
// of memory references in a function, returning either NULL, for no dependence,
|
||||
// or a more-or-less detailed description of the dependence between them.
|
||||
//
|
||||
// This pass exists to support the DependenceGraph pass. There are two separate
|
||||
// passes because there's a useful separation of concerns. A dependence exists
|
||||
// if two conditions are met:
|
||||
//
|
||||
// 1) Two instructions reference the same memory location, and
|
||||
// 2) There is a flow of control leading from one instruction to the other.
|
||||
//
|
||||
// DependenceAnalysis attacks the first condition; DependenceGraph will attack
|
||||
// the second (it's not yet ready).
|
||||
//
|
||||
// Please note that this is work in progress and the interface is subject to
|
||||
// change.
|
||||
//
|
||||
// Plausible changes:
|
||||
// Return a set of more precise dependences instead of just one dependence
|
||||
// summarizing all.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
|
||||
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class AliasAnalysis;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class SCEVConstant;
|
||||
class raw_ostream;
|
||||
|
||||
/// Dependence - This class represents a dependence between two memory
|
||||
/// memory references in a function. It contains minimal information and
|
||||
/// is used in the very common situation where the compiler is unable to
|
||||
/// determine anything beyond the existence of a dependence; that is, it
|
||||
/// represents a confused dependence (see also FullDependence). In most
|
||||
/// cases (for output, flow, and anti dependences), the dependence implies
|
||||
/// an ordering, where the source must precede the destination; in contrast,
|
||||
/// input dependences are unordered.
|
||||
class Dependence {
|
||||
public:
|
||||
Dependence(Instruction *Source,
|
||||
Instruction *Destination) :
|
||||
Src(Source), Dst(Destination) {}
|
||||
virtual ~Dependence() {}
|
||||
|
||||
/// Dependence::DVEntry - Each level in the distance/direction vector
|
||||
/// has a direction (or perhaps a union of several directions), and
|
||||
/// perhaps a distance.
|
||||
struct DVEntry {
|
||||
enum { NONE = 0,
|
||||
LT = 1,
|
||||
EQ = 2,
|
||||
LE = 3,
|
||||
GT = 4,
|
||||
NE = 5,
|
||||
GE = 6,
|
||||
ALL = 7 };
|
||||
unsigned char Direction : 3; // Init to ALL, then refine.
|
||||
bool Scalar : 1; // Init to true.
|
||||
bool PeelFirst : 1; // Peeling the first iteration will break dependence.
|
||||
bool PeelLast : 1; // Peeling the last iteration will break the dependence.
|
||||
bool Splitable : 1; // Splitting the loop will break dependence.
|
||||
const SCEV *Distance; // NULL implies no distance available.
|
||||
DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false),
|
||||
PeelLast(false), Splitable(false), Distance(NULL) { }
|
||||
};
|
||||
|
||||
/// getSrc - Returns the source instruction for this dependence.
|
||||
///
|
||||
Instruction *getSrc() const { return Src; }
|
||||
|
||||
/// getDst - Returns the destination instruction for this dependence.
|
||||
///
|
||||
Instruction *getDst() const { return Dst; }
|
||||
|
||||
/// isInput - Returns true if this is an input dependence.
|
||||
///
|
||||
bool isInput() const;
|
||||
|
||||
/// isOutput - Returns true if this is an output dependence.
|
||||
///
|
||||
bool isOutput() const;
|
||||
|
||||
/// isFlow - Returns true if this is a flow (aka true) dependence.
|
||||
///
|
||||
bool isFlow() const;
|
||||
|
||||
/// isAnti - Returns true if this is an anti dependence.
|
||||
///
|
||||
bool isAnti() const;
|
||||
|
||||
/// isOrdered - Returns true if dependence is Output, Flow, or Anti
|
||||
///
|
||||
bool isOrdered() const { return isOutput() || isFlow() || isAnti(); }
|
||||
|
||||
/// isUnordered - Returns true if dependence is Input
|
||||
///
|
||||
bool isUnordered() const { return isInput(); }
|
||||
|
||||
/// isLoopIndependent - Returns true if this is a loop-independent
|
||||
/// dependence.
|
||||
virtual bool isLoopIndependent() const { return true; }
|
||||
|
||||
/// isConfused - Returns true if this dependence is confused
|
||||
/// (the compiler understands nothing and makes worst-case
|
||||
/// assumptions).
|
||||
virtual bool isConfused() const { return true; }
|
||||
|
||||
/// isConsistent - Returns true if this dependence is consistent
|
||||
/// (occurs every time the source and destination are executed).
|
||||
virtual bool isConsistent() const { return false; }
|
||||
|
||||
/// getLevels - Returns the number of common loops surrounding the
|
||||
/// source and destination of the dependence.
|
||||
virtual unsigned getLevels() const { return 0; }
|
||||
|
||||
/// getDirection - Returns the direction associated with a particular
|
||||
/// level.
|
||||
virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
|
||||
|
||||
/// getDistance - Returns the distance (or NULL) associated with a
|
||||
/// particular level.
|
||||
virtual const SCEV *getDistance(unsigned Level) const { return NULL; }
|
||||
|
||||
/// isPeelFirst - Returns true if peeling the first iteration from
|
||||
/// this loop will break this dependence.
|
||||
virtual bool isPeelFirst(unsigned Level) const { return false; }
|
||||
|
||||
/// isPeelLast - Returns true if peeling the last iteration from
|
||||
/// this loop will break this dependence.
|
||||
virtual bool isPeelLast(unsigned Level) const { return false; }
|
||||
|
||||
/// isSplitable - Returns true if splitting this loop will break
|
||||
/// the dependence.
|
||||
virtual bool isSplitable(unsigned Level) const { return false; }
|
||||
|
||||
/// isScalar - Returns true if a particular level is scalar; that is,
|
||||
/// if no subscript in the source or destination mention the induction
|
||||
/// variable associated with the loop at this level.
|
||||
virtual bool isScalar(unsigned Level) const;
|
||||
|
||||
/// dump - For debugging purposes, dumps a dependence to OS.
|
||||
///
|
||||
void dump(raw_ostream &OS) const;
|
||||
private:
|
||||
Instruction *Src, *Dst;
|
||||
friend class DependenceAnalysis;
|
||||
};
|
||||
|
||||
|
||||
/// FullDependence - This class represents a dependence between two memory
|
||||
/// references in a function. It contains detailed information about the
|
||||
/// dependence (direction vectors, etc.) and is used when the compiler is
|
||||
/// able to accurately analyze the interaction of the references; that is,
|
||||
/// it is not a confused dependence (see Dependence). In most cases
|
||||
/// (for output, flow, and anti dependences), the dependence implies an
|
||||
/// ordering, where the source must precede the destination; in contrast,
|
||||
/// input dependences are unordered.
|
||||
class FullDependence : public Dependence {
|
||||
public:
|
||||
FullDependence(Instruction *Src,
|
||||
Instruction *Dst,
|
||||
bool LoopIndependent,
|
||||
unsigned Levels);
|
||||
~FullDependence() {
|
||||
delete[] DV;
|
||||
}
|
||||
|
||||
/// isLoopIndependent - Returns true if this is a loop-independent
|
||||
/// dependence.
|
||||
bool isLoopIndependent() const { return LoopIndependent; }
|
||||
|
||||
/// isConfused - Returns true if this dependence is confused
|
||||
/// (the compiler understands nothing and makes worst-case
|
||||
/// assumptions).
|
||||
bool isConfused() const { return false; }
|
||||
|
||||
/// isConsistent - Returns true if this dependence is consistent
|
||||
/// (occurs every time the source and destination are executed).
|
||||
bool isConsistent() const { return Consistent; }
|
||||
|
||||
/// getLevels - Returns the number of common loops surrounding the
|
||||
/// source and destination of the dependence.
|
||||
unsigned getLevels() const { return Levels; }
|
||||
|
||||
/// getDirection - Returns the direction associated with a particular
|
||||
/// level.
|
||||
unsigned getDirection(unsigned Level) const;
|
||||
|
||||
/// getDistance - Returns the distance (or NULL) associated with a
|
||||
/// particular level.
|
||||
const SCEV *getDistance(unsigned Level) const;
|
||||
|
||||
/// isPeelFirst - Returns true if peeling the first iteration from
|
||||
/// this loop will break this dependence.
|
||||
bool isPeelFirst(unsigned Level) const;
|
||||
|
||||
/// isPeelLast - Returns true if peeling the last iteration from
|
||||
/// this loop will break this dependence.
|
||||
bool isPeelLast(unsigned Level) const;
|
||||
|
||||
/// isSplitable - Returns true if splitting the loop will break
|
||||
/// the dependence.
|
||||
bool isSplitable(unsigned Level) const;
|
||||
|
||||
/// isScalar - Returns true if a particular level is scalar; that is,
|
||||
/// if no subscript in the source or destination mention the induction
|
||||
/// variable associated with the loop at this level.
|
||||
bool isScalar(unsigned Level) const;
|
||||
private:
|
||||
unsigned short Levels;
|
||||
bool LoopIndependent;
|
||||
bool Consistent; // Init to true, then refine.
|
||||
DVEntry *DV;
|
||||
friend class DependenceAnalysis;
|
||||
};
|
||||
|
||||
|
||||
/// DependenceAnalysis - This class is the main dependence-analysis driver.
|
||||
///
|
||||
class DependenceAnalysis : public FunctionPass {
|
||||
void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
|
||||
DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
/// depends - Tests for a dependence between the Src and Dst instructions.
|
||||
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
|
||||
/// FullDependence) with as much information as can be gleaned.
|
||||
/// The flag PossiblyLoopIndependent should be set by the caller
|
||||
/// if it appears that control flow can reach from Src to Dst
|
||||
/// without traversing a loop back edge.
|
||||
Dependence *depends(Instruction *Src,
|
||||
Instruction *Dst,
|
||||
bool PossiblyLoopIndependent);
|
||||
|
||||
/// getSplitIteration - Give a dependence that's splittable at some
|
||||
/// particular level, return the iteration that should be used to split
|
||||
/// the loop.
|
||||
///
|
||||
/// Generally, the dependence analyzer will be used to build
|
||||
/// a dependence graph for a function (basically a map from instructions
|
||||
/// to dependences). Looking for cycles in the graph shows us loops
|
||||
/// that cannot be trivially vectorized/parallelized.
|
||||
///
|
||||
/// We can try to improve the situation by examining all the dependences
|
||||
/// that make up the cycle, looking for ones we can break.
|
||||
/// Sometimes, peeling the first or last iteration of a loop will break
|
||||
/// dependences, and there are flags for those possibilities.
|
||||
/// Sometimes, splitting a loop at some other iteration will do the trick,
|
||||
/// and we've got a flag for that case. Rather than waste the space to
|
||||
/// record the exact iteration (since we rarely know), we provide
|
||||
/// a method that calculates the iteration. It's a drag that it must work
|
||||
/// from scratch, but wonderful in that it's possible.
|
||||
///
|
||||
/// Here's an example:
|
||||
///
|
||||
/// for (i = 0; i < 10; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
///
|
||||
/// There's a loop-carried flow dependence from the store to the load,
|
||||
/// found by the weak-crossing SIV test. The dependence will have a flag,
|
||||
/// indicating that the dependence can be broken by splitting the loop.
|
||||
/// Calling getSplitIteration will return 5.
|
||||
/// Splitting the loop breaks the dependence, like so:
|
||||
///
|
||||
/// for (i = 0; i <= 5; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
/// for (i = 6; i < 10; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
///
|
||||
/// breaks the dependence and allows us to vectorize/parallelize
|
||||
/// both loops.
|
||||
const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level);
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA;
|
||||
ScalarEvolution *SE;
|
||||
LoopInfo *LI;
|
||||
Function *F;
|
||||
|
||||
/// Subscript - This private struct represents a pair of subscripts from
|
||||
/// a pair of potentially multi-dimensional array references. We use a
|
||||
/// vector of them to guide subscript partitioning.
|
||||
struct Subscript {
|
||||
const SCEV *Src;
|
||||
const SCEV *Dst;
|
||||
enum ClassificationKind { ZIV, SIV, RDIV, MIV, NonLinear } Classification;
|
||||
SmallBitVector Loops;
|
||||
SmallBitVector GroupLoops;
|
||||
SmallBitVector Group;
|
||||
};
|
||||
|
||||
struct CoefficientInfo {
|
||||
const SCEV *Coeff;
|
||||
const SCEV *PosPart;
|
||||
const SCEV *NegPart;
|
||||
const SCEV *Iterations;
|
||||
};
|
||||
|
||||
struct BoundInfo {
|
||||
const SCEV *Iterations;
|
||||
const SCEV *Upper[8];
|
||||
const SCEV *Lower[8];
|
||||
unsigned char Direction;
|
||||
unsigned char DirSet;
|
||||
};
|
||||
|
||||
/// Constraint - This private class represents a constraint, as defined
|
||||
/// in the paper
|
||||
///
|
||||
/// Practical Dependence Testing
|
||||
/// Goff, Kennedy, Tseng
|
||||
/// PLDI 1991
|
||||
///
|
||||
/// There are 5 kinds of constraint, in a hierarchy.
|
||||
/// 1) Any - indicates no constraint, any dependence is possible.
|
||||
/// 2) Line - A line ax + by = c, where a, b, and c are parameters,
|
||||
/// representing the dependence equation.
|
||||
/// 3) Distance - The value d of the dependence distance;
|
||||
/// 4) Point - A point <x, y> representing the dependence from
|
||||
/// iteration x to iteration y.
|
||||
/// 5) Empty - No dependence is possible.
|
||||
class Constraint {
|
||||
private:
|
||||
enum ConstraintKind { Empty, Point, Distance, Line, Any } Kind;
|
||||
ScalarEvolution *SE;
|
||||
const SCEV *A;
|
||||
const SCEV *B;
|
||||
const SCEV *C;
|
||||
const Loop *AssociatedLoop;
|
||||
public:
|
||||
/// isEmpty - Return true if the constraint is of kind Empty.
|
||||
bool isEmpty() const { return Kind == Empty; }
|
||||
|
||||
/// isPoint - Return true if the constraint is of kind Point.
|
||||
bool isPoint() const { return Kind == Point; }
|
||||
|
||||
/// isDistance - Return true if the constraint is of kind Distance.
|
||||
bool isDistance() const { return Kind == Distance; }
|
||||
|
||||
/// isLine - Return true if the constraint is of kind Line.
|
||||
/// Since Distance's can also be represented as Lines, we also return
|
||||
/// true if the constraint is of kind Distance.
|
||||
bool isLine() const { return Kind == Line || Kind == Distance; }
|
||||
|
||||
/// isAny - Return true if the constraint is of kind Any;
|
||||
bool isAny() const { return Kind == Any; }
|
||||
|
||||
/// getX - If constraint is a point <X, Y>, returns X.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getX() const;
|
||||
|
||||
/// getY - If constraint is a point <X, Y>, returns Y.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getY() const;
|
||||
|
||||
/// getA - If constraint is a line AX + BY = C, returns A.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getA() const;
|
||||
|
||||
/// getB - If constraint is a line AX + BY = C, returns B.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getB() const;
|
||||
|
||||
/// getC - If constraint is a line AX + BY = C, returns C.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getC() const;
|
||||
|
||||
/// getD - If constraint is a distance, returns D.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getD() const;
|
||||
|
||||
/// getAssociatedLoop - Returns the loop associated with this constraint.
|
||||
const Loop *getAssociatedLoop() const;
|
||||
|
||||
/// setPoint - Change a constraint to Point.
|
||||
void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop);
|
||||
|
||||
/// setLine - Change a constraint to Line.
|
||||
void setLine(const SCEV *A, const SCEV *B,
|
||||
const SCEV *C, const Loop *CurrentLoop);
|
||||
|
||||
/// setDistance - Change a constraint to Distance.
|
||||
void setDistance(const SCEV *D, const Loop *CurrentLoop);
|
||||
|
||||
/// setEmpty - Change a constraint to Empty.
|
||||
void setEmpty();
|
||||
|
||||
/// setAny - Change a constraint to Any.
|
||||
void setAny(ScalarEvolution *SE);
|
||||
|
||||
/// dump - For debugging purposes. Dumps the constraint
|
||||
/// out to OS.
|
||||
void dump(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
|
||||
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
|
||||
/// instructions and establishes their shared loops. Sets the variables
|
||||
/// CommonLevels, SrcLevels, and MaxLevels.
|
||||
/// The source and destination instructions needn't be contained in the same
|
||||
/// loop. The routine establishNestingLevels finds the level of most deeply
|
||||
/// nested loop that contains them both, CommonLevels. An instruction that's
|
||||
/// not contained in a loop is at level = 0. MaxLevels is equal to the level
|
||||
/// of the source plus the level of the destination, minus CommonLevels.
|
||||
/// This lets us allocate vectors MaxLevels in length, with room for every
|
||||
/// distinct loop referenced in both the source and destination subscripts.
|
||||
/// The variable SrcLevels is the nesting depth of the source instruction.
|
||||
/// It's used to help calculate distinct loops referenced by the destination.
|
||||
/// Here's the map from loops to levels:
|
||||
/// 0 - unused
|
||||
/// 1 - outermost common loop
|
||||
/// ... - other common loops
|
||||
/// CommonLevels - innermost common loop
|
||||
/// ... - loops containing Src but not Dst
|
||||
/// SrcLevels - innermost loop containing Src but not Dst
|
||||
/// ... - loops containing Dst but not Src
|
||||
/// MaxLevels - innermost loop containing Dst but not Src
|
||||
/// Consider the follow code fragment:
|
||||
/// for (a = ...) {
|
||||
/// for (b = ...) {
|
||||
/// for (c = ...) {
|
||||
/// for (d = ...) {
|
||||
/// A[] = ...;
|
||||
/// }
|
||||
/// }
|
||||
/// for (e = ...) {
|
||||
/// for (f = ...) {
|
||||
/// for (g = ...) {
|
||||
/// ... = A[];
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// If we're looking at the possibility of a dependence between the store
|
||||
/// to A (the Src) and the load from A (the Dst), we'll note that they
|
||||
/// have 2 loops in common, so CommonLevels will equal 2 and the direction
|
||||
/// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7.
|
||||
/// A map from loop names to level indices would look like
|
||||
/// a - 1
|
||||
/// b - 2 = CommonLevels
|
||||
/// c - 3
|
||||
/// d - 4 = SrcLevels
|
||||
/// e - 5
|
||||
/// f - 6
|
||||
/// g - 7 = MaxLevels
|
||||
void establishNestingLevels(const Instruction *Src,
|
||||
const Instruction *Dst);
|
||||
|
||||
unsigned CommonLevels, SrcLevels, MaxLevels;
|
||||
|
||||
/// mapSrcLoop - Given one of the loops containing the source, return
|
||||
/// its level index in our numbering scheme.
|
||||
unsigned mapSrcLoop(const Loop *SrcLoop) const;
|
||||
|
||||
/// mapDstLoop - Given one of the loops containing the destination,
|
||||
/// return its level index in our numbering scheme.
|
||||
unsigned mapDstLoop(const Loop *DstLoop) const;
|
||||
|
||||
/// isLoopInvariant - Returns true if Expression is loop invariant
|
||||
/// in LoopNest.
|
||||
bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
|
||||
|
||||
/// removeMatchingExtensions - Examines a subscript pair.
|
||||
/// If the source and destination are identically sign (or zero)
|
||||
/// extended, it strips off the extension in an effort to
|
||||
/// simplify the actual analysis.
|
||||
void removeMatchingExtensions(Subscript *Pair);
|
||||
|
||||
/// collectCommonLoops - Finds the set of loops from the LoopNest that
|
||||
/// have a level <= CommonLevels and are referred to by the SCEV Expression.
|
||||
void collectCommonLoops(const SCEV *Expression,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops) const;
|
||||
|
||||
/// checkSrcSubscript - Examines the SCEV Src, returning true iff it's
|
||||
/// linear. Collect the set of loops mentioned by Src.
|
||||
bool checkSrcSubscript(const SCEV *Src,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// checkDstSubscript - Examines the SCEV Dst, returning true iff it's
|
||||
/// linear. Collect the set of loops mentioned by Dst.
|
||||
bool checkDstSubscript(const SCEV *Dst,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// isKnownPredicate - Compare X and Y using the predicate Pred.
|
||||
/// Basically a wrapper for SCEV::isKnownPredicate,
|
||||
/// but tries harder, especially in the presence of sign and zero
|
||||
/// extensions and symbolics.
|
||||
bool isKnownPredicate(ICmpInst::Predicate Pred,
|
||||
const SCEV *X,
|
||||
const SCEV *Y) const;
|
||||
|
||||
/// collectUpperBound - All subscripts are the same type (on my machine,
|
||||
/// an i64). The loop bound may be a smaller type. collectUpperBound
|
||||
/// find the bound, if available, and zero extends it to the Type T.
|
||||
/// (I zero extend since the bound should always be >= 0.)
|
||||
/// If no upper bound is available, return NULL.
|
||||
const SCEV *collectUpperBound(const Loop *l, Type *T) const;
|
||||
|
||||
/// collectConstantUpperBound - Calls collectUpperBound(), then
|
||||
/// attempts to cast it to SCEVConstant. If the cast fails,
|
||||
/// returns NULL.
|
||||
const SCEVConstant *collectConstantUpperBound(const Loop *l, Type *T) const;
|
||||
|
||||
/// classifyPair - Examines the subscript pair (the Src and Dst SCEVs)
|
||||
/// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear.
|
||||
/// Collects the associated loops in a set.
|
||||
Subscript::ClassificationKind classifyPair(const SCEV *Src,
|
||||
const Loop *SrcLoopNest,
|
||||
const SCEV *Dst,
|
||||
const Loop *DstLoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// testZIV - Tests the ZIV subscript pair (Src and Dst) for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// If the dependence isn't proven to exist,
|
||||
/// marks the Result as inconsistent.
|
||||
bool testZIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// testSIV - Tests the SIV subscript pair (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*j], where
|
||||
/// i and j are induction variables, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction vector entry and, when possible,
|
||||
/// the distance vector entry.
|
||||
/// If the dependence isn't proven to exist,
|
||||
/// marks the Result as inconsistent.
|
||||
bool testSIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
unsigned &Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint,
|
||||
const SCEV *&SplitIter) const;
|
||||
|
||||
/// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*j]
|
||||
/// where i and j are induction variables, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// With minor algebra, this test can also be used for things like
|
||||
/// [c1 + a1*i + a2*j][c2].
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Marks the Result as inconsistent.
|
||||
bool testRDIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// testMIV - Tests the MIV subscript pair (Src and Dst) for dependence.
|
||||
/// Returns true if dependence disproved.
|
||||
/// Can sometimes refine direction vectors.
|
||||
bool testMIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
const SmallBitVector &Loops,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// strongSIVtest - Tests the strong SIV subscript pair (Src and Dst)
|
||||
/// for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction and distance.
|
||||
bool strongSIVtest(const SCEV *Coeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 - a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// Marks the dependence as splitable.
|
||||
bool weakCrossingSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint,
|
||||
const SCEV *&SplitIter) const;
|
||||
|
||||
/// ExactSIVtest - Tests the SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
bool exactSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1] and [c2 + a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant. See also weakZeroDstSIVtest.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// If loop peeling will break the dependence, mark appropriately.
|
||||
bool weakZeroSrcSIVtest(const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant. See also weakZeroSrcSIVtest.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// If loop peeling will break the dependence, mark appropriately.
|
||||
bool weakZeroDstSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// exactRDIVtest - Tests the RDIV subscript pair for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + b*j],
|
||||
/// where i and j are induction variable, c1 and c2 are loop invariant,
|
||||
/// and a and b are constants.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Works in some cases that symbolicRDIVtest doesn't,
|
||||
/// and vice versa.
|
||||
bool exactRDIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *SrcLoop,
|
||||
const Loop *DstLoop,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// symbolicRDIVtest - Tests the RDIV subscript pair for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + b*j],
|
||||
/// where i and j are induction variable, c1 and c2 are loop invariant,
|
||||
/// and a and b are constants.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Works in some cases that exactRDIVtest doesn't,
|
||||
/// and vice versa. Can also be used as a backup for
|
||||
/// ordinary SIV tests.
|
||||
bool symbolicRDIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *SrcLoop,
|
||||
const Loop *DstLoop) const;
|
||||
|
||||
/// gcdMIVtest - Tests an MIV subscript pair for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Can sometimes disprove the equal direction for 1 or more loops.
|
||||
// Can handle some symbolics that even the SIV tests don't get,
|
||||
/// so we use it as a backup for everything.
|
||||
bool gcdMIVtest(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// banerjeeMIVtest - Tests an MIV subscript pair for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Computes directions.
|
||||
bool banerjeeMIVtest(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
const SmallBitVector &Loops,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// collectCoefficientInfo - Walks through the subscript,
|
||||
/// collecting each coefficient, the associated loop bounds,
|
||||
/// and recording its positive and negative parts for later use.
|
||||
CoefficientInfo *collectCoeffInfo(const SCEV *Subscript,
|
||||
bool SrcFlag,
|
||||
const SCEV *&Constant) const;
|
||||
|
||||
/// getPositivePart - X^+ = max(X, 0).
|
||||
///
|
||||
const SCEV *getPositivePart(const SCEV *X) const;
|
||||
|
||||
/// getNegativePart - X^- = min(X, 0).
|
||||
///
|
||||
const SCEV *getNegativePart(const SCEV *X) const;
|
||||
|
||||
/// getLowerBound - Looks through all the bounds info and
|
||||
/// computes the lower bound given the current direction settings
|
||||
/// at each level.
|
||||
const SCEV *getLowerBound(BoundInfo *Bound) const;
|
||||
|
||||
/// getUpperBound - Looks through all the bounds info and
|
||||
/// computes the upper bound given the current direction settings
|
||||
/// at each level.
|
||||
const SCEV *getUpperBound(BoundInfo *Bound) const;
|
||||
|
||||
/// exploreDirections - Hierarchically expands the direction vector
|
||||
/// search space, combining the directions of discovered dependences
|
||||
/// in the DirSet field of Bound. Returns the number of distinct
|
||||
/// dependences discovered. If the dependence is disproved,
|
||||
/// it will return 0.
|
||||
unsigned exploreDirections(unsigned Level,
|
||||
CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
const SmallBitVector &Loops,
|
||||
unsigned &DepthExpanded,
|
||||
const SCEV *Delta) const;
|
||||
|
||||
/// testBounds - Returns true iff the current bounds are plausible.
|
||||
///
|
||||
bool testBounds(unsigned char DirKind,
|
||||
unsigned Level,
|
||||
BoundInfo *Bound,
|
||||
const SCEV *Delta) const;
|
||||
|
||||
/// findBoundsALL - Computes the upper and lower bounds for level K
|
||||
/// using the * direction. Records them in Bound.
|
||||
void findBoundsALL(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsLT - Computes the upper and lower bounds for level K
|
||||
/// using the < direction. Records them in Bound.
|
||||
void findBoundsLT(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsGT - Computes the upper and lower bounds for level K
|
||||
/// using the > direction. Records them in Bound.
|
||||
void findBoundsGT(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsEQ - Computes the upper and lower bounds for level K
|
||||
/// using the = direction. Records them in Bound.
|
||||
void findBoundsEQ(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// intersectConstraints - Updates X with the intersection
|
||||
/// of the Constraints X and Y. Returns true if X has changed.
|
||||
bool intersectConstraints(Constraint *X,
|
||||
const Constraint *Y);
|
||||
|
||||
/// propagate - Review the constraints, looking for opportunities
|
||||
/// to simplify a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagate(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
SmallBitVector &Loops,
|
||||
SmallVector<Constraint, 4> &Constraints,
|
||||
bool &Consistent);
|
||||
|
||||
/// propagateDistance - Attempt to propagate a distance
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagateDistance(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint,
|
||||
bool &Consistent);
|
||||
|
||||
/// propagatePoint - Attempt to propagate a point
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
bool propagatePoint(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint);
|
||||
|
||||
/// propagateLine - Attempt to propagate a line
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagateLine(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint,
|
||||
bool &Consistent);
|
||||
|
||||
/// findCoefficient - Given a linear SCEV,
|
||||
/// return the coefficient corresponding to specified loop.
|
||||
/// If there isn't one, return the SCEV constant 0.
|
||||
/// For example, given a*i + b*j + c*k, returning the coefficient
|
||||
/// corresponding to the j loop would yield b.
|
||||
const SCEV *findCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop) const;
|
||||
|
||||
/// zeroCoefficient - Given a linear SCEV,
|
||||
/// return the SCEV given by zeroing out the coefficient
|
||||
/// corresponding to the specified loop.
|
||||
/// For example, given a*i + b*j + c*k, zeroing the coefficient
|
||||
/// corresponding to the j loop would yield a*i + c*k.
|
||||
const SCEV *zeroCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop) const;
|
||||
|
||||
/// addToCoefficient - Given a linear SCEV Expr,
|
||||
/// return the SCEV given by adding some Value to the
|
||||
/// coefficient corresponding to the specified TargetLoop.
|
||||
/// For example, given a*i + b*j + c*k, adding 1 to the coefficient
|
||||
/// corresponding to the j loop would yield a*i + (b+1)*j + c*k.
|
||||
const SCEV *addToCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop,
|
||||
const SCEV *Value) const;
|
||||
|
||||
/// updateDirection - Update direction vector entry
|
||||
/// based on the current constraint.
|
||||
void updateDirection(Dependence::DVEntry &Level,
|
||||
const Constraint &CurConstraint) const;
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
DependenceAnalysis() : FunctionPass(ID) {
|
||||
initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
void releaseMemory();
|
||||
void getAnalysisUsage(AnalysisUsage &) const;
|
||||
void print(raw_ostream &, const Module * = 0) const;
|
||||
}; // class DependenceAnalysis
|
||||
|
||||
/// createDependenceAnalysisPass - This creates an instance of the
|
||||
/// DependenceAnalysis pass.
|
||||
FunctionPass *createDependenceAnalysisPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
30
thirdparty/clang/include/llvm/Analysis/DomPrinter.h
vendored
Normal file
30
thirdparty/clang/include/llvm/Analysis/DomPrinter.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
//===-- DomPrinter.h - Dom printer external interface ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines external functions that can be called to explicitly
|
||||
// instantiate the dominance tree printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMPRINTER_H
|
||||
#define LLVM_ANALYSIS_DOMPRINTER_H
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
FunctionPass *createDomPrinterPass();
|
||||
FunctionPass *createDomOnlyPrinterPass();
|
||||
FunctionPass *createDomViewerPass();
|
||||
FunctionPass *createDomOnlyViewerPass();
|
||||
FunctionPass *createPostDomPrinterPass();
|
||||
FunctionPass *createPostDomOnlyPrinterPass();
|
||||
FunctionPass *createPostDomViewerPass();
|
||||
FunctionPass *createPostDomOnlyViewerPass();
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
190
thirdparty/clang/include/llvm/Analysis/DominanceFrontier.h
vendored
Normal file
190
thirdparty/clang/include/llvm/Analysis/DominanceFrontier.h
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the DominanceFrontier class, which calculate and holds the
|
||||
// dominance frontier for a function.
|
||||
//
|
||||
// This should be considered deprecated, don't add any more uses of this data
|
||||
// structure.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H
|
||||
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
|
||||
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominanceFrontierBase - Common base class for computing forward and inverse
|
||||
/// dominance frontiers for a function.
|
||||
///
|
||||
class DominanceFrontierBase : public FunctionPass {
|
||||
public:
|
||||
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
|
||||
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
|
||||
protected:
|
||||
DomSetMapType Frontiers;
|
||||
std::vector<BasicBlock*> Roots;
|
||||
const bool IsPostDominators;
|
||||
|
||||
public:
|
||||
DominanceFrontierBase(char &ID, bool isPostDom)
|
||||
: FunctionPass(ID), IsPostDominators(isPostDom) {}
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
|
||||
|
||||
/// isPostDominator - Returns true if analysis based of postdoms
|
||||
///
|
||||
bool isPostDominator() const { return IsPostDominators; }
|
||||
|
||||
virtual void releaseMemory() { Frontiers.clear(); }
|
||||
|
||||
// Accessor interface:
|
||||
typedef DomSetMapType::iterator iterator;
|
||||
typedef DomSetMapType::const_iterator const_iterator;
|
||||
iterator begin() { return Frontiers.begin(); }
|
||||
const_iterator begin() const { return Frontiers.begin(); }
|
||||
iterator end() { return Frontiers.end(); }
|
||||
const_iterator end() const { return Frontiers.end(); }
|
||||
iterator find(BasicBlock *B) { return Frontiers.find(B); }
|
||||
const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
|
||||
|
||||
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
|
||||
assert(find(BB) == end() && "Block already in DominanceFrontier!");
|
||||
return Frontiers.insert(std::make_pair(BB, frontier)).first;
|
||||
}
|
||||
|
||||
/// removeBlock - Remove basic block BB's frontier.
|
||||
void removeBlock(BasicBlock *BB) {
|
||||
assert(find(BB) != end() && "Block is not in DominanceFrontier!");
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
I->second.erase(BB);
|
||||
Frontiers.erase(BB);
|
||||
}
|
||||
|
||||
void addToFrontier(iterator I, BasicBlock *Node) {
|
||||
assert(I != end() && "BB is not in DominanceFrontier!");
|
||||
I->second.insert(Node);
|
||||
}
|
||||
|
||||
void removeFromFrontier(iterator I, BasicBlock *Node) {
|
||||
assert(I != end() && "BB is not in DominanceFrontier!");
|
||||
assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
|
||||
I->second.erase(Node);
|
||||
}
|
||||
|
||||
/// compareDomSet - Return false if two domsets match. Otherwise
|
||||
/// return true;
|
||||
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
|
||||
std::set<BasicBlock *> tmpSet;
|
||||
for (DomSetType::const_iterator I = DS2.begin(),
|
||||
E = DS2.end(); I != E; ++I)
|
||||
tmpSet.insert(*I);
|
||||
|
||||
for (DomSetType::const_iterator I = DS1.begin(),
|
||||
E = DS1.end(); I != E; ) {
|
||||
BasicBlock *Node = *I++;
|
||||
|
||||
if (tmpSet.erase(Node) == 0)
|
||||
// Node is in DS1 but not in DS2.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!tmpSet.empty())
|
||||
// There are nodes that are in DS2 but not in DS1.
|
||||
return true;
|
||||
|
||||
// DS1 and DS2 matches.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// compare - Return true if the other dominance frontier base matches
|
||||
/// this dominance frontier base. Otherwise return false.
|
||||
bool compare(DominanceFrontierBase &Other) const {
|
||||
DomSetMapType tmpFrontiers;
|
||||
for (DomSetMapType::const_iterator I = Other.begin(),
|
||||
E = Other.end(); I != E; ++I)
|
||||
tmpFrontiers.insert(std::make_pair(I->first, I->second));
|
||||
|
||||
for (DomSetMapType::iterator I = tmpFrontiers.begin(),
|
||||
E = tmpFrontiers.end(); I != E; ) {
|
||||
BasicBlock *Node = I->first;
|
||||
const_iterator DFI = find(Node);
|
||||
if (DFI == end())
|
||||
return true;
|
||||
|
||||
if (compareDomSet(I->second, DFI->second))
|
||||
return true;
|
||||
|
||||
++I;
|
||||
tmpFrontiers.erase(Node);
|
||||
}
|
||||
|
||||
if (!tmpFrontiers.empty())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// print - Convert to human readable form
|
||||
///
|
||||
virtual void print(raw_ostream &OS, const Module* = 0) const;
|
||||
|
||||
/// dump - Dump the dominance frontier to dbgs().
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
|
||||
/// used to compute a forward dominator frontiers.
|
||||
///
|
||||
class DominanceFrontier : public DominanceFrontierBase {
|
||||
virtual void anchor();
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
DominanceFrontier() :
|
||||
DominanceFrontierBase(ID, false) {
|
||||
initializeDominanceFrontierPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
BasicBlock *getRoot() const {
|
||||
assert(Roots.size() == 1 && "Should always have entry node!");
|
||||
return Roots[0];
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(Function &) {
|
||||
Frontiers.clear();
|
||||
DominatorTree &DT = getAnalysis<DominatorTree>();
|
||||
Roots = DT.getRoots();
|
||||
assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
|
||||
calculate(DT, DT[Roots[0]]);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<DominatorTree>();
|
||||
}
|
||||
|
||||
const DomSetType &calculate(const DominatorTree &DT,
|
||||
const DomTreeNode *Node);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
289
thirdparty/clang/include/llvm/Analysis/DominatorInternals.h
vendored
Normal file
289
thirdparty/clang/include/llvm/Analysis/DominatorInternals.h
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
//=== llvm/Analysis/DominatorInternals.h - Dominator Calculation -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H
|
||||
#define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DominatorTree construction - This pass constructs immediate dominator
|
||||
// information for a flow-graph based on the algorithm described in this
|
||||
// document:
|
||||
//
|
||||
// A Fast Algorithm for Finding Dominators in a Flowgraph
|
||||
// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141.
|
||||
//
|
||||
// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns
|
||||
// out that the theoretically slower O(n*log(n)) implementation is actually
|
||||
// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<class GraphT>
|
||||
unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V, unsigned N) {
|
||||
// This is more understandable as a recursive algorithm, but we can't use the
|
||||
// recursive algorithm due to stack depth issues. Keep it here for
|
||||
// documentation purposes.
|
||||
#if 0
|
||||
InfoRec &VInfo = DT.Info[DT.Roots[i]];
|
||||
VInfo.DFSNum = VInfo.Semi = ++N;
|
||||
VInfo.Label = V;
|
||||
|
||||
Vertex.push_back(V); // Vertex[n] = V;
|
||||
|
||||
for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
|
||||
InfoRec &SuccVInfo = DT.Info[*SI];
|
||||
if (SuccVInfo.Semi == 0) {
|
||||
SuccVInfo.Parent = V;
|
||||
N = DTDFSPass(DT, *SI, N);
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool IsChildOfArtificialExit = (N != 0);
|
||||
|
||||
SmallVector<std::pair<typename GraphT::NodeType*,
|
||||
typename GraphT::ChildIteratorType>, 32> Worklist;
|
||||
Worklist.push_back(std::make_pair(V, GraphT::child_begin(V)));
|
||||
while (!Worklist.empty()) {
|
||||
typename GraphT::NodeType* BB = Worklist.back().first;
|
||||
typename GraphT::ChildIteratorType NextSucc = Worklist.back().second;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo =
|
||||
DT.Info[BB];
|
||||
|
||||
// First time we visited this BB?
|
||||
if (NextSucc == GraphT::child_begin(BB)) {
|
||||
BBInfo.DFSNum = BBInfo.Semi = ++N;
|
||||
BBInfo.Label = BB;
|
||||
|
||||
DT.Vertex.push_back(BB); // Vertex[n] = V;
|
||||
|
||||
if (IsChildOfArtificialExit)
|
||||
BBInfo.Parent = 1;
|
||||
|
||||
IsChildOfArtificialExit = false;
|
||||
}
|
||||
|
||||
// store the DFS number of the current BB - the reference to BBInfo might
|
||||
// get invalidated when processing the successors.
|
||||
unsigned BBDFSNum = BBInfo.DFSNum;
|
||||
|
||||
// If we are done with this block, remove it from the worklist.
|
||||
if (NextSucc == GraphT::child_end(BB)) {
|
||||
Worklist.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Increment the successor number for the next time we get to it.
|
||||
++Worklist.back().second;
|
||||
|
||||
// Visit the successor next, if it isn't already visited.
|
||||
typename GraphT::NodeType* Succ = *NextSucc;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &SuccVInfo =
|
||||
DT.Info[Succ];
|
||||
if (SuccVInfo.Semi == 0) {
|
||||
SuccVInfo.Parent = BBDFSNum;
|
||||
Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return N;
|
||||
}
|
||||
|
||||
template<class GraphT>
|
||||
typename GraphT::NodeType*
|
||||
Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType *VIn, unsigned LastLinked) {
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo =
|
||||
DT.Info[VIn];
|
||||
if (VInInfo.DFSNum < LastLinked)
|
||||
return VIn;
|
||||
|
||||
SmallVector<typename GraphT::NodeType*, 32> Work;
|
||||
SmallPtrSet<typename GraphT::NodeType*, 32> Visited;
|
||||
|
||||
if (VInInfo.Parent >= LastLinked)
|
||||
Work.push_back(VIn);
|
||||
|
||||
while (!Work.empty()) {
|
||||
typename GraphT::NodeType* V = Work.back();
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
|
||||
DT.Info[V];
|
||||
typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent];
|
||||
|
||||
// Process Ancestor first
|
||||
if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) {
|
||||
Work.push_back(VAncestor);
|
||||
continue;
|
||||
}
|
||||
Work.pop_back();
|
||||
|
||||
// Update VInfo based on Ancestor info
|
||||
if (VInfo.Parent < LastLinked)
|
||||
continue;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo =
|
||||
DT.Info[VAncestor];
|
||||
typename GraphT::NodeType* VAncestorLabel = VAInfo.Label;
|
||||
typename GraphT::NodeType* VLabel = VInfo.Label;
|
||||
if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi)
|
||||
VInfo.Label = VAncestorLabel;
|
||||
VInfo.Parent = VAInfo.Parent;
|
||||
}
|
||||
|
||||
return VInInfo.Label;
|
||||
}
|
||||
|
||||
template<class FuncT, class NodeT>
|
||||
void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
|
||||
FuncT& F) {
|
||||
typedef GraphTraits<NodeT> GraphT;
|
||||
|
||||
unsigned N = 0;
|
||||
bool MultipleRoots = (DT.Roots.size() > 1);
|
||||
if (MultipleRoots) {
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo =
|
||||
DT.Info[NULL];
|
||||
BBInfo.DFSNum = BBInfo.Semi = ++N;
|
||||
BBInfo.Label = NULL;
|
||||
|
||||
DT.Vertex.push_back(NULL); // Vertex[n] = V;
|
||||
}
|
||||
|
||||
// Step #1: Number blocks in depth-first order and initialize variables used
|
||||
// in later stages of the algorithm.
|
||||
for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
|
||||
i != e; ++i)
|
||||
N = DFSPass<GraphT>(DT, DT.Roots[i], N);
|
||||
|
||||
// it might be that some blocks did not get a DFS number (e.g., blocks of
|
||||
// infinite loops). In these cases an artificial exit node is required.
|
||||
MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F));
|
||||
|
||||
// When naively implemented, the Lengauer-Tarjan algorithm requires a separate
|
||||
// bucket for each vertex. However, this is unnecessary, because each vertex
|
||||
// is only placed into a single bucket (that of its semidominator), and each
|
||||
// vertex's bucket is processed before it is added to any bucket itself.
|
||||
//
|
||||
// Instead of using a bucket per vertex, we use a single array Buckets that
|
||||
// has two purposes. Before the vertex V with preorder number i is processed,
|
||||
// Buckets[i] stores the index of the first element in V's bucket. After V's
|
||||
// bucket is processed, Buckets[i] stores the index of the next element in the
|
||||
// bucket containing V, if any.
|
||||
SmallVector<unsigned, 32> Buckets;
|
||||
Buckets.resize(N + 1);
|
||||
for (unsigned i = 1; i <= N; ++i)
|
||||
Buckets[i] = i;
|
||||
|
||||
for (unsigned i = N; i >= 2; --i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo =
|
||||
DT.Info[W];
|
||||
|
||||
// Step #2: Implicitly define the immediate dominator of vertices
|
||||
for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) {
|
||||
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
|
||||
typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1);
|
||||
DT.IDoms[V] = DT.Info[U].Semi < i ? U : W;
|
||||
}
|
||||
|
||||
// Step #3: Calculate the semidominators of all vertices
|
||||
|
||||
// initialize the semi dominator to point to the parent node
|
||||
WInfo.Semi = WInfo.Parent;
|
||||
typedef GraphTraits<Inverse<NodeT> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType CI =
|
||||
InvTraits::child_begin(W),
|
||||
E = InvTraits::child_end(W); CI != E; ++CI) {
|
||||
typename InvTraits::NodeType *N = *CI;
|
||||
if (DT.Info.count(N)) { // Only if this predecessor is reachable!
|
||||
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi;
|
||||
if (SemiU < WInfo.Semi)
|
||||
WInfo.Semi = SemiU;
|
||||
}
|
||||
}
|
||||
|
||||
// If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is
|
||||
// necessarily parent(V). In this case, set idom(V) here and avoid placing
|
||||
// V into a bucket.
|
||||
if (WInfo.Semi == WInfo.Parent) {
|
||||
DT.IDoms[W] = DT.Vertex[WInfo.Parent];
|
||||
} else {
|
||||
Buckets[i] = Buckets[WInfo.Semi];
|
||||
Buckets[WInfo.Semi] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (N >= 1) {
|
||||
typename GraphT::NodeType* Root = DT.Vertex[1];
|
||||
for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) {
|
||||
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
|
||||
DT.IDoms[V] = Root;
|
||||
}
|
||||
}
|
||||
|
||||
// Step #4: Explicitly define the immediate dominator of each vertex
|
||||
for (unsigned i = 2; i <= N; ++i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
typename GraphT::NodeType*& WIDom = DT.IDoms[W];
|
||||
if (WIDom != DT.Vertex[DT.Info[W].Semi])
|
||||
WIDom = DT.IDoms[WIDom];
|
||||
}
|
||||
|
||||
if (DT.Roots.empty()) return;
|
||||
|
||||
// Add a node for the root. This node might be the actual root, if there is
|
||||
// one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0)
|
||||
// which postdominates all real exits if there are multiple exit blocks, or
|
||||
// an infinite loop.
|
||||
typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : 0;
|
||||
|
||||
DT.DomTreeNodes[Root] = DT.RootNode =
|
||||
new DomTreeNodeBase<typename GraphT::NodeType>(Root, 0);
|
||||
|
||||
// Loop over all of the reachable blocks in the function...
|
||||
for (unsigned i = 2; i <= N; ++i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W];
|
||||
if (BBNode) continue; // Haven't calculated this node yet?
|
||||
|
||||
typename GraphT::NodeType* ImmDom = DT.getIDom(W);
|
||||
|
||||
assert(ImmDom || DT.DomTreeNodes[NULL]);
|
||||
|
||||
// Get or calculate the node for the immediate dominator
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *IDomNode =
|
||||
DT.getNodeForBlock(ImmDom);
|
||||
|
||||
// Add a new tree node for this BasicBlock, and link it as a child of
|
||||
// IDomNode
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *C =
|
||||
new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode);
|
||||
DT.DomTreeNodes[W] = IDomNode->addChild(C);
|
||||
}
|
||||
|
||||
// Free temporary memory used to construct idom's
|
||||
DT.IDoms.clear();
|
||||
DT.Info.clear();
|
||||
std::vector<typename GraphT::NodeType*>().swap(DT.Vertex);
|
||||
|
||||
DT.updateDFSNumbers();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
920
thirdparty/clang/include/llvm/Analysis/Dominators.h
vendored
Normal file
920
thirdparty/clang/include/llvm/Analysis/Dominators.h
vendored
Normal file
@@ -0,0 +1,920 @@
|
||||
//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- 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 DominatorTree class, which provides fast and efficient
|
||||
// dominance queries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINATORS_H
|
||||
#define LLVM_ANALYSIS_DOMINATORS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DepthFirstIterator.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominatorBase - Base class that other, more interesting dominator analyses
|
||||
/// inherit from.
|
||||
///
|
||||
template <class NodeT>
|
||||
class DominatorBase {
|
||||
protected:
|
||||
std::vector<NodeT*> Roots;
|
||||
const bool IsPostDominators;
|
||||
inline explicit DominatorBase(bool isPostDom) :
|
||||
Roots(), IsPostDominators(isPostDom) {}
|
||||
public:
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<NodeT*> &getRoots() const { return Roots; }
|
||||
|
||||
/// isPostDominator - Returns true if analysis based of postdoms
|
||||
///
|
||||
bool isPostDominator() const { return IsPostDominators; }
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DomTreeNode - Dominator Tree Node
|
||||
template<class NodeT> class DominatorTreeBase;
|
||||
struct PostDominatorTree;
|
||||
class MachineBasicBlock;
|
||||
|
||||
template <class NodeT>
|
||||
class DomTreeNodeBase {
|
||||
NodeT *TheBB;
|
||||
DomTreeNodeBase<NodeT> *IDom;
|
||||
std::vector<DomTreeNodeBase<NodeT> *> Children;
|
||||
int DFSNumIn, DFSNumOut;
|
||||
|
||||
template<class N> friend class DominatorTreeBase;
|
||||
friend struct PostDominatorTree;
|
||||
public:
|
||||
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
|
||||
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator
|
||||
const_iterator;
|
||||
|
||||
iterator begin() { return Children.begin(); }
|
||||
iterator end() { return Children.end(); }
|
||||
const_iterator begin() const { return Children.begin(); }
|
||||
const_iterator end() const { return Children.end(); }
|
||||
|
||||
NodeT *getBlock() const { return TheBB; }
|
||||
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
|
||||
const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const {
|
||||
return Children;
|
||||
}
|
||||
|
||||
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
|
||||
: TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { }
|
||||
|
||||
DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
|
||||
Children.push_back(C);
|
||||
return C;
|
||||
}
|
||||
|
||||
size_t getNumChildren() const {
|
||||
return Children.size();
|
||||
}
|
||||
|
||||
void clearAllChildren() {
|
||||
Children.clear();
|
||||
}
|
||||
|
||||
bool compare(const DomTreeNodeBase<NodeT> *Other) const {
|
||||
if (getNumChildren() != Other->getNumChildren())
|
||||
return true;
|
||||
|
||||
SmallPtrSet<const NodeT *, 4> OtherChildren;
|
||||
for (const_iterator I = Other->begin(), E = Other->end(); I != E; ++I) {
|
||||
const NodeT *Nd = (*I)->getBlock();
|
||||
OtherChildren.insert(Nd);
|
||||
}
|
||||
|
||||
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
||||
const NodeT *N = (*I)->getBlock();
|
||||
if (OtherChildren.count(N) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setIDom(DomTreeNodeBase<NodeT> *NewIDom) {
|
||||
assert(IDom && "No immediate dominator?");
|
||||
if (IDom != NewIDom) {
|
||||
typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
|
||||
std::find(IDom->Children.begin(), IDom->Children.end(), this);
|
||||
assert(I != IDom->Children.end() &&
|
||||
"Not in immediate dominator children set!");
|
||||
// I am no longer your child...
|
||||
IDom->Children.erase(I);
|
||||
|
||||
// Switch to new dominator
|
||||
IDom = NewIDom;
|
||||
IDom->Children.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do
|
||||
/// not call them.
|
||||
unsigned getDFSNumIn() const { return DFSNumIn; }
|
||||
unsigned getDFSNumOut() const { return DFSNumOut; }
|
||||
private:
|
||||
// Return true if this node is dominated by other. Use this only if DFS info
|
||||
// is valid.
|
||||
bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const {
|
||||
return this->DFSNumIn >= other->DFSNumIn &&
|
||||
this->DFSNumOut <= other->DFSNumOut;
|
||||
}
|
||||
};
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<MachineBasicBlock>);
|
||||
|
||||
template<class NodeT>
|
||||
inline raw_ostream &operator<<(raw_ostream &o,
|
||||
const DomTreeNodeBase<NodeT> *Node) {
|
||||
if (Node->getBlock())
|
||||
WriteAsOperand(o, Node->getBlock(), false);
|
||||
else
|
||||
o << " <<exit node>>";
|
||||
|
||||
o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
|
||||
|
||||
return o << "\n";
|
||||
}
|
||||
|
||||
template<class NodeT>
|
||||
inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
|
||||
unsigned Lev) {
|
||||
o.indent(2*Lev) << "[" << Lev << "] " << N;
|
||||
for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(),
|
||||
E = N->end(); I != E; ++I)
|
||||
PrintDomTree<NodeT>(*I, o, Lev+1);
|
||||
}
|
||||
|
||||
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominatorTree - Calculate the immediate dominator tree for a function.
|
||||
///
|
||||
|
||||
template<class FuncT, class N>
|
||||
void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
|
||||
FuncT& F);
|
||||
|
||||
template<class NodeT>
|
||||
class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) const {
|
||||
assert(A != B);
|
||||
assert(isReachableFromEntry(B));
|
||||
assert(isReachableFromEntry(A));
|
||||
|
||||
const DomTreeNodeBase<NodeT> *IDom;
|
||||
while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B)
|
||||
B = IDom; // Walk up the tree
|
||||
return IDom != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
|
||||
DomTreeNodeMapType DomTreeNodes;
|
||||
DomTreeNodeBase<NodeT> *RootNode;
|
||||
|
||||
bool DFSInfoValid;
|
||||
unsigned int SlowQueries;
|
||||
// Information record used during immediate dominators computation.
|
||||
struct InfoRec {
|
||||
unsigned DFSNum;
|
||||
unsigned Parent;
|
||||
unsigned Semi;
|
||||
NodeT *Label;
|
||||
|
||||
InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {}
|
||||
};
|
||||
|
||||
DenseMap<NodeT*, NodeT*> IDoms;
|
||||
|
||||
// Vertex - Map the DFS number to the BasicBlock*
|
||||
std::vector<NodeT*> Vertex;
|
||||
|
||||
// Info - Collection of information used during the computation of idoms.
|
||||
DenseMap<NodeT*, InfoRec> Info;
|
||||
|
||||
void reset() {
|
||||
for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
|
||||
E = DomTreeNodes.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
DomTreeNodes.clear();
|
||||
IDoms.clear();
|
||||
this->Roots.clear();
|
||||
Vertex.clear();
|
||||
RootNode = 0;
|
||||
}
|
||||
|
||||
// NewBB is split and now it has one successor. Update dominator tree to
|
||||
// reflect this change.
|
||||
template<class N, class GraphT>
|
||||
void Split(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* NewBB) {
|
||||
assert(std::distance(GraphT::child_begin(NewBB),
|
||||
GraphT::child_end(NewBB)) == 1 &&
|
||||
"NewBB should have a single successor!");
|
||||
typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
|
||||
|
||||
std::vector<typename GraphT::NodeType*> PredBlocks;
|
||||
typedef GraphTraits<Inverse<N> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBB),
|
||||
PE = InvTraits::child_end(NewBB); PI != PE; ++PI)
|
||||
PredBlocks.push_back(*PI);
|
||||
|
||||
assert(!PredBlocks.empty() && "No predblocks?");
|
||||
|
||||
bool NewBBDominatesNewBBSucc = true;
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBBSucc),
|
||||
E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) {
|
||||
typename InvTraits::NodeType *ND = *PI;
|
||||
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
|
||||
DT.isReachableFromEntry(ND)) {
|
||||
NewBBDominatesNewBBSucc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find NewBB's immediate dominator and create new dominator tree node for
|
||||
// NewBB.
|
||||
NodeT *NewBBIDom = 0;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < PredBlocks.size(); ++i)
|
||||
if (DT.isReachableFromEntry(PredBlocks[i])) {
|
||||
NewBBIDom = PredBlocks[i];
|
||||
break;
|
||||
}
|
||||
|
||||
// It's possible that none of the predecessors of NewBB are reachable;
|
||||
// in that case, NewBB itself is unreachable, so nothing needs to be
|
||||
// changed.
|
||||
if (!NewBBIDom)
|
||||
return;
|
||||
|
||||
for (i = i + 1; i < PredBlocks.size(); ++i) {
|
||||
if (DT.isReachableFromEntry(PredBlocks[i]))
|
||||
NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
|
||||
}
|
||||
|
||||
// Create the new dominator tree node... and set the idom of NewBB.
|
||||
DomTreeNodeBase<NodeT> *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom);
|
||||
|
||||
// If NewBB strictly dominates other blocks, then it is now the immediate
|
||||
// dominator of NewBBSucc. Update the dominator tree as appropriate.
|
||||
if (NewBBDominatesNewBBSucc) {
|
||||
DomTreeNodeBase<NodeT> *NewBBSuccNode = DT.getNode(NewBBSucc);
|
||||
DT.changeImmediateDominator(NewBBSuccNode, NewBBNode);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit DominatorTreeBase(bool isPostDom)
|
||||
: DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
|
||||
virtual ~DominatorTreeBase() { reset(); }
|
||||
|
||||
/// compare - Return false if the other dominator tree base matches this
|
||||
/// dominator tree base. Otherwise return true.
|
||||
bool compare(DominatorTreeBase &Other) const {
|
||||
|
||||
const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes;
|
||||
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
|
||||
return true;
|
||||
|
||||
for (typename DomTreeNodeMapType::const_iterator
|
||||
I = this->DomTreeNodes.begin(),
|
||||
E = this->DomTreeNodes.end(); I != E; ++I) {
|
||||
NodeT *BB = I->first;
|
||||
typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB);
|
||||
if (OI == OtherDomTreeNodes.end())
|
||||
return true;
|
||||
|
||||
DomTreeNodeBase<NodeT>* MyNd = I->second;
|
||||
DomTreeNodeBase<NodeT>* OtherNd = OI->second;
|
||||
|
||||
if (MyNd->compare(OtherNd))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void releaseMemory() { reset(); }
|
||||
|
||||
/// getNode - return the (Post)DominatorTree node for the specified basic
|
||||
/// block. This is the same as using operator[] on this class.
|
||||
///
|
||||
inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
|
||||
return DomTreeNodes.lookup(BB);
|
||||
}
|
||||
|
||||
/// getRootNode - This returns the entry node for the CFG of the function. If
|
||||
/// this tree represents the post-dominance relations for a function, however,
|
||||
/// this root may be a node with the block == NULL. This is the case when
|
||||
/// there are multiple exit nodes from a particular function. Consumers of
|
||||
/// post-dominance information must be capable of dealing with this
|
||||
/// possibility.
|
||||
///
|
||||
DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; }
|
||||
const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; }
|
||||
|
||||
/// properlyDominates - Returns true iff A dominates B and A != B.
|
||||
/// Note that this is not a constant time operation!
|
||||
///
|
||||
bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
if (A == 0 || B == 0)
|
||||
return false;
|
||||
if (A == B)
|
||||
return false;
|
||||
return dominates(A, B);
|
||||
}
|
||||
|
||||
bool properlyDominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
/// isReachableFromEntry - Return true if A is dominated by the entry
|
||||
/// block of the function containing it.
|
||||
bool isReachableFromEntry(const NodeT* A) const {
|
||||
assert(!this->isPostDominator() &&
|
||||
"This is not implemented for post dominators");
|
||||
return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
|
||||
}
|
||||
|
||||
inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const {
|
||||
return A;
|
||||
}
|
||||
|
||||
/// dominates - Returns true iff A dominates B. Note that this is not a
|
||||
/// constant time operation!
|
||||
///
|
||||
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
// A node trivially dominates itself.
|
||||
if (B == A)
|
||||
return true;
|
||||
|
||||
// An unreachable node is dominated by anything.
|
||||
if (!isReachableFromEntry(B))
|
||||
return true;
|
||||
|
||||
// And dominates nothing.
|
||||
if (!isReachableFromEntry(A))
|
||||
return false;
|
||||
|
||||
// Compare the result of the tree walk and the dfs numbers, if expensive
|
||||
// checks are enabled.
|
||||
#ifdef XDEBUG
|
||||
assert((!DFSInfoValid ||
|
||||
(dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
|
||||
"Tree walk disagrees with dfs numbers!");
|
||||
#endif
|
||||
|
||||
if (DFSInfoValid)
|
||||
return B->DominatedBy(A);
|
||||
|
||||
// If we end up with too many slow queries, just update the
|
||||
// DFS numbers on the theory that we are going to keep querying.
|
||||
SlowQueries++;
|
||||
if (SlowQueries > 32) {
|
||||
updateDFSNumbers();
|
||||
return B->DominatedBy(A);
|
||||
}
|
||||
|
||||
return dominatedBySlowTreeWalk(A, B);
|
||||
}
|
||||
|
||||
bool dominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
NodeT *getRoot() const {
|
||||
assert(this->Roots.size() == 1 && "Should always have entry node!");
|
||||
return this->Roots[0];
|
||||
}
|
||||
|
||||
/// findNearestCommonDominator - Find nearest common dominator basic block
|
||||
/// for basic block A and B. If there is no such block then return NULL.
|
||||
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
|
||||
assert(A->getParent() == B->getParent() &&
|
||||
"Two blocks are not in same function");
|
||||
|
||||
// If either A or B is a entry block then it is nearest common dominator
|
||||
// (for forward-dominators).
|
||||
if (!this->isPostDominator()) {
|
||||
NodeT &Entry = A->getParent()->front();
|
||||
if (A == &Entry || B == &Entry)
|
||||
return &Entry;
|
||||
}
|
||||
|
||||
// If B dominates A then B is nearest common dominator.
|
||||
if (dominates(B, A))
|
||||
return B;
|
||||
|
||||
// If A dominates B then A is nearest common dominator.
|
||||
if (dominates(A, B))
|
||||
return A;
|
||||
|
||||
DomTreeNodeBase<NodeT> *NodeA = getNode(A);
|
||||
DomTreeNodeBase<NodeT> *NodeB = getNode(B);
|
||||
|
||||
// Collect NodeA dominators set.
|
||||
SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms;
|
||||
NodeADoms.insert(NodeA);
|
||||
DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom();
|
||||
while (IDomA) {
|
||||
NodeADoms.insert(IDomA);
|
||||
IDomA = IDomA->getIDom();
|
||||
}
|
||||
|
||||
// Walk NodeB immediate dominators chain and find common dominator node.
|
||||
DomTreeNodeBase<NodeT> *IDomB = NodeB->getIDom();
|
||||
while (IDomB) {
|
||||
if (NodeADoms.count(IDomB) != 0)
|
||||
return IDomB->getBlock();
|
||||
|
||||
IDomB = IDomB->getIDom();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) {
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// const is re-introduced on the return type.
|
||||
return findNearestCommonDominator(const_cast<NodeT *>(A),
|
||||
const_cast<NodeT *>(B));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// API to update (Post)DominatorTree information based on modifications to
|
||||
// the CFG...
|
||||
|
||||
/// addNewBlock - Add a new node to the dominator tree information. This
|
||||
/// creates a new node as a child of DomBB dominator node,linking it into
|
||||
/// the children list of the immediate dominator.
|
||||
DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) {
|
||||
assert(getNode(BB) == 0 && "Block already in dominator tree!");
|
||||
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
|
||||
assert(IDomNode && "Not immediate dominator specified for block!");
|
||||
DFSInfoValid = false;
|
||||
return DomTreeNodes[BB] =
|
||||
IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
|
||||
}
|
||||
|
||||
/// changeImmediateDominator - This method is used to update the dominator
|
||||
/// tree information when a node's immediate dominator changes.
|
||||
///
|
||||
void changeImmediateDominator(DomTreeNodeBase<NodeT> *N,
|
||||
DomTreeNodeBase<NodeT> *NewIDom) {
|
||||
assert(N && NewIDom && "Cannot change null node pointers!");
|
||||
DFSInfoValid = false;
|
||||
N->setIDom(NewIDom);
|
||||
}
|
||||
|
||||
void changeImmediateDominator(NodeT *BB, NodeT *NewBB) {
|
||||
changeImmediateDominator(getNode(BB), getNode(NewBB));
|
||||
}
|
||||
|
||||
/// eraseNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Removes node from its immediate dominator's
|
||||
/// children list. Deletes dominator node associated with basic block BB.
|
||||
void eraseNode(NodeT *BB) {
|
||||
DomTreeNodeBase<NodeT> *Node = getNode(BB);
|
||||
assert(Node && "Removing node that isn't in dominator tree.");
|
||||
assert(Node->getChildren().empty() && "Node is not a leaf node.");
|
||||
|
||||
// Remove node from immediate dominator's children list.
|
||||
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
|
||||
if (IDom) {
|
||||
typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
|
||||
std::find(IDom->Children.begin(), IDom->Children.end(), Node);
|
||||
assert(I != IDom->Children.end() &&
|
||||
"Not in immediate dominator children set!");
|
||||
// I am no longer your child...
|
||||
IDom->Children.erase(I);
|
||||
}
|
||||
|
||||
DomTreeNodes.erase(BB);
|
||||
delete Node;
|
||||
}
|
||||
|
||||
/// removeNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Invalidates any node pointing to removed
|
||||
/// block.
|
||||
void removeNode(NodeT *BB) {
|
||||
assert(getNode(BB) && "Removing node that isn't in dominator tree.");
|
||||
DomTreeNodes.erase(BB);
|
||||
}
|
||||
|
||||
/// splitBlock - BB is split and now it has one successor. Update dominator
|
||||
/// tree to reflect this change.
|
||||
void splitBlock(NodeT* NewBB) {
|
||||
if (this->IsPostDominators)
|
||||
this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB);
|
||||
else
|
||||
this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB);
|
||||
}
|
||||
|
||||
/// print - Convert to human readable form
|
||||
///
|
||||
void print(raw_ostream &o) const {
|
||||
o << "=============================--------------------------------\n";
|
||||
if (this->isPostDominator())
|
||||
o << "Inorder PostDominator Tree: ";
|
||||
else
|
||||
o << "Inorder Dominator Tree: ";
|
||||
if (!this->DFSInfoValid)
|
||||
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
|
||||
o << "\n";
|
||||
|
||||
// The postdom tree can have a null root if there are no returns.
|
||||
if (getRootNode())
|
||||
PrintDomTree<NodeT>(getRootNode(), o, 1);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<class GraphT>
|
||||
friend typename GraphT::NodeType* Eval(
|
||||
DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V,
|
||||
unsigned LastLinked);
|
||||
|
||||
template<class GraphT>
|
||||
friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V,
|
||||
unsigned N);
|
||||
|
||||
template<class FuncT, class N>
|
||||
friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
|
||||
FuncT& F);
|
||||
|
||||
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
|
||||
/// dominator tree in dfs order.
|
||||
void updateDFSNumbers() {
|
||||
unsigned DFSNum = 0;
|
||||
|
||||
SmallVector<std::pair<DomTreeNodeBase<NodeT>*,
|
||||
typename DomTreeNodeBase<NodeT>::iterator>, 32> WorkStack;
|
||||
|
||||
DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
|
||||
|
||||
if (!ThisRoot)
|
||||
return;
|
||||
|
||||
// Even in the case of multiple exits that form the post dominator root
|
||||
// nodes, do not iterate over all exits, but start from the virtual root
|
||||
// node. Otherwise bbs, that are not post dominated by any exit but by the
|
||||
// virtual root node, will never be assigned a DFS number.
|
||||
WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin()));
|
||||
ThisRoot->DFSNumIn = DFSNum++;
|
||||
|
||||
while (!WorkStack.empty()) {
|
||||
DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
|
||||
typename DomTreeNodeBase<NodeT>::iterator ChildIt =
|
||||
WorkStack.back().second;
|
||||
|
||||
// If we visited all of the children of this node, "recurse" back up the
|
||||
// stack setting the DFOutNum.
|
||||
if (ChildIt == Node->end()) {
|
||||
Node->DFSNumOut = DFSNum++;
|
||||
WorkStack.pop_back();
|
||||
} else {
|
||||
// Otherwise, recursively visit this child.
|
||||
DomTreeNodeBase<NodeT> *Child = *ChildIt;
|
||||
++WorkStack.back().second;
|
||||
|
||||
WorkStack.push_back(std::make_pair(Child, Child->begin()));
|
||||
Child->DFSNumIn = DFSNum++;
|
||||
}
|
||||
}
|
||||
|
||||
SlowQueries = 0;
|
||||
DFSInfoValid = true;
|
||||
}
|
||||
|
||||
DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
|
||||
if (DomTreeNodeBase<NodeT> *Node = getNode(BB))
|
||||
return Node;
|
||||
|
||||
// Haven't calculated this node yet? Get or calculate the node for the
|
||||
// immediate dominator.
|
||||
NodeT *IDom = getIDom(BB);
|
||||
|
||||
assert(IDom || this->DomTreeNodes[NULL]);
|
||||
DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
|
||||
|
||||
// Add a new tree node for this BasicBlock, and link it as a child of
|
||||
// IDomNode
|
||||
DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
|
||||
return this->DomTreeNodes[BB] = IDomNode->addChild(C);
|
||||
}
|
||||
|
||||
inline NodeT *getIDom(NodeT *BB) const {
|
||||
return IDoms.lookup(BB);
|
||||
}
|
||||
|
||||
inline void addRoot(NodeT* BB) {
|
||||
this->Roots.push_back(BB);
|
||||
}
|
||||
|
||||
public:
|
||||
/// recalculate - compute a dominator tree for the given function
|
||||
template<class FT>
|
||||
void recalculate(FT& F) {
|
||||
typedef GraphTraits<FT*> TraitsTy;
|
||||
reset();
|
||||
this->Vertex.push_back(0);
|
||||
|
||||
if (!this->IsPostDominators) {
|
||||
// Initialize root
|
||||
NodeT *entry = TraitsTy::getEntryNode(&F);
|
||||
this->Roots.push_back(entry);
|
||||
this->IDoms[entry] = 0;
|
||||
this->DomTreeNodes[entry] = 0;
|
||||
|
||||
Calculate<FT, NodeT*>(*this, F);
|
||||
} else {
|
||||
// Initialize the roots list
|
||||
for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
|
||||
E = TraitsTy::nodes_end(&F); I != E; ++I) {
|
||||
if (TraitsTy::child_begin(I) == TraitsTy::child_end(I))
|
||||
addRoot(I);
|
||||
|
||||
// Prepopulate maps so that we don't get iterator invalidation issues later.
|
||||
this->IDoms[I] = 0;
|
||||
this->DomTreeNodes[I] = 0;
|
||||
}
|
||||
|
||||
Calculate<FT, Inverse<NodeT*> >(*this, F);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// These two functions are declared out of line as a workaround for building
|
||||
// with old (< r147295) versions of clang because of pr11642.
|
||||
template<class NodeT>
|
||||
bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return true;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
template<class NodeT>
|
||||
bool
|
||||
DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return false;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
|
||||
|
||||
class BasicBlockEdge {
|
||||
const BasicBlock *Start;
|
||||
const BasicBlock *End;
|
||||
public:
|
||||
BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) :
|
||||
Start(Start_), End(End_) { }
|
||||
const BasicBlock *getStart() const {
|
||||
return Start;
|
||||
}
|
||||
const BasicBlock *getEnd() const {
|
||||
return End;
|
||||
}
|
||||
bool isSingleEdge() const;
|
||||
};
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
|
||||
/// compute a normal dominator tree.
|
||||
///
|
||||
class DominatorTree : public FunctionPass {
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
DominatorTreeBase<BasicBlock>* DT;
|
||||
|
||||
DominatorTree() : FunctionPass(ID) {
|
||||
initializeDominatorTreePass(*PassRegistry::getPassRegistry());
|
||||
DT = new DominatorTreeBase<BasicBlock>(false);
|
||||
}
|
||||
|
||||
~DominatorTree() {
|
||||
delete DT;
|
||||
}
|
||||
|
||||
DominatorTreeBase<BasicBlock>& getBase() { return *DT; }
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<BasicBlock*> &getRoots() const {
|
||||
return DT->getRoots();
|
||||
}
|
||||
|
||||
inline BasicBlock *getRoot() const {
|
||||
return DT->getRoot();
|
||||
}
|
||||
|
||||
inline DomTreeNode *getRootNode() const {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
/// compare - Return false if the other dominator tree matches this
|
||||
/// dominator tree. Otherwise return true.
|
||||
inline bool compare(DominatorTree &Other) const {
|
||||
DomTreeNode *R = getRootNode();
|
||||
DomTreeNode *OtherR = Other.getRootNode();
|
||||
|
||||
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
|
||||
return true;
|
||||
|
||||
if (DT->compare(Other.getBase()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
// dominates - Return true if Def dominates a use in User. This performs
|
||||
// the special checks necessary if Def and User are in the same basic block.
|
||||
// Note that Def doesn't dominate a use in Def itself!
|
||||
bool dominates(const Instruction *Def, const Use &U) const;
|
||||
bool dominates(const Instruction *Def, const Instruction *User) const;
|
||||
bool dominates(const Instruction *Def, const BasicBlock *BB) const;
|
||||
bool dominates(const BasicBlockEdge &BBE, const Use &U) const;
|
||||
bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const;
|
||||
|
||||
bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
/// findNearestCommonDominator - Find nearest common dominator basic block
|
||||
/// for basic block A and B. If there is no such block then return NULL.
|
||||
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A,
|
||||
const BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
inline DomTreeNode *operator[](BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
/// getNode - return the (Post)DominatorTree node for the specified basic
|
||||
/// block. This is the same as using operator[] on this class.
|
||||
///
|
||||
inline DomTreeNode *getNode(BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
/// addNewBlock - Add a new node to the dominator tree information. This
|
||||
/// creates a new node as a child of DomBB dominator node,linking it into
|
||||
/// the children list of the immediate dominator.
|
||||
inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) {
|
||||
return DT->addNewBlock(BB, DomBB);
|
||||
}
|
||||
|
||||
/// changeImmediateDominator - This method is used to update the dominator
|
||||
/// tree information when a node's immediate dominator changes.
|
||||
///
|
||||
inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) {
|
||||
DT->changeImmediateDominator(N, NewIDom);
|
||||
}
|
||||
|
||||
inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) {
|
||||
DT->changeImmediateDominator(N, NewIDom);
|
||||
}
|
||||
|
||||
/// eraseNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Removes node from its immediate dominator's
|
||||
/// children list. Deletes dominator node associated with basic block BB.
|
||||
inline void eraseNode(BasicBlock *BB) {
|
||||
DT->eraseNode(BB);
|
||||
}
|
||||
|
||||
/// splitBlock - BB is split and now it has one successor. Update dominator
|
||||
/// tree to reflect this change.
|
||||
inline void splitBlock(BasicBlock* NewBB) {
|
||||
DT->splitBlock(NewBB);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const BasicBlock* A) const {
|
||||
return DT->isReachableFromEntry(A);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const Use &U) const;
|
||||
|
||||
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS, const Module* M= 0) const;
|
||||
};
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominatorTree GraphTraits specialization so the DominatorTree can be
|
||||
/// iterable by generic graph iterators.
|
||||
///
|
||||
template <> struct GraphTraits<DomTreeNode*> {
|
||||
typedef DomTreeNode NodeType;
|
||||
typedef NodeType::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(NodeType *N) {
|
||||
return N;
|
||||
}
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
|
||||
typedef df_iterator<DomTreeNode*> nodes_iterator;
|
||||
|
||||
static nodes_iterator nodes_begin(DomTreeNode *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(DomTreeNode *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<DominatorTree*>
|
||||
: public GraphTraits<DomTreeNode*> {
|
||||
static NodeType *getEntryNode(DominatorTree *DT) {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(DominatorTree *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(DominatorTree *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
66
thirdparty/clang/include/llvm/Analysis/FindUsedTypes.h
vendored
Normal file
66
thirdparty/clang/include/llvm/Analysis/FindUsedTypes.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass is used to seek out all of the types in use by the program.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H
|
||||
#define LLVM_ANALYSIS_FINDUSEDTYPES_H
|
||||
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
class FindUsedTypes : public ModulePass {
|
||||
SetVector<Type *> UsedTypes;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
FindUsedTypes() : ModulePass(ID) {
|
||||
initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
/// getTypes - After the pass has been run, return the set containing all of
|
||||
/// the types used in the module.
|
||||
///
|
||||
const SetVector<Type *> &getTypes() const { return UsedTypes; }
|
||||
|
||||
/// Print the types found in the module. If the optional Module parameter is
|
||||
/// passed in, then the types are printed symbolically if possible, using the
|
||||
/// symbol table from the module.
|
||||
///
|
||||
void print(raw_ostream &o, const Module *M) const;
|
||||
|
||||
private:
|
||||
/// IncorporateType - Incorporate one type and all of its subtypes into the
|
||||
/// collection of used types.
|
||||
///
|
||||
void IncorporateType(Type *Ty);
|
||||
|
||||
/// IncorporateValue - Incorporate all of the types used by this value.
|
||||
///
|
||||
void IncorporateValue(const Value *V);
|
||||
|
||||
public:
|
||||
/// run - This incorporates all types used by the specified module
|
||||
bool runOnModule(Module &M);
|
||||
|
||||
/// getAnalysisUsage - We do not modify anything.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
184
thirdparty/clang/include/llvm/Analysis/IVUsers.h
vendored
Normal file
184
thirdparty/clang/include/llvm/Analysis/IVUsers.h
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- 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 bookkeeping for "interesting" users of expressions
|
||||
// computed from induction variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_IVUSERS_H
|
||||
#define LLVM_ANALYSIS_IVUSERS_H
|
||||
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionNormalization.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class Value;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class IVUsers;
|
||||
class DataLayout;
|
||||
|
||||
/// IVStrideUse - Keep track of one use of a strided induction variable.
|
||||
/// The Expr member keeps track of the expression, User is the actual user
|
||||
/// instruction of the operand, and 'OperandValToReplace' is the operand of
|
||||
/// the User that is the use.
|
||||
class IVStrideUse : public CallbackVH, public ilist_node<IVStrideUse> {
|
||||
friend class IVUsers;
|
||||
public:
|
||||
IVStrideUse(IVUsers *P, Instruction* U, Value *O)
|
||||
: CallbackVH(U), Parent(P), OperandValToReplace(O) {
|
||||
}
|
||||
|
||||
/// getUser - Return the user instruction for this use.
|
||||
Instruction *getUser() const {
|
||||
return cast<Instruction>(getValPtr());
|
||||
}
|
||||
|
||||
/// setUser - Assign a new user instruction for this use.
|
||||
void setUser(Instruction *NewUser) {
|
||||
setValPtr(NewUser);
|
||||
}
|
||||
|
||||
/// getOperandValToReplace - Return the Value of the operand in the user
|
||||
/// instruction that this IVStrideUse is representing.
|
||||
Value *getOperandValToReplace() const {
|
||||
return OperandValToReplace;
|
||||
}
|
||||
|
||||
/// setOperandValToReplace - Assign a new Value as the operand value
|
||||
/// to replace.
|
||||
void setOperandValToReplace(Value *Op) {
|
||||
OperandValToReplace = Op;
|
||||
}
|
||||
|
||||
/// getPostIncLoops - Return the set of loops for which the expression has
|
||||
/// been adjusted to use post-inc mode.
|
||||
const PostIncLoopSet &getPostIncLoops() const {
|
||||
return PostIncLoops;
|
||||
}
|
||||
|
||||
/// transformToPostInc - Transform the expression to post-inc form for the
|
||||
/// given loop.
|
||||
void transformToPostInc(const Loop *L);
|
||||
|
||||
private:
|
||||
/// Parent - a pointer to the IVUsers that owns this IVStrideUse.
|
||||
IVUsers *Parent;
|
||||
|
||||
/// OperandValToReplace - The Value of the operand in the user instruction
|
||||
/// that this IVStrideUse is representing.
|
||||
WeakVH OperandValToReplace;
|
||||
|
||||
/// PostIncLoops - The set of loops for which Expr has been adjusted to
|
||||
/// use post-inc mode. This corresponds with SCEVExpander's post-inc concept.
|
||||
PostIncLoopSet PostIncLoops;
|
||||
|
||||
/// Deleted - Implementation of CallbackVH virtual function to
|
||||
/// receive notification when the User is deleted.
|
||||
virtual void deleted();
|
||||
};
|
||||
|
||||
template<> struct ilist_traits<IVStrideUse>
|
||||
: public ilist_default_traits<IVStrideUse> {
|
||||
// createSentinel is used to get hold of a node that marks the end of
|
||||
// the list...
|
||||
// The sentinel is relative to this instance, so we use a non-static
|
||||
// method.
|
||||
IVStrideUse *createSentinel() const {
|
||||
// since i(p)lists always publicly derive from the corresponding
|
||||
// traits, placing a data member in this class will augment i(p)list.
|
||||
// But since the NodeTy is expected to publicly derive from
|
||||
// ilist_node<NodeTy>, there is a legal viable downcast from it
|
||||
// to NodeTy. We use this trick to superpose i(p)list with a "ghostly"
|
||||
// NodeTy, which becomes the sentinel. Dereferencing the sentinel is
|
||||
// forbidden (save the ilist_node<NodeTy>) so no one will ever notice
|
||||
// the superposition.
|
||||
return static_cast<IVStrideUse*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(IVStrideUse*) {}
|
||||
|
||||
IVStrideUse *provideInitialHead() const { return createSentinel(); }
|
||||
IVStrideUse *ensureHead(IVStrideUse*) const { return createSentinel(); }
|
||||
static void noteHead(IVStrideUse*, IVStrideUse*) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<IVStrideUse> Sentinel;
|
||||
};
|
||||
|
||||
class IVUsers : public LoopPass {
|
||||
friend class IVStrideUse;
|
||||
Loop *L;
|
||||
LoopInfo *LI;
|
||||
DominatorTree *DT;
|
||||
ScalarEvolution *SE;
|
||||
DataLayout *TD;
|
||||
SmallPtrSet<Instruction*,16> Processed;
|
||||
|
||||
/// IVUses - A list of all tracked IV uses of induction variable expressions
|
||||
/// we are interested in.
|
||||
ilist<IVStrideUse> IVUses;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
|
||||
|
||||
virtual void releaseMemory();
|
||||
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
IVUsers();
|
||||
|
||||
Loop *getLoop() const { return L; }
|
||||
|
||||
/// AddUsersIfInteresting - Inspect the specified Instruction. If it is a
|
||||
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
|
||||
/// return true. Otherwise, return false.
|
||||
bool AddUsersIfInteresting(Instruction *I);
|
||||
|
||||
IVStrideUse &AddUser(Instruction *User, Value *Operand);
|
||||
|
||||
/// getReplacementExpr - Return a SCEV expression which computes the
|
||||
/// value of the OperandValToReplace of the given IVStrideUse.
|
||||
const SCEV *getReplacementExpr(const IVStrideUse &IU) const;
|
||||
|
||||
/// getExpr - Return the expression for the use.
|
||||
const SCEV *getExpr(const IVStrideUse &IU) const;
|
||||
|
||||
const SCEV *getStride(const IVStrideUse &IU, const Loop *L) const;
|
||||
|
||||
typedef ilist<IVStrideUse>::iterator iterator;
|
||||
typedef ilist<IVStrideUse>::const_iterator const_iterator;
|
||||
iterator begin() { return IVUses.begin(); }
|
||||
iterator end() { return IVUses.end(); }
|
||||
const_iterator begin() const { return IVUses.begin(); }
|
||||
const_iterator end() const { return IVUses.end(); }
|
||||
bool empty() const { return IVUses.empty(); }
|
||||
|
||||
bool isIVUserOrOperand(Instruction *Inst) const {
|
||||
return Processed.count(Inst);
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS, const Module* = 0) const;
|
||||
|
||||
/// dump - This method is used for debugging.
|
||||
void dump() const;
|
||||
protected:
|
||||
bool AddUsersImpl(Instruction *I, SmallPtrSet<Loop*,16> &SimpleLoopNests);
|
||||
};
|
||||
|
||||
Pass *createIVUsersPass();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
143
thirdparty/clang/include/llvm/Analysis/InlineCost.h
vendored
Normal file
143
thirdparty/clang/include/llvm/Analysis/InlineCost.h
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
//===- InlineCost.h - Cost analysis for inliner -----------------*- 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 heuristics for inlining decisions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INLINECOST_H
|
||||
#define LLVM_ANALYSIS_INLINECOST_H
|
||||
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
|
||||
namespace llvm {
|
||||
class CallSite;
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class TargetTransformInfo;
|
||||
|
||||
namespace InlineConstants {
|
||||
// Various magic constants used to adjust heuristics.
|
||||
const int InstrCost = 5;
|
||||
const int IndirectCallThreshold = 100;
|
||||
const int CallPenalty = 25;
|
||||
const int LastCallToStaticBonus = -15000;
|
||||
const int ColdccPenalty = 2000;
|
||||
const int NoreturnPenalty = 10000;
|
||||
/// Do not inline functions which allocate this many bytes on the stack
|
||||
/// when the caller is recursive.
|
||||
const unsigned TotalAllocaSizeRecursiveCaller = 1024;
|
||||
}
|
||||
|
||||
/// \brief Represents the cost of inlining a function.
|
||||
///
|
||||
/// This supports special values for functions which should "always" or
|
||||
/// "never" be inlined. Otherwise, the cost represents a unitless amount;
|
||||
/// smaller values increase the likelihood of the function being inlined.
|
||||
///
|
||||
/// Objects of this type also provide the adjusted threshold for inlining
|
||||
/// based on the information available for a particular callsite. They can be
|
||||
/// directly tested to determine if inlining should occur given the cost and
|
||||
/// threshold for this cost metric.
|
||||
class InlineCost {
|
||||
enum SentinelValues {
|
||||
AlwaysInlineCost = INT_MIN,
|
||||
NeverInlineCost = INT_MAX
|
||||
};
|
||||
|
||||
/// \brief The estimated cost of inlining this callsite.
|
||||
const int Cost;
|
||||
|
||||
/// \brief The adjusted threshold against which this cost was computed.
|
||||
const int Threshold;
|
||||
|
||||
// Trivial constructor, interesting logic in the factory functions below.
|
||||
InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {}
|
||||
|
||||
public:
|
||||
static InlineCost get(int Cost, int Threshold) {
|
||||
assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
|
||||
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
|
||||
return InlineCost(Cost, Threshold);
|
||||
}
|
||||
static InlineCost getAlways() {
|
||||
return InlineCost(AlwaysInlineCost, 0);
|
||||
}
|
||||
static InlineCost getNever() {
|
||||
return InlineCost(NeverInlineCost, 0);
|
||||
}
|
||||
|
||||
/// \brief Test whether the inline cost is low enough for inlining.
|
||||
operator bool() const {
|
||||
return Cost < Threshold;
|
||||
}
|
||||
|
||||
bool isAlways() const { return Cost == AlwaysInlineCost; }
|
||||
bool isNever() const { return Cost == NeverInlineCost; }
|
||||
bool isVariable() const { return !isAlways() && !isNever(); }
|
||||
|
||||
/// \brief Get the inline cost estimate.
|
||||
/// It is an error to call this on an "always" or "never" InlineCost.
|
||||
int getCost() const {
|
||||
assert(isVariable() && "Invalid access of InlineCost");
|
||||
return Cost;
|
||||
}
|
||||
|
||||
/// \brief Get the cost delta from the threshold for inlining.
|
||||
/// Only valid if the cost is of the variable kind. Returns a negative
|
||||
/// value if the cost is too high to inline.
|
||||
int getCostDelta() const { return Threshold - getCost(); }
|
||||
};
|
||||
|
||||
/// \brief Cost analyzer used by inliner.
|
||||
class InlineCostAnalysis : public CallGraphSCCPass {
|
||||
const DataLayout *TD;
|
||||
const TargetTransformInfo *TTI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
InlineCostAnalysis();
|
||||
~InlineCostAnalysis();
|
||||
|
||||
// Pass interface implementation.
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
bool runOnSCC(CallGraphSCC &SCC);
|
||||
|
||||
/// \brief Get an InlineCost object representing the cost of inlining this
|
||||
/// callsite.
|
||||
///
|
||||
/// Note that threshold is passed into this function. Only costs below the
|
||||
/// threshold are computed with any accuracy. The threshold can be used to
|
||||
/// bound the computation necessary to determine whether the cost is
|
||||
/// sufficiently low to warrant inlining.
|
||||
///
|
||||
/// Also note that calling this function *dynamically* computes the cost of
|
||||
/// inlining the callsite. It is an expensive, heavyweight call.
|
||||
InlineCost getInlineCost(CallSite CS, int Threshold);
|
||||
|
||||
/// \brief Get an InlineCost with the callee explicitly specified.
|
||||
/// This allows you to calculate the cost of inlining a function via a
|
||||
/// pointer. This behaves exactly as the version with no explicit callee
|
||||
/// parameter in all other respects.
|
||||
//
|
||||
// Note: This is used by out-of-tree passes, please do not remove without
|
||||
// adding a replacement API.
|
||||
InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold);
|
||||
|
||||
/// \brief Minimal filter to detect invalid constructs for inlining.
|
||||
bool isInlineViable(Function &Callee);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
274
thirdparty/clang/include/llvm/Analysis/InstructionSimplify.h
vendored
Normal file
274
thirdparty/clang/include/llvm/Analysis/InstructionSimplify.h
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares routines for folding instructions into simpler forms
|
||||
// that do not require creating new instructions. This does constant folding
|
||||
// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either
|
||||
// returning a constant ("and i32 %x, 0" -> "0") or an already existing value
|
||||
// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction
|
||||
// then it dominates the original instruction.
|
||||
//
|
||||
// These routines implicitly resolve undef uses. The easiest way to be safe when
|
||||
// using these routines to obtain simplified values for existing instructions is
|
||||
// to always replace all uses of the instructions with the resulting simplified
|
||||
// values. This will prevent other code from seeing the same undef uses and
|
||||
// resolving them to different values.
|
||||
//
|
||||
// These routines are designed to tolerate moderately incomplete IR, such as
|
||||
// instructions that are not connected to basic blocks yet. However, they do
|
||||
// require that all the IR that they encounter be valid. In particular, they
|
||||
// require that all non-constant values be defined in the same function, and the
|
||||
// same call context of that function (and not split between caller and callee
|
||||
// contexts of a directly recursive call, for example).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
|
||||
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
|
||||
|
||||
#include "llvm/IR/User.h"
|
||||
|
||||
namespace llvm {
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class FastMathFlags;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
/// SimplifyAddInst - Given operands for an Add, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySubInst - Given operands for a Sub, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FAdd, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FSub, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FMul, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFMulInst(Value *LHS, Value *RHS,
|
||||
FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyMulInst - Given operands for a Mul, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySDivInst - Given operands for an SDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySRemInst - Given operands for an SRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyURemInst - Given operands for a URem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFRemInst - Given operands for an FRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyShlInst - Given operands for a Shl, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyLShrInst - Given operands for a LShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAShrInst - Given operands for a AShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyOrInst - Given operands for an Or, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyXorInst - Given operands for a Xor, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
|
||||
/// can fold the result. If not, this returns null.
|
||||
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
|
||||
ArrayRef<unsigned> Idxs,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
//=== Helper functions for higher up the class hierarchy.
|
||||
|
||||
|
||||
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Given a function and iterators over arguments, see if we can fold
|
||||
/// the result.
|
||||
///
|
||||
/// If this call could not be simplified returns null.
|
||||
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
|
||||
User::op_iterator ArgEnd, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Given a function and set of arguments, see if we can fold the
|
||||
/// result.
|
||||
///
|
||||
/// If this call could not be simplified returns null.
|
||||
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInstruction - See if we can compute a simplified version of this
|
||||
/// instruction. If not, this returns null.
|
||||
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
|
||||
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
|
||||
/// recursively.
|
||||
///
|
||||
/// This first performs a normal RAUW of I with SimpleV. It then recursively
|
||||
/// attempts to simplify those users updated by the operation. The 'I'
|
||||
/// instruction must not be equal to the simplified value 'SimpleV'.
|
||||
///
|
||||
/// The function returns true if any simplifications were performed.
|
||||
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Recursively attempt to simplify an instruction.
|
||||
///
|
||||
/// This routine uses SimplifyInstruction to simplify 'I', and if successful
|
||||
/// replaces uses of 'I' with the simplified value. It then recurses on each
|
||||
/// of the users impacted. It returns true if any simplifications were
|
||||
/// performed.
|
||||
bool recursivelySimplifyInstruction(Instruction *I,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
153
thirdparty/clang/include/llvm/Analysis/Interval.h
vendored
Normal file
153
thirdparty/clang/include/llvm/Analysis/Interval.h
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the Interval class, which
|
||||
// represents a set of CFG nodes and is a portion of an interval partition.
|
||||
//
|
||||
// Intervals have some interesting and useful properties, including the
|
||||
// following:
|
||||
// 1. The header node of an interval dominates all of the elements of the
|
||||
// interval
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVAL_H
|
||||
#define LLVM_ANALYSIS_INTERVAL_H
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class raw_ostream;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// Interval Class - An Interval is a set of nodes defined such that every node
|
||||
/// in the interval has all of its predecessors in the interval (except for the
|
||||
/// header)
|
||||
///
|
||||
class Interval {
|
||||
/// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this
|
||||
/// interval. Also, any loops in this interval must go through the HeaderNode.
|
||||
///
|
||||
BasicBlock *HeaderNode;
|
||||
public:
|
||||
typedef std::vector<BasicBlock*>::iterator succ_iterator;
|
||||
typedef std::vector<BasicBlock*>::iterator pred_iterator;
|
||||
typedef std::vector<BasicBlock*>::iterator node_iterator;
|
||||
|
||||
inline Interval(BasicBlock *Header) : HeaderNode(Header) {
|
||||
Nodes.push_back(Header);
|
||||
}
|
||||
|
||||
inline Interval(const Interval &I) // copy ctor
|
||||
: HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {}
|
||||
|
||||
inline BasicBlock *getHeaderNode() const { return HeaderNode; }
|
||||
|
||||
/// Nodes - The basic blocks in this interval.
|
||||
///
|
||||
std::vector<BasicBlock*> Nodes;
|
||||
|
||||
/// Successors - List of BasicBlocks that are reachable directly from nodes in
|
||||
/// this interval, but are not in the interval themselves.
|
||||
/// These nodes necessarily must be header nodes for other intervals.
|
||||
///
|
||||
std::vector<BasicBlock*> Successors;
|
||||
|
||||
/// Predecessors - List of BasicBlocks that have this Interval's header block
|
||||
/// as one of their successors.
|
||||
///
|
||||
std::vector<BasicBlock*> Predecessors;
|
||||
|
||||
/// contains - Find out if a basic block is in this interval
|
||||
inline bool contains(BasicBlock *BB) const {
|
||||
for (unsigned i = 0; i < Nodes.size(); ++i)
|
||||
if (Nodes[i] == BB) return true;
|
||||
return false;
|
||||
// I don't want the dependency on <algorithm>
|
||||
//return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end();
|
||||
}
|
||||
|
||||
/// isSuccessor - find out if a basic block is a successor of this Interval
|
||||
inline bool isSuccessor(BasicBlock *BB) const {
|
||||
for (unsigned i = 0; i < Successors.size(); ++i)
|
||||
if (Successors[i] == BB) return true;
|
||||
return false;
|
||||
// I don't want the dependency on <algorithm>
|
||||
//return find(Successors.begin(), Successors.end(), BB) != Successors.end();
|
||||
}
|
||||
|
||||
/// Equality operator. It is only valid to compare two intervals from the
|
||||
/// same partition, because of this, all we have to check is the header node
|
||||
/// for equality.
|
||||
///
|
||||
inline bool operator==(const Interval &I) const {
|
||||
return HeaderNode == I.HeaderNode;
|
||||
}
|
||||
|
||||
/// isLoop - Find out if there is a back edge in this interval...
|
||||
bool isLoop() const;
|
||||
|
||||
/// print - Show contents in human readable format...
|
||||
void print(raw_ostream &O) const;
|
||||
};
|
||||
|
||||
/// succ_begin/succ_end - define methods so that Intervals may be used
|
||||
/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator.
|
||||
///
|
||||
inline Interval::succ_iterator succ_begin(Interval *I) {
|
||||
return I->Successors.begin();
|
||||
}
|
||||
inline Interval::succ_iterator succ_end(Interval *I) {
|
||||
return I->Successors.end();
|
||||
}
|
||||
|
||||
/// pred_begin/pred_end - define methods so that Intervals may be used
|
||||
/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator.
|
||||
///
|
||||
inline Interval::pred_iterator pred_begin(Interval *I) {
|
||||
return I->Predecessors.begin();
|
||||
}
|
||||
inline Interval::pred_iterator pred_end(Interval *I) {
|
||||
return I->Predecessors.end();
|
||||
}
|
||||
|
||||
template <> struct GraphTraits<Interval*> {
|
||||
typedef Interval NodeType;
|
||||
typedef Interval::succ_iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(Interval *I) { return I; }
|
||||
|
||||
/// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return succ_end(N);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse<Interval*> > {
|
||||
typedef Interval NodeType;
|
||||
typedef Interval::pred_iterator ChildIteratorType;
|
||||
static NodeType *getEntryNode(Inverse<Interval *> G) { return G.Graph; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return pred_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return pred_end(N);
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
259
thirdparty/clang/include/llvm/Analysis/IntervalIterator.h
vendored
Normal file
259
thirdparty/clang/include/llvm/Analysis/IntervalIterator.h
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
//===- IntervalIterator.h - Interval Iterator Declaration -------*- 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 an iterator that enumerates the intervals in a control flow
|
||||
// graph of some sort. This iterator is parametric, allowing iterator over the
|
||||
// following types of graphs:
|
||||
//
|
||||
// 1. A Function* object, composed of BasicBlock nodes.
|
||||
// 2. An IntervalPartition& object, composed of Interval nodes.
|
||||
//
|
||||
// This iterator is defined to walk the control flow graph, returning intervals
|
||||
// in depth first order. These intervals are completely filled in except for
|
||||
// the predecessor fields (the successor information is filled in however).
|
||||
//
|
||||
// By default, the intervals created by this iterator are deleted after they
|
||||
// are no longer any use to the iterator. This behavior can be changed by
|
||||
// passing a false value into the intervals_begin() function. This causes the
|
||||
// IOwnMem member to be set, and the intervals to not be deleted.
|
||||
//
|
||||
// It is only safe to use this if all of the intervals are deleted by the caller
|
||||
// and all of the intervals are processed. However, the user of the iterator is
|
||||
// not allowed to modify or delete the intervals until after the iterator has
|
||||
// been used completely. The IntervalPartition class uses this functionality.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVALITERATOR_H
|
||||
#define LLVM_ANALYSIS_INTERVALITERATOR_H
|
||||
|
||||
#include "llvm/Analysis/IntervalPartition.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// getNodeHeader - Given a source graph node and the source graph, return the
|
||||
// BasicBlock that is the header node. This is the opposite of
|
||||
// getSourceGraphNode.
|
||||
//
|
||||
inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; }
|
||||
inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); }
|
||||
|
||||
// getSourceGraphNode - Given a BasicBlock and the source graph, return the
|
||||
// source graph node that corresponds to the BasicBlock. This is the opposite
|
||||
// of getNodeHeader.
|
||||
//
|
||||
inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) {
|
||||
return BB;
|
||||
}
|
||||
inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) {
|
||||
return IP->getBlockInterval(BB);
|
||||
}
|
||||
|
||||
// addNodeToInterval - This method exists to assist the generic ProcessNode
|
||||
// with the task of adding a node to the new interval, depending on the
|
||||
// type of the source node. In the case of a CFG source graph (BasicBlock
|
||||
// case), the BasicBlock itself is added to the interval.
|
||||
//
|
||||
inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
|
||||
Int->Nodes.push_back(BB);
|
||||
}
|
||||
|
||||
// addNodeToInterval - This method exists to assist the generic ProcessNode
|
||||
// with the task of adding a node to the new interval, depending on the
|
||||
// type of the source node. In the case of a CFG source graph (BasicBlock
|
||||
// case), the BasicBlock itself is added to the interval. In the case of
|
||||
// an IntervalPartition source graph (Interval case), all of the member
|
||||
// BasicBlocks are added to the interval.
|
||||
//
|
||||
inline void addNodeToInterval(Interval *Int, Interval *I) {
|
||||
// Add all of the nodes in I as new nodes in Int.
|
||||
copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>,
|
||||
class IGT = GraphTraits<Inverse<NodeTy*> > >
|
||||
class IntervalIterator {
|
||||
std::vector<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
|
||||
std::set<BasicBlock*> Visited;
|
||||
OrigContainer_t *OrigContainer;
|
||||
bool IOwnMem; // If True, delete intervals when done with them
|
||||
// See file header for conditions of use
|
||||
public:
|
||||
typedef IntervalIterator<NodeTy, OrigContainer_t> _Self;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
IntervalIterator() {} // End iterator, empty stack
|
||||
IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = M;
|
||||
if (!ProcessInterval(&M->front())) {
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = &IP;
|
||||
if (!ProcessInterval(IP.getRootInterval())) {
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
inline ~IntervalIterator() {
|
||||
if (IOwnMem)
|
||||
while (!IntStack.empty()) {
|
||||
delete operator*();
|
||||
IntStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline const Interval *operator*() const { return IntStack.back().first; }
|
||||
inline Interval *operator*() { return IntStack.back().first; }
|
||||
inline const Interval *operator->() const { return operator*(); }
|
||||
inline Interval *operator->() { return operator*(); }
|
||||
|
||||
_Self& operator++() { // Preincrement
|
||||
assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
|
||||
do {
|
||||
// All of the intervals on the stack have been visited. Try visiting
|
||||
// their successors now.
|
||||
Interval::succ_iterator &SuccIt = IntStack.back().second,
|
||||
EndIt = succ_end(IntStack.back().first);
|
||||
while (SuccIt != EndIt) { // Loop over all interval succs
|
||||
bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt));
|
||||
++SuccIt; // Increment iterator
|
||||
if (Done) return *this; // Found a new interval! Use it!
|
||||
}
|
||||
|
||||
// Free interval memory... if necessary
|
||||
if (IOwnMem) delete IntStack.back().first;
|
||||
|
||||
// We ran out of successors for this interval... pop off the stack
|
||||
IntStack.pop_back();
|
||||
} while (!IntStack.empty());
|
||||
|
||||
return *this;
|
||||
}
|
||||
inline _Self operator++(int) { // Postincrement
|
||||
_Self tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
// ProcessInterval - This method is used during the construction of the
|
||||
// interval graph. It walks through the source graph, recursively creating
|
||||
// an interval per invocation until the entire graph is covered. This uses
|
||||
// the ProcessNode method to add all of the nodes to the interval.
|
||||
//
|
||||
// This method is templated because it may operate on two different source
|
||||
// graphs: a basic block graph, or a preexisting interval graph.
|
||||
//
|
||||
bool ProcessInterval(NodeTy *Node) {
|
||||
BasicBlock *Header = getNodeHeader(Node);
|
||||
if (Visited.count(Header)) return false;
|
||||
|
||||
Interval *Int = new Interval(Header);
|
||||
Visited.insert(Header); // The header has now been visited!
|
||||
|
||||
// Check all of our successors to see if they are in the interval...
|
||||
for (typename GT::ChildIteratorType I = GT::child_begin(Node),
|
||||
E = GT::child_end(Node); I != E; ++I)
|
||||
ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
|
||||
|
||||
IntStack.push_back(std::make_pair(Int, succ_begin(Int)));
|
||||
return true;
|
||||
}
|
||||
|
||||
// ProcessNode - This method is called by ProcessInterval to add nodes to the
|
||||
// interval being constructed, and it is also called recursively as it walks
|
||||
// the source graph. A node is added to the current interval only if all of
|
||||
// its predecessors are already in the graph. This also takes care of keeping
|
||||
// the successor set of an interval up to date.
|
||||
//
|
||||
// This method is templated because it may operate on two different source
|
||||
// graphs: a basic block graph, or a preexisting interval graph.
|
||||
//
|
||||
void ProcessNode(Interval *Int, NodeTy *Node) {
|
||||
assert(Int && "Null interval == bad!");
|
||||
assert(Node && "Null Node == bad!");
|
||||
|
||||
BasicBlock *NodeHeader = getNodeHeader(Node);
|
||||
|
||||
if (Visited.count(NodeHeader)) { // Node already been visited?
|
||||
if (Int->contains(NodeHeader)) { // Already in this interval...
|
||||
return;
|
||||
} else { // In other interval, add as successor
|
||||
if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
|
||||
Int->Successors.push_back(NodeHeader);
|
||||
}
|
||||
} else { // Otherwise, not in interval yet
|
||||
for (typename IGT::ChildIteratorType I = IGT::child_begin(Node),
|
||||
E = IGT::child_end(Node); I != E; ++I) {
|
||||
if (!Int->contains(*I)) { // If pred not in interval, we can't be
|
||||
if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
|
||||
Int->Successors.push_back(NodeHeader);
|
||||
return; // See you later
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then all of the predecessors of BB are in the interval
|
||||
// already. In this case, we must add BB to the interval!
|
||||
addNodeToInterval(Int, Node);
|
||||
Visited.insert(NodeHeader); // The node has now been visited!
|
||||
|
||||
if (Int->isSuccessor(NodeHeader)) {
|
||||
// If we were in the successor list from before... remove from succ list
|
||||
Int->Successors.erase(std::remove(Int->Successors.begin(),
|
||||
Int->Successors.end(), NodeHeader),
|
||||
Int->Successors.end());
|
||||
}
|
||||
|
||||
// Now that we have discovered that Node is in the interval, perhaps some
|
||||
// of its successors are as well?
|
||||
for (typename GT::ChildIteratorType It = GT::child_begin(Node),
|
||||
End = GT::child_end(Node); It != End; ++It)
|
||||
ProcessNode(Int, getSourceGraphNode(OrigContainer, *It));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef IntervalIterator<BasicBlock, Function> function_interval_iterator;
|
||||
typedef IntervalIterator<Interval, IntervalPartition>
|
||||
interval_part_interval_iterator;
|
||||
|
||||
|
||||
inline function_interval_iterator intervals_begin(Function *F,
|
||||
bool DeleteInts = true) {
|
||||
return function_interval_iterator(F, DeleteInts);
|
||||
}
|
||||
inline function_interval_iterator intervals_end(Function *) {
|
||||
return function_interval_iterator();
|
||||
}
|
||||
|
||||
inline interval_part_interval_iterator
|
||||
intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) {
|
||||
return interval_part_interval_iterator(IP, DeleteIntervals);
|
||||
}
|
||||
|
||||
inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) {
|
||||
return interval_part_interval_iterator();
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
111
thirdparty/clang/include/llvm/Analysis/IntervalPartition.h
vendored
Normal file
111
thirdparty/clang/include/llvm/Analysis/IntervalPartition.h
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the IntervalPartition class, which
|
||||
// calculates and represents the interval partition of a function, or a
|
||||
// preexisting interval partition.
|
||||
//
|
||||
// In this way, the interval partition may be used to reduce a flow graph down
|
||||
// to its degenerate single node interval partition (unless it is irreducible).
|
||||
//
|
||||
// TODO: The IntervalPartition class should take a bool parameter that tells
|
||||
// whether it should add the "tails" of an interval to an interval itself or if
|
||||
// they should be represented as distinct intervals.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVALPARTITION_H
|
||||
#define LLVM_ANALYSIS_INTERVALPARTITION_H
|
||||
|
||||
#include "llvm/Analysis/Interval.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// IntervalPartition - This class builds and holds an "interval partition" for
|
||||
// a function. This partition divides the control flow graph into a set of
|
||||
// maximal intervals, as defined with the properties above. Intuitively, an
|
||||
// interval is a (possibly nonexistent) loop with a "tail" of non looping
|
||||
// nodes following it.
|
||||
//
|
||||
class IntervalPartition : public FunctionPass {
|
||||
typedef std::map<BasicBlock*, Interval*> IntervalMapTy;
|
||||
IntervalMapTy IntervalMap;
|
||||
|
||||
typedef std::vector<Interval*> IntervalListTy;
|
||||
Interval *RootInterval;
|
||||
std::vector<Interval*> Intervals;
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
IntervalPartition() : FunctionPass(ID), RootInterval(0) {
|
||||
initializeIntervalPartitionPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
// run - Calculate the interval partition for this function
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
// IntervalPartition ctor - Build a reduced interval partition from an
|
||||
// existing interval graph. This takes an additional boolean parameter to
|
||||
// distinguish it from a copy constructor. Always pass in false for now.
|
||||
//
|
||||
IntervalPartition(IntervalPartition &I, bool);
|
||||
|
||||
// print - Show contents in human readable format...
|
||||
virtual void print(raw_ostream &O, const Module* = 0) const;
|
||||
|
||||
// getRootInterval() - Return the root interval that contains the starting
|
||||
// block of the function.
|
||||
inline Interval *getRootInterval() { return RootInterval; }
|
||||
|
||||
// isDegeneratePartition() - Returns true if the interval partition contains
|
||||
// a single interval, and thus cannot be simplified anymore.
|
||||
bool isDegeneratePartition() { return Intervals.size() == 1; }
|
||||
|
||||
// TODO: isIrreducible - look for triangle graph.
|
||||
|
||||
// getBlockInterval - Return the interval that a basic block exists in.
|
||||
inline Interval *getBlockInterval(BasicBlock *BB) {
|
||||
IntervalMapTy::iterator I = IntervalMap.find(BB);
|
||||
return I != IntervalMap.end() ? I->second : 0;
|
||||
}
|
||||
|
||||
// getAnalysisUsage - Implement the Pass API
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
// Interface to Intervals vector...
|
||||
const std::vector<Interval*> &getIntervals() const { return Intervals; }
|
||||
|
||||
// releaseMemory - Reset state back to before function was analyzed
|
||||
void releaseMemory();
|
||||
|
||||
private:
|
||||
// addIntervalToPartition - Add an interval to the internal list of intervals,
|
||||
// and then add mappings from all of the basic blocks in the interval to the
|
||||
// interval itself (in the IntervalMap).
|
||||
//
|
||||
void addIntervalToPartition(Interval *I);
|
||||
|
||||
// updatePredecessors - Interval generation only sets the successor fields of
|
||||
// the interval data structures. After interval generation is complete,
|
||||
// run through all of the intervals and propagate successor info as
|
||||
// predecessor info.
|
||||
//
|
||||
void updatePredecessors(Interval *Int);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
81
thirdparty/clang/include/llvm/Analysis/LazyValueInfo.h
vendored
Normal file
81
thirdparty/clang/include/llvm/Analysis/LazyValueInfo.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//===- LazyValueInfo.h - Value constraint analysis --------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the interface for lazy computation of value constraint
|
||||
// information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LAZYVALUEINFO_H
|
||||
#define LLVM_ANALYSIS_LAZYVALUEINFO_H
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class Constant;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Value;
|
||||
|
||||
/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
|
||||
/// information.
|
||||
class LazyValueInfo : public FunctionPass {
|
||||
class DataLayout *TD;
|
||||
class TargetLibraryInfo *TLI;
|
||||
void *PImpl;
|
||||
LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
static char ID;
|
||||
LazyValueInfo() : FunctionPass(ID), PImpl(0) {
|
||||
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); }
|
||||
|
||||
/// Tristate - This is used to return true/false/dunno results.
|
||||
enum Tristate {
|
||||
Unknown = -1, False = 0, True = 1
|
||||
};
|
||||
|
||||
|
||||
// Public query interface.
|
||||
|
||||
/// getPredicateOnEdge - Determine whether the specified value comparison
|
||||
/// with a constant is known to be true or false on the specified CFG edge.
|
||||
/// Pred is a CmpInst predicate.
|
||||
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
|
||||
BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
|
||||
|
||||
/// getConstant - Determine whether the specified value is known to be a
|
||||
/// constant at the end of the specified block. Return null if not.
|
||||
Constant *getConstant(Value *V, BasicBlock *BB);
|
||||
|
||||
/// getConstantOnEdge - Determine whether the specified value is known to be a
|
||||
/// constant on the specified edge. Return null if not.
|
||||
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
|
||||
/// threadEdge - Inform the analysis cache that we have threaded an edge from
|
||||
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
|
||||
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
|
||||
|
||||
/// eraseBlock - Inform the analysis cache that we have erased a block.
|
||||
void eraseBlock(BasicBlock *BB);
|
||||
|
||||
// Implementation boilerplate.
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
virtual bool runOnFunction(Function &F);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
73
thirdparty/clang/include/llvm/Analysis/LibCallAliasAnalysis.h
vendored
Normal file
73
thirdparty/clang/include/llvm/Analysis/LibCallAliasAnalysis.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
//===- LibCallAliasAnalysis.h - Implement AliasAnalysis for libcalls ------===//
|
||||
//
|
||||
// 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 LibCallAliasAnalysis class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
|
||||
#define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class LibCallInfo;
|
||||
struct LibCallFunctionInfo;
|
||||
|
||||
/// LibCallAliasAnalysis - Alias analysis driven from LibCallInfo.
|
||||
struct LibCallAliasAnalysis : public FunctionPass, public AliasAnalysis {
|
||||
static char ID; // Class identification
|
||||
|
||||
LibCallInfo *LCI;
|
||||
|
||||
explicit LibCallAliasAnalysis(LibCallInfo *LC = 0)
|
||||
: FunctionPass(ID), LCI(LC) {
|
||||
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit LibCallAliasAnalysis(char &ID, LibCallInfo *LC)
|
||||
: FunctionPass(ID), LCI(LC) {
|
||||
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
~LibCallAliasAnalysis();
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
// TODO: Could compare two direct calls against each other if we cared to.
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
InitializeAliasAnalysis(this); // set up super class
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
virtual void *getAdjustedAnalysisPointer(const void *PI) {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis*)this;
|
||||
return this;
|
||||
}
|
||||
|
||||
private:
|
||||
ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
};
|
||||
} // End of llvm namespace
|
||||
|
||||
#endif
|
||||
167
thirdparty/clang/include/llvm/Analysis/LibCallSemantics.h
vendored
Normal file
167
thirdparty/clang/include/llvm/Analysis/LibCallSemantics.h
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
//===- LibCallSemantics.h - Describe library semantics --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines interfaces that can be used to describe language specific
|
||||
// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H
|
||||
#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// LibCallLocationInfo - This struct describes a set of memory locations that
|
||||
/// are accessed by libcalls. Identification of a location is doing with a
|
||||
/// simple callback function.
|
||||
///
|
||||
/// For example, the LibCallInfo may be set up to model the behavior of
|
||||
/// standard libm functions. The location that they may be interested in is
|
||||
/// an abstract location that represents errno for the current target. In
|
||||
/// this case, a location for errno is anything such that the predicate
|
||||
/// returns true. On Mac OS/X, this predicate would return true if the
|
||||
/// pointer is the result of a call to "__error()".
|
||||
///
|
||||
/// Locations can also be defined in a constant-sensitive way. For example,
|
||||
/// it is possible to define a location that returns true iff it is passed
|
||||
/// into the call as a specific argument. This is useful for modeling things
|
||||
/// like "printf", which can store to memory, but only through pointers passed
|
||||
/// with a '%n' constraint.
|
||||
///
|
||||
struct LibCallLocationInfo {
|
||||
// TODO: Flags: isContextSensitive etc.
|
||||
|
||||
/// isLocation - Return a LocResult if the specified pointer refers to this
|
||||
/// location for the specified call site. This returns "Yes" if we can tell
|
||||
/// that the pointer *does definitely* refer to the location, "No" if we can
|
||||
/// tell that the location *definitely does not* refer to the location, and
|
||||
/// returns "Unknown" if we cannot tell for certain.
|
||||
enum LocResult {
|
||||
Yes, No, Unknown
|
||||
};
|
||||
LocResult (*isLocation)(ImmutableCallSite CS,
|
||||
const AliasAnalysis::Location &Loc);
|
||||
};
|
||||
|
||||
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
|
||||
/// records the behavior of one libcall that is known by the optimizer. This
|
||||
/// captures things like the side effects of the call. Side effects are
|
||||
/// modeled both universally (in the readnone/readonly) sense, but also
|
||||
/// potentially against a set of abstract locations defined by the optimizer.
|
||||
/// This allows an optimizer to define that some libcall (e.g. sqrt) is
|
||||
/// side-effect free except that it might modify errno (thus, the call is
|
||||
/// *not* universally readonly). Or it might say that the side effects
|
||||
/// are unknown other than to say that errno is not modified.
|
||||
///
|
||||
struct LibCallFunctionInfo {
|
||||
/// Name - This is the name of the libcall this describes.
|
||||
const char *Name;
|
||||
|
||||
/// TODO: Constant folding function: Constant* vector -> Constant*.
|
||||
|
||||
/// UniversalBehavior - This captures the absolute mod/ref behavior without
|
||||
/// any specific context knowledge. For example, if the function is known
|
||||
/// to be readonly, this would be set to 'ref'. If known to be readnone,
|
||||
/// this is set to NoModRef.
|
||||
AliasAnalysis::ModRefResult UniversalBehavior;
|
||||
|
||||
/// LocationMRInfo - This pair captures info about whether a specific
|
||||
/// location is modified or referenced by a libcall.
|
||||
struct LocationMRInfo {
|
||||
/// LocationID - ID # of the accessed location or ~0U for array end.
|
||||
unsigned LocationID;
|
||||
/// MRInfo - Mod/Ref info for this location.
|
||||
AliasAnalysis::ModRefResult MRInfo;
|
||||
};
|
||||
|
||||
/// DetailsType - Indicate the sense of the LocationDetails array. This
|
||||
/// controls how the LocationDetails array is interpreted.
|
||||
enum {
|
||||
/// DoesOnly - If DetailsType is set to DoesOnly, then we know that the
|
||||
/// *only* mod/ref behavior of this function is captured by the
|
||||
/// LocationDetails array. If we are trying to say that 'sqrt' can only
|
||||
/// modify errno, we'd have the {errnoloc,mod} in the LocationDetails
|
||||
/// array and have DetailsType set to DoesOnly.
|
||||
DoesOnly,
|
||||
|
||||
/// DoesNot - If DetailsType is set to DoesNot, then the sense of the
|
||||
/// LocationDetails array is completely inverted. This means that we *do
|
||||
/// not* know everything about the side effects of this libcall, but we do
|
||||
/// know things that the libcall cannot do. This is useful for complex
|
||||
/// functions like 'ctime' which have crazy mod/ref behavior, but are
|
||||
/// known to never read or write errno. In this case, we'd have
|
||||
/// {errnoloc,modref} in the LocationDetails array and DetailsType would
|
||||
/// be set to DoesNot, indicating that ctime does not read or write the
|
||||
/// errno location.
|
||||
DoesNot
|
||||
} DetailsType;
|
||||
|
||||
/// LocationDetails - This is a pointer to an array of LocationMRInfo
|
||||
/// structs which indicates the behavior of the libcall w.r.t. specific
|
||||
/// locations. For example, if this libcall is known to only modify
|
||||
/// 'errno', it would have a LocationDetails array with the errno ID and
|
||||
/// 'mod' in it. See the DetailsType field for how this is interpreted.
|
||||
///
|
||||
/// In the "DoesOnly" case, this information is 'may' information for: there
|
||||
/// is no guarantee that the specified side effect actually does happen,
|
||||
/// just that it could. In the "DoesNot" case, this is 'must not' info.
|
||||
///
|
||||
/// If this pointer is null, no details are known.
|
||||
///
|
||||
const LocationMRInfo *LocationDetails;
|
||||
};
|
||||
|
||||
|
||||
/// LibCallInfo - Abstract interface to query about library call information.
|
||||
/// Instances of this class return known information about some set of
|
||||
/// libcalls.
|
||||
///
|
||||
class LibCallInfo {
|
||||
// Implementation details of this object, private.
|
||||
mutable void *Impl;
|
||||
mutable const LibCallLocationInfo *Locations;
|
||||
mutable unsigned NumLocations;
|
||||
public:
|
||||
LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {}
|
||||
virtual ~LibCallInfo();
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Accessor Methods: Efficient access to contained data.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// getLocationInfo - Return information about the specified LocationID.
|
||||
const LibCallLocationInfo &getLocationInfo(unsigned LocID) const;
|
||||
|
||||
|
||||
/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to
|
||||
/// the specified function if we have it. If not, return null.
|
||||
const LibCallFunctionInfo *getFunctionInfo(const Function *F) const;
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Implementation Methods: Subclasses should implement these.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// getLocationInfo - Return descriptors for the locations referenced by
|
||||
/// this set of libcalls.
|
||||
virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getFunctionInfoArray - Return an array of descriptors that describe the
|
||||
/// set of libcalls represented by this LibCallInfo object. This array is
|
||||
/// terminated by an entry with a NULL name.
|
||||
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
49
thirdparty/clang/include/llvm/Analysis/Lint.h
vendored
Normal file
49
thirdparty/clang/include/llvm/Analysis/Lint.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
//===-- llvm/Analysis/Lint.h - LLVM IR Lint ---------------------*- 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 lint interfaces that can be used for some sanity checking
|
||||
// of input to the system, and for checking that transformations
|
||||
// haven't done something bad. In contrast to the Verifier, the Lint checker
|
||||
// checks for undefined behavior or constructions with likely unintended
|
||||
// behavior.
|
||||
//
|
||||
// To see what specifically is checked, look at Lint.cpp
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LINT_H
|
||||
#define LLVM_ANALYSIS_LINT_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class FunctionPass;
|
||||
class Module;
|
||||
class Function;
|
||||
|
||||
/// @brief Create a lint pass.
|
||||
///
|
||||
/// Check a module or function.
|
||||
FunctionPass *createLintPass();
|
||||
|
||||
/// @brief Check a module.
|
||||
///
|
||||
/// This should only be used for debugging, because it plays games with
|
||||
/// PassManagers and stuff.
|
||||
void lintModule(
|
||||
const Module &M ///< The module to be checked
|
||||
);
|
||||
|
||||
// lintFunction - Check a function.
|
||||
void lintFunction(
|
||||
const Function &F ///< The function to be checked
|
||||
);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
57
thirdparty/clang/include/llvm/Analysis/Loads.h
vendored
Normal file
57
thirdparty/clang/include/llvm/Analysis/Loads.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
//===- Loads.h - Local load analysis --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares simple local analyses for load instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOADS_H
|
||||
#define LLVM_ANALYSIS_LOADS_H
|
||||
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class DataLayout;
|
||||
class MDNode;
|
||||
|
||||
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
|
||||
/// from this value cannot trap. If it is not obviously safe to load from the
|
||||
/// specified pointer, we do a quick local scan of the basic block containing
|
||||
/// ScanFrom, to determine if the address is already accessed.
|
||||
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
|
||||
unsigned Align, const DataLayout *TD = 0);
|
||||
|
||||
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
|
||||
/// the instruction before ScanFrom) checking to see if we have the value at
|
||||
/// the memory address *Ptr locally available within a small number of
|
||||
/// instructions. If the value is available, return it.
|
||||
///
|
||||
/// If not, return the iterator for the last validated instruction that the
|
||||
/// value would be live through. If we scanned the entire block and didn't
|
||||
/// find something that invalidates *Ptr or provides it, ScanFrom would be
|
||||
/// left at begin() and this returns null. ScanFrom could also be left
|
||||
///
|
||||
/// MaxInstsToScan specifies the maximum instructions to scan in the block.
|
||||
/// If it is set to 0, it will scan the whole block. You can also optionally
|
||||
/// specify an alias analysis implementation, which makes this more precise.
|
||||
///
|
||||
/// If TBAATag is non-null and a load or store is found, the TBAA tag from the
|
||||
/// load or store is recorded there. If there is no TBAA tag or if no access
|
||||
/// is found, it is left unmodified.
|
||||
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
|
||||
BasicBlock::iterator &ScanFrom,
|
||||
unsigned MaxInstsToScan = 6,
|
||||
AliasAnalysis *AA = 0,
|
||||
MDNode **TBAATag = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
124
thirdparty/clang/include/llvm/Analysis/LoopDependenceAnalysis.h
vendored
Normal file
124
thirdparty/clang/include/llvm/Analysis/LoopDependenceAnalysis.h
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
//===- llvm/Analysis/LoopDependenceAnalysis.h --------------- -*- C++ -*---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// LoopDependenceAnalysis is an LLVM pass that analyses dependences in memory
|
||||
// accesses in loops.
|
||||
//
|
||||
// Please note that this is work in progress and the interface is subject to
|
||||
// change.
|
||||
//
|
||||
// TODO: adapt as interface progresses
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H
|
||||
#define LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class AnalysisUsage;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class Value;
|
||||
class raw_ostream;
|
||||
|
||||
class LoopDependenceAnalysis : public LoopPass {
|
||||
AliasAnalysis *AA;
|
||||
ScalarEvolution *SE;
|
||||
|
||||
/// L - The loop we are currently analysing.
|
||||
Loop *L;
|
||||
|
||||
/// TODO: doc
|
||||
enum DependenceResult { Independent = 0, Dependent = 1, Unknown = 2 };
|
||||
|
||||
/// TODO: doc
|
||||
struct Subscript {
|
||||
/// TODO: Add distance, direction, breaking conditions, ...
|
||||
};
|
||||
|
||||
/// DependencePair - Represents a data dependence relation between to memory
|
||||
/// reference instructions.
|
||||
struct DependencePair : public FastFoldingSetNode {
|
||||
Value *A;
|
||||
Value *B;
|
||||
DependenceResult Result;
|
||||
SmallVector<Subscript, 4> Subscripts;
|
||||
|
||||
DependencePair(const FoldingSetNodeID &ID, Value *a, Value *b) :
|
||||
FastFoldingSetNode(ID), A(a), B(b), Result(Unknown), Subscripts() {}
|
||||
};
|
||||
|
||||
/// findOrInsertDependencePair - Return true if a DependencePair for the
|
||||
/// given Values already exists, false if a new DependencePair had to be
|
||||
/// created. The third argument is set to the pair found or created.
|
||||
bool findOrInsertDependencePair(Value*, Value*, DependencePair*&);
|
||||
|
||||
/// getLoops - Collect all loops of the loop nest L in which
|
||||
/// a given SCEV is variant.
|
||||
void getLoops(const SCEV*, DenseSet<const Loop*>*) const;
|
||||
|
||||
/// isLoopInvariant - True if a given SCEV is invariant in all loops of the
|
||||
/// loop nest starting at the innermost loop L.
|
||||
bool isLoopInvariant(const SCEV*) const;
|
||||
|
||||
/// isAffine - An SCEV is affine with respect to the loop nest starting at
|
||||
/// the innermost loop L if it is of the form A+B*X where A, B are invariant
|
||||
/// in the loop nest and X is a induction variable in the loop nest.
|
||||
bool isAffine(const SCEV*) const;
|
||||
|
||||
/// TODO: doc
|
||||
bool isZIVPair(const SCEV*, const SCEV*) const;
|
||||
bool isSIVPair(const SCEV*, const SCEV*) const;
|
||||
DependenceResult analyseZIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseSIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseMIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseSubscript(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analysePair(DependencePair*) const;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
LoopDependenceAnalysis() : LoopPass(ID) {
|
||||
initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
/// isDependencePair - Check whether two values can possibly give rise to
|
||||
/// a data dependence: that is the case if both are instructions accessing
|
||||
/// memory and at least one of those accesses is a write.
|
||||
bool isDependencePair(const Value*, const Value*) const;
|
||||
|
||||
/// depends - Return a boolean indicating if there is a data dependence
|
||||
/// between two instructions.
|
||||
bool depends(Value*, Value*);
|
||||
|
||||
bool runOnLoop(Loop*, LPPassManager&);
|
||||
virtual void releaseMemory();
|
||||
virtual void getAnalysisUsage(AnalysisUsage&) const;
|
||||
void print(raw_ostream&, const Module* = 0) const;
|
||||
|
||||
private:
|
||||
FoldingSet<DependencePair> Pairs;
|
||||
BumpPtrAllocator PairAllocator;
|
||||
}; // class LoopDependenceAnalysis
|
||||
|
||||
// createLoopDependenceAnalysisPass - This creates an instance of the
|
||||
// LoopDependenceAnalysis pass.
|
||||
//
|
||||
LoopPass *createLoopDependenceAnalysisPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif /* LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H */
|
||||
710
thirdparty/clang/include/llvm/Analysis/LoopInfo.h
vendored
Normal file
710
thirdparty/clang/include/llvm/Analysis/LoopInfo.h
vendored
Normal file
@@ -0,0 +1,710 @@
|
||||
//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- 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 LoopInfo class that is used to identify natural loops
|
||||
// and determine the loop depth of various nodes of the CFG. A natural loop
|
||||
// has exactly one entry-point, which is called the header. Note that natural
|
||||
// loops may actually be several loops that share the same header node.
|
||||
//
|
||||
// This analysis calculates the nesting structure of loops in a function. For
|
||||
// each natural loop identified, this analysis identifies natural loops
|
||||
// contained entirely within the loop and the basic blocks the make up the loop.
|
||||
//
|
||||
// It can calculate on the fly various bits of information, for example:
|
||||
//
|
||||
// * whether there is a preheader for the loop
|
||||
// * the number of back edges to the header
|
||||
// * whether or not a particular block branches out of the loop
|
||||
// * the successor blocks of the loop
|
||||
// * the loop depth
|
||||
// * etc...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPINFO_H
|
||||
#define LLVM_ANALYSIS_LOOPINFO_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename T>
|
||||
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
|
||||
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
|
||||
assert(I != V.end() && "N is not in this list!");
|
||||
V.erase(I);
|
||||
}
|
||||
|
||||
class DominatorTree;
|
||||
class LoopInfo;
|
||||
class Loop;
|
||||
class PHINode;
|
||||
class raw_ostream;
|
||||
template<class N, class M> class LoopInfoBase;
|
||||
template<class N, class M> class LoopBase;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// LoopBase class - Instances of this class are used to represent loops that
|
||||
/// are detected in the flow graph
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
class LoopBase {
|
||||
LoopT *ParentLoop;
|
||||
// SubLoops - Loops contained entirely within this one.
|
||||
std::vector<LoopT *> SubLoops;
|
||||
|
||||
// Blocks - The list of blocks in this loop. First entry is the header node.
|
||||
std::vector<BlockT*> Blocks;
|
||||
|
||||
LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
const LoopBase<BlockT, LoopT>&
|
||||
operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
/// Loop ctor - This creates an empty loop.
|
||||
LoopBase() : ParentLoop(0) {}
|
||||
~LoopBase() {
|
||||
for (size_t i = 0, e = SubLoops.size(); i != e; ++i)
|
||||
delete SubLoops[i];
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the nesting level of this loop. An outer-most
|
||||
/// loop has depth 1, for consistency with loop depth values used for basic
|
||||
/// blocks, where depth 0 is used for blocks not inside any loops.
|
||||
unsigned getLoopDepth() const {
|
||||
unsigned D = 1;
|
||||
for (const LoopT *CurLoop = ParentLoop; CurLoop;
|
||||
CurLoop = CurLoop->ParentLoop)
|
||||
++D;
|
||||
return D;
|
||||
}
|
||||
BlockT *getHeader() const { return Blocks.front(); }
|
||||
LoopT *getParentLoop() const { return ParentLoop; }
|
||||
|
||||
/// setParentLoop is a raw interface for bypassing addChildLoop.
|
||||
void setParentLoop(LoopT *L) { ParentLoop = L; }
|
||||
|
||||
/// contains - Return true if the specified loop is contained within in
|
||||
/// this loop.
|
||||
///
|
||||
bool contains(const LoopT *L) const {
|
||||
if (L == this) return true;
|
||||
if (L == 0) return false;
|
||||
return contains(L->getParentLoop());
|
||||
}
|
||||
|
||||
/// contains - Return true if the specified basic block is in this loop.
|
||||
///
|
||||
bool contains(const BlockT *BB) const {
|
||||
return std::find(block_begin(), block_end(), BB) != block_end();
|
||||
}
|
||||
|
||||
/// contains - Return true if the specified instruction is in this loop.
|
||||
///
|
||||
template<class InstT>
|
||||
bool contains(const InstT *Inst) const {
|
||||
return contains(Inst->getParent());
|
||||
}
|
||||
|
||||
/// iterator/begin/end - Return the loops contained entirely within this loop.
|
||||
///
|
||||
const std::vector<LoopT *> &getSubLoops() const { return SubLoops; }
|
||||
std::vector<LoopT *> &getSubLoopsVector() { return SubLoops; }
|
||||
typedef typename std::vector<LoopT *>::const_iterator iterator;
|
||||
typedef typename std::vector<LoopT *>::const_reverse_iterator
|
||||
reverse_iterator;
|
||||
iterator begin() const { return SubLoops.begin(); }
|
||||
iterator end() const { return SubLoops.end(); }
|
||||
reverse_iterator rbegin() const { return SubLoops.rbegin(); }
|
||||
reverse_iterator rend() const { return SubLoops.rend(); }
|
||||
bool empty() const { return SubLoops.empty(); }
|
||||
|
||||
/// getBlocks - Get a list of the basic blocks which make up this loop.
|
||||
///
|
||||
const std::vector<BlockT*> &getBlocks() const { return Blocks; }
|
||||
std::vector<BlockT*> &getBlocksVector() { return Blocks; }
|
||||
typedef typename std::vector<BlockT*>::const_iterator block_iterator;
|
||||
block_iterator block_begin() const { return Blocks.begin(); }
|
||||
block_iterator block_end() const { return Blocks.end(); }
|
||||
|
||||
/// getNumBlocks - Get the number of blocks in this loop in constant time.
|
||||
unsigned getNumBlocks() const {
|
||||
return Blocks.size();
|
||||
}
|
||||
|
||||
/// isLoopExiting - True if terminator in the block can branch to another
|
||||
/// block that is outside of the current loop.
|
||||
///
|
||||
bool isLoopExiting(const BlockT *BB) const {
|
||||
typedef GraphTraits<const BlockT*> BlockTraits;
|
||||
for (typename BlockTraits::ChildIteratorType SI =
|
||||
BlockTraits::child_begin(BB),
|
||||
SE = BlockTraits::child_end(BB); SI != SE; ++SI) {
|
||||
if (!contains(*SI))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getNumBackEdges - Calculate the number of back edges to the loop header
|
||||
///
|
||||
unsigned getNumBackEdges() const {
|
||||
unsigned NumBackEdges = 0;
|
||||
BlockT *H = getHeader();
|
||||
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType I =
|
||||
InvBlockTraits::child_begin(H),
|
||||
E = InvBlockTraits::child_end(H); I != E; ++I)
|
||||
if (contains(*I))
|
||||
++NumBackEdges;
|
||||
|
||||
return NumBackEdges;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// APIs for simple analysis of the loop.
|
||||
//
|
||||
// Note that all of these methods can fail on general loops (ie, there may not
|
||||
// be a preheader, etc). For best success, the loop simplification and
|
||||
// induction variable canonicalization pass should be used to normalize loops
|
||||
// for easy analysis. These methods assume canonical loops.
|
||||
|
||||
/// getExitingBlocks - Return all blocks inside the loop that have successors
|
||||
/// outside of the loop. These are the blocks _inside of the current loop_
|
||||
/// which branch out. The returned list is always unique.
|
||||
///
|
||||
void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const;
|
||||
|
||||
/// getExitingBlock - If getExitingBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
BlockT *getExitingBlock() const;
|
||||
|
||||
/// getExitBlocks - Return all of the successor blocks of this loop. These
|
||||
/// are the blocks _outside of the current loop_ which are branched to.
|
||||
///
|
||||
void getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const;
|
||||
|
||||
/// getExitBlock - If getExitBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
BlockT *getExitBlock() const;
|
||||
|
||||
/// Edge type.
|
||||
typedef std::pair<const BlockT*, const BlockT*> Edge;
|
||||
|
||||
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
|
||||
void getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const;
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
BlockT *getLoopPreheader() const;
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
/// This is less strict that the loop "preheader" concept, which requires
|
||||
/// the predecessor to have exactly one successor.
|
||||
///
|
||||
BlockT *getLoopPredecessor() const;
|
||||
|
||||
/// getLoopLatch - If there is a single latch block for this loop, return it.
|
||||
/// A latch block is a block that contains a branch back to the header.
|
||||
BlockT *getLoopLatch() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// APIs for updating loop information after changing the CFG
|
||||
//
|
||||
|
||||
/// addBasicBlockToLoop - This method is used by other analyses to update loop
|
||||
/// information. NewBB is set to be a new member of the current loop.
|
||||
/// Because of this, it is added as a member of all parent loops, and is added
|
||||
/// to the specified LoopInfo object as being in the current basic block. It
|
||||
/// is not valid to replace the loop header with this method.
|
||||
///
|
||||
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LI);
|
||||
|
||||
/// replaceChildLoopWith - This is used when splitting loops up. It replaces
|
||||
/// the OldChild entry in our children list with NewChild, and updates the
|
||||
/// parent pointer of OldChild to be null and the NewChild to be this loop.
|
||||
/// This updates the loop depth of the new child.
|
||||
void replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild);
|
||||
|
||||
/// addChildLoop - Add the specified loop to be a child of this loop. This
|
||||
/// updates the loop depth of the new child.
|
||||
///
|
||||
void addChildLoop(LoopT *NewChild) {
|
||||
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
|
||||
NewChild->ParentLoop = static_cast<LoopT *>(this);
|
||||
SubLoops.push_back(NewChild);
|
||||
}
|
||||
|
||||
/// removeChildLoop - This removes the specified child from being a subloop of
|
||||
/// this loop. The loop is not deleted, as it will presumably be inserted
|
||||
/// into another loop.
|
||||
LoopT *removeChildLoop(iterator I) {
|
||||
assert(I != SubLoops.end() && "Cannot remove end iterator!");
|
||||
LoopT *Child = *I;
|
||||
assert(Child->ParentLoop == this && "Child is not a child of this loop!");
|
||||
SubLoops.erase(SubLoops.begin()+(I-begin()));
|
||||
Child->ParentLoop = 0;
|
||||
return Child;
|
||||
}
|
||||
|
||||
/// addBlockEntry - This adds a basic block directly to the basic block list.
|
||||
/// This should only be used by transformations that create new loops. Other
|
||||
/// transformations should use addBasicBlockToLoop.
|
||||
void addBlockEntry(BlockT *BB) {
|
||||
Blocks.push_back(BB);
|
||||
}
|
||||
|
||||
/// moveToHeader - This method is used to move BB (which must be part of this
|
||||
/// loop) to be the loop header of the loop (the block that dominates all
|
||||
/// others).
|
||||
void moveToHeader(BlockT *BB) {
|
||||
if (Blocks[0] == BB) return;
|
||||
for (unsigned i = 0; ; ++i) {
|
||||
assert(i != Blocks.size() && "Loop does not contain BB!");
|
||||
if (Blocks[i] == BB) {
|
||||
Blocks[i] = Blocks[0];
|
||||
Blocks[0] = BB;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// removeBlockFromLoop - This removes the specified basic block from the
|
||||
/// current loop, updating the Blocks as appropriate. This does not update
|
||||
/// the mapping in the LoopInfo class.
|
||||
void removeBlockFromLoop(BlockT *BB) {
|
||||
RemoveFromVector(Blocks, BB);
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure
|
||||
void verifyLoop() const;
|
||||
|
||||
/// verifyLoop - Verify loop structure of this loop and all nested loops.
|
||||
void verifyLoopNest(DenseSet<const LoopT*> *Loops) const;
|
||||
|
||||
void print(raw_ostream &OS, unsigned Depth = 0) const;
|
||||
|
||||
protected:
|
||||
friend class LoopInfoBase<BlockT, LoopT>;
|
||||
explicit LoopBase(BlockT *BB) : ParentLoop(0) {
|
||||
Blocks.push_back(BB);
|
||||
}
|
||||
};
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
|
||||
Loop.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
|
||||
class Loop : public LoopBase<BasicBlock, Loop> {
|
||||
public:
|
||||
Loop() {}
|
||||
|
||||
/// isLoopInvariant - Return true if the specified value is loop invariant
|
||||
///
|
||||
bool isLoopInvariant(Value *V) const;
|
||||
|
||||
/// hasLoopInvariantOperands - Return true if all the operands of the
|
||||
/// specified instruction are loop invariant.
|
||||
bool hasLoopInvariantOperands(Instruction *I) const;
|
||||
|
||||
/// makeLoopInvariant - If the given value is an instruction inside of the
|
||||
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
|
||||
/// Return true if the value after any hoisting is loop invariant. This
|
||||
/// function can be used as a slightly more aggressive replacement for
|
||||
/// isLoopInvariant.
|
||||
///
|
||||
/// If InsertPt is specified, it is the point to hoist instructions to.
|
||||
/// If null, the terminator of the loop preheader is used.
|
||||
///
|
||||
bool makeLoopInvariant(Value *V, bool &Changed,
|
||||
Instruction *InsertPt = 0) const;
|
||||
|
||||
/// makeLoopInvariant - If the given instruction is inside of the
|
||||
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
|
||||
/// Return true if the instruction after any hoisting is loop invariant. This
|
||||
/// function can be used as a slightly more aggressive replacement for
|
||||
/// isLoopInvariant.
|
||||
///
|
||||
/// If InsertPt is specified, it is the point to hoist instructions to.
|
||||
/// If null, the terminator of the loop preheader is used.
|
||||
///
|
||||
bool makeLoopInvariant(Instruction *I, bool &Changed,
|
||||
Instruction *InsertPt = 0) const;
|
||||
|
||||
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
|
||||
/// induction variable: an integer recurrence that starts at 0 and increments
|
||||
/// by one each time through the loop. If so, return the phi node that
|
||||
/// corresponds to it.
|
||||
///
|
||||
/// The IndVarSimplify pass transforms loops to have a canonical induction
|
||||
/// variable.
|
||||
///
|
||||
PHINode *getCanonicalInductionVariable() const;
|
||||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool isLCSSAForm(DominatorTree &DT) const;
|
||||
|
||||
/// isLoopSimplifyForm - Return true if the Loop is in the form that
|
||||
/// the LoopSimplify form transforms loops to, which is sometimes called
|
||||
/// normal form.
|
||||
bool isLoopSimplifyForm() const;
|
||||
|
||||
/// isSafeToClone - Return true if the loop body is safe to clone in practice.
|
||||
bool isSafeToClone() const;
|
||||
|
||||
/// Returns true if the loop is annotated parallel.
|
||||
///
|
||||
/// A parallel loop can be assumed to not contain any dependencies between
|
||||
/// iterations by the compiler. That is, any loop-carried dependency checking
|
||||
/// can be skipped completely when parallelizing the loop on the target
|
||||
/// machine. Thus, if the parallel loop information originates from the
|
||||
/// programmer, e.g. via the OpenMP parallel for pragma, it is the
|
||||
/// programmer's responsibility to ensure there are no loop-carried
|
||||
/// dependencies. The final execution order of the instructions across
|
||||
/// iterations is not guaranteed, thus, the end result might or might not
|
||||
/// implement actual concurrent execution of instructions across multiple
|
||||
/// iterations.
|
||||
bool isAnnotatedParallel() const;
|
||||
|
||||
/// hasDedicatedExits - Return true if no exit block for the loop
|
||||
/// has a predecessor that is outside the loop.
|
||||
bool hasDedicatedExits() const;
|
||||
|
||||
/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
|
||||
/// These are the blocks _outside of the current loop_ which are branched to.
|
||||
/// This assumes that loop exits are in canonical form.
|
||||
///
|
||||
void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
|
||||
|
||||
/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
|
||||
/// block, return that block. Otherwise return null.
|
||||
BasicBlock *getUniqueExitBlock() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
friend class LoopInfoBase<BasicBlock, Loop>;
|
||||
explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// LoopInfo - This class builds and contains all of the top level loop
|
||||
/// structures in the specified function.
|
||||
///
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
class LoopInfoBase {
|
||||
// BBMap - Mapping of basic blocks to the inner most loop they occur in
|
||||
DenseMap<BlockT *, LoopT *> BBMap;
|
||||
std::vector<LoopT *> TopLevelLoops;
|
||||
friend class LoopBase<BlockT, LoopT>;
|
||||
friend class LoopInfo;
|
||||
|
||||
void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION;
|
||||
LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
LoopInfoBase() { }
|
||||
~LoopInfoBase() { releaseMemory(); }
|
||||
|
||||
void releaseMemory() {
|
||||
for (typename std::vector<LoopT *>::iterator I =
|
||||
TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
|
||||
delete *I; // Delete all of the loops...
|
||||
|
||||
BBMap.clear(); // Reset internal state of analysis
|
||||
TopLevelLoops.clear();
|
||||
}
|
||||
|
||||
/// iterator/begin/end - The interface to the top-level loops in the current
|
||||
/// function.
|
||||
///
|
||||
typedef typename std::vector<LoopT *>::const_iterator iterator;
|
||||
typedef typename std::vector<LoopT *>::const_reverse_iterator
|
||||
reverse_iterator;
|
||||
iterator begin() const { return TopLevelLoops.begin(); }
|
||||
iterator end() const { return TopLevelLoops.end(); }
|
||||
reverse_iterator rbegin() const { return TopLevelLoops.rbegin(); }
|
||||
reverse_iterator rend() const { return TopLevelLoops.rend(); }
|
||||
bool empty() const { return TopLevelLoops.empty(); }
|
||||
|
||||
/// getLoopFor - Return the inner most loop that BB lives in. If a basic
|
||||
/// block is in no loop (for example the entry node), null is returned.
|
||||
///
|
||||
LoopT *getLoopFor(const BlockT *BB) const {
|
||||
return BBMap.lookup(const_cast<BlockT*>(BB));
|
||||
}
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
///
|
||||
const LoopT *operator[](const BlockT *BB) const {
|
||||
return getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the loop nesting level of the specified block. A
|
||||
/// depth of 0 means the block is not inside any loop.
|
||||
///
|
||||
unsigned getLoopDepth(const BlockT *BB) const {
|
||||
const LoopT *L = getLoopFor(BB);
|
||||
return L ? L->getLoopDepth() : 0;
|
||||
}
|
||||
|
||||
// isLoopHeader - True if the block is a loop header node
|
||||
bool isLoopHeader(BlockT *BB) const {
|
||||
const LoopT *L = getLoopFor(BB);
|
||||
return L && L->getHeader() == BB;
|
||||
}
|
||||
|
||||
/// removeLoop - This removes the specified top-level loop from this loop info
|
||||
/// object. The loop is not deleted, as it will presumably be inserted into
|
||||
/// another loop.
|
||||
LoopT *removeLoop(iterator I) {
|
||||
assert(I != end() && "Cannot remove end iterator!");
|
||||
LoopT *L = *I;
|
||||
assert(L->getParentLoop() == 0 && "Not a top-level loop!");
|
||||
TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin()));
|
||||
return L;
|
||||
}
|
||||
|
||||
/// changeLoopFor - Change the top-level loop that contains BB to the
|
||||
/// specified loop. This should be used by transformations that restructure
|
||||
/// the loop hierarchy tree.
|
||||
void changeLoopFor(BlockT *BB, LoopT *L) {
|
||||
if (!L) {
|
||||
BBMap.erase(BB);
|
||||
return;
|
||||
}
|
||||
BBMap[BB] = L;
|
||||
}
|
||||
|
||||
/// changeTopLevelLoop - Replace the specified loop in the top-level loops
|
||||
/// list with the indicated loop.
|
||||
void changeTopLevelLoop(LoopT *OldLoop,
|
||||
LoopT *NewLoop) {
|
||||
typename std::vector<LoopT *>::iterator I =
|
||||
std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
|
||||
assert(I != TopLevelLoops.end() && "Old loop not at top level!");
|
||||
*I = NewLoop;
|
||||
assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 &&
|
||||
"Loops already embedded into a subloop!");
|
||||
}
|
||||
|
||||
/// addTopLevelLoop - This adds the specified loop to the collection of
|
||||
/// top-level loops.
|
||||
void addTopLevelLoop(LoopT *New) {
|
||||
assert(New->getParentLoop() == 0 && "Loop already in subloop!");
|
||||
TopLevelLoops.push_back(New);
|
||||
}
|
||||
|
||||
/// removeBlock - This method completely removes BB from all data structures,
|
||||
/// including all of the Loop objects it is nested in and our mapping from
|
||||
/// BasicBlocks to loops.
|
||||
void removeBlock(BlockT *BB) {
|
||||
typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
|
||||
if (I != BBMap.end()) {
|
||||
for (LoopT *L = I->second; L; L = L->getParentLoop())
|
||||
L->removeBlockFromLoop(BB);
|
||||
|
||||
BBMap.erase(I);
|
||||
}
|
||||
}
|
||||
|
||||
// Internals
|
||||
|
||||
static bool isNotAlreadyContainedIn(const LoopT *SubLoop,
|
||||
const LoopT *ParentLoop) {
|
||||
if (SubLoop == 0) return true;
|
||||
if (SubLoop == ParentLoop) return false;
|
||||
return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop);
|
||||
}
|
||||
|
||||
/// Create the loop forest using a stable algorithm.
|
||||
void Analyze(DominatorTreeBase<BlockT> &DomTree);
|
||||
|
||||
// Debugging
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
|
||||
class LoopInfo : public FunctionPass {
|
||||
LoopInfoBase<BasicBlock, Loop> LI;
|
||||
friend class LoopBase<BasicBlock, Loop>;
|
||||
|
||||
void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
LoopInfo() : FunctionPass(ID) {
|
||||
initializeLoopInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }
|
||||
|
||||
/// iterator/begin/end - The interface to the top-level loops in the current
|
||||
/// function.
|
||||
///
|
||||
typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
|
||||
typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator;
|
||||
inline iterator begin() const { return LI.begin(); }
|
||||
inline iterator end() const { return LI.end(); }
|
||||
inline reverse_iterator rbegin() const { return LI.rbegin(); }
|
||||
inline reverse_iterator rend() const { return LI.rend(); }
|
||||
bool empty() const { return LI.empty(); }
|
||||
|
||||
/// getLoopFor - Return the inner most loop that BB lives in. If a basic
|
||||
/// block is in no loop (for example the entry node), null is returned.
|
||||
///
|
||||
inline Loop *getLoopFor(const BasicBlock *BB) const {
|
||||
return LI.getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
///
|
||||
inline const Loop *operator[](const BasicBlock *BB) const {
|
||||
return LI.getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the loop nesting level of the specified block. A
|
||||
/// depth of 0 means the block is not inside any loop.
|
||||
///
|
||||
inline unsigned getLoopDepth(const BasicBlock *BB) const {
|
||||
return LI.getLoopDepth(BB);
|
||||
}
|
||||
|
||||
// isLoopHeader - True if the block is a loop header node
|
||||
inline bool isLoopHeader(BasicBlock *BB) const {
|
||||
return LI.isLoopHeader(BB);
|
||||
}
|
||||
|
||||
/// runOnFunction - Calculate the natural loop information.
|
||||
///
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
virtual void releaseMemory() { LI.releaseMemory(); }
|
||||
|
||||
virtual void print(raw_ostream &O, const Module* M = 0) const;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
/// removeLoop - This removes the specified top-level loop from this loop info
|
||||
/// object. The loop is not deleted, as it will presumably be inserted into
|
||||
/// another loop.
|
||||
inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); }
|
||||
|
||||
/// changeLoopFor - Change the top-level loop that contains BB to the
|
||||
/// specified loop. This should be used by transformations that restructure
|
||||
/// the loop hierarchy tree.
|
||||
inline void changeLoopFor(BasicBlock *BB, Loop *L) {
|
||||
LI.changeLoopFor(BB, L);
|
||||
}
|
||||
|
||||
/// changeTopLevelLoop - Replace the specified loop in the top-level loops
|
||||
/// list with the indicated loop.
|
||||
inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) {
|
||||
LI.changeTopLevelLoop(OldLoop, NewLoop);
|
||||
}
|
||||
|
||||
/// addTopLevelLoop - This adds the specified loop to the collection of
|
||||
/// top-level loops.
|
||||
inline void addTopLevelLoop(Loop *New) {
|
||||
LI.addTopLevelLoop(New);
|
||||
}
|
||||
|
||||
/// removeBlock - This method completely removes BB from all data structures,
|
||||
/// including all of the Loop objects it is nested in and our mapping from
|
||||
/// BasicBlocks to loops.
|
||||
void removeBlock(BasicBlock *BB) {
|
||||
LI.removeBlock(BB);
|
||||
}
|
||||
|
||||
/// updateUnloop - Update LoopInfo after removing the last backedge from a
|
||||
/// loop--now the "unloop". This updates the loop forest and parent loops for
|
||||
/// each block so that Unloop is no longer referenced, but the caller must
|
||||
/// actually delete the Unloop object.
|
||||
void updateUnloop(Loop *Unloop);
|
||||
|
||||
/// replacementPreservesLCSSAForm - Returns true if replacing From with To
|
||||
/// everywhere is guaranteed to preserve LCSSA form.
|
||||
bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {
|
||||
// Preserving LCSSA form is only problematic if the replacing value is an
|
||||
// instruction.
|
||||
Instruction *I = dyn_cast<Instruction>(To);
|
||||
if (!I) return true;
|
||||
// If both instructions are defined in the same basic block then replacement
|
||||
// cannot break LCSSA form.
|
||||
if (I->getParent() == From->getParent())
|
||||
return true;
|
||||
// If the instruction is not defined in a loop then it can safely replace
|
||||
// anything.
|
||||
Loop *ToLoop = getLoopFor(I->getParent());
|
||||
if (!ToLoop) return true;
|
||||
// If the replacing instruction is defined in the same loop as the original
|
||||
// instruction, or in a loop that contains it as an inner loop, then using
|
||||
// it as a replacement will not break LCSSA form.
|
||||
return ToLoop->contains(getLoopFor(From->getParent()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Allow clients to walk the list of nested loops...
|
||||
template <> struct GraphTraits<const Loop*> {
|
||||
typedef const Loop NodeType;
|
||||
typedef LoopInfo::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(const Loop *L) { return L; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Loop*> {
|
||||
typedef Loop NodeType;
|
||||
typedef LoopInfo::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(Loop *L) { return L; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
570
thirdparty/clang/include/llvm/Analysis/LoopInfoImpl.h
vendored
Normal file
570
thirdparty/clang/include/llvm/Analysis/LoopInfoImpl.h
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
//===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the generic implementation of LoopInfo used for both Loops and
|
||||
// MachineLoops.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H
|
||||
#define LLVM_ANALYSIS_LOOPINFOIMPL_H
|
||||
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APIs for simple analysis of the loop. See header notes.
|
||||
|
||||
/// getExitingBlocks - Return all blocks inside the loop that have successors
|
||||
/// outside of the loop. These are the blocks _inside of the current loop_
|
||||
/// which branch out. The returned list is always unique.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) {
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitingBlocks.push_back(*BI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// getExitingBlock - If getExitingBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
|
||||
SmallVector<BlockT*, 8> ExitingBlocks;
|
||||
getExitingBlocks(ExitingBlocks);
|
||||
if (ExitingBlocks.size() == 1)
|
||||
return ExitingBlocks[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getExitBlocks - Return all of the successor blocks of this loop. These
|
||||
/// are the blocks _outside of the current loop_ which are branched to.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitBlocks.push_back(*I);
|
||||
}
|
||||
|
||||
/// getExitBlock - If getExitBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
|
||||
SmallVector<BlockT*, 8> ExitBlocks;
|
||||
getExitBlocks(ExitBlocks);
|
||||
if (ExitBlocks.size() == 1)
|
||||
return ExitBlocks[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
array_pod_sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitEdges.push_back(Edge(*BI, *I));
|
||||
}
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = getLoopPredecessor();
|
||||
if (!Out) return 0;
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
++SI;
|
||||
if (SI != BlockTraits::child_end(Out))
|
||||
return 0; // Multiple exits from the block, must not be a preheader.
|
||||
|
||||
// The predecessor has exactly one successor, so it is a preheader.
|
||||
return Out;
|
||||
}
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
/// This is less strict that the loop "preheader" concept, which requires
|
||||
/// the predecessor to have exactly one successor.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = 0;
|
||||
|
||||
// Loop over the predecessors of the header node...
|
||||
BlockT *Header = getHeader();
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header),
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (!contains(N)) { // If the block is not in the loop...
|
||||
if (Out && Out != N)
|
||||
return 0; // Multiple predecessors outside the loop
|
||||
Out = N;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
assert(Out && "Header of loop has no predecessors from outside loop?");
|
||||
return Out;
|
||||
}
|
||||
|
||||
/// getLoopLatch - If there is a single latch block for this loop, return it.
|
||||
/// A latch block is a block that contains a branch back to the header.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
|
||||
BlockT *Header = getHeader();
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header);
|
||||
typename InvBlockTraits::ChildIteratorType PE =
|
||||
InvBlockTraits::child_end(Header);
|
||||
BlockT *Latch = 0;
|
||||
for (; PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (contains(N)) {
|
||||
if (Latch) return 0;
|
||||
Latch = N;
|
||||
}
|
||||
}
|
||||
|
||||
return Latch;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APIs for updating loop information after changing the CFG
|
||||
//
|
||||
|
||||
/// addBasicBlockToLoop - This method is used by other analyses to update loop
|
||||
/// information. NewBB is set to be a new member of the current loop.
|
||||
/// Because of this, it is added as a member of all parent loops, and is added
|
||||
/// to the specified LoopInfo object as being in the current basic block. It
|
||||
/// is not valid to replace the loop header with this method.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) {
|
||||
assert((Blocks.empty() || LIB[getHeader()] == this) &&
|
||||
"Incorrect LI specified for this loop!");
|
||||
assert(NewBB && "Cannot add a null basic block to the loop!");
|
||||
assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!");
|
||||
|
||||
LoopT *L = static_cast<LoopT *>(this);
|
||||
|
||||
// Add the loop mapping to the LoopInfo object...
|
||||
LIB.BBMap[NewBB] = L;
|
||||
|
||||
// Add the basic block to this loop and all parent loops...
|
||||
while (L) {
|
||||
L->Blocks.push_back(NewBB);
|
||||
L = L->getParentLoop();
|
||||
}
|
||||
}
|
||||
|
||||
/// replaceChildLoopWith - This is used when splitting loops up. It replaces
|
||||
/// the OldChild entry in our children list with NewChild, and updates the
|
||||
/// parent pointer of OldChild to be null and the NewChild to be this loop.
|
||||
/// This updates the loop depth of the new child.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild) {
|
||||
assert(OldChild->ParentLoop == this && "This loop is already broken!");
|
||||
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
|
||||
typename std::vector<LoopT *>::iterator I =
|
||||
std::find(SubLoops.begin(), SubLoops.end(), OldChild);
|
||||
assert(I != SubLoops.end() && "OldChild not in loop!");
|
||||
*I = NewChild;
|
||||
OldChild->ParentLoop = 0;
|
||||
NewChild->ParentLoop = static_cast<LoopT *>(this);
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
#ifndef NDEBUG
|
||||
assert(!Blocks.empty() && "Loop header is missing");
|
||||
|
||||
// Setup for using a depth-first iterator to visit every block in the loop.
|
||||
SmallVector<BlockT*, 8> ExitBBs;
|
||||
getExitBlocks(ExitBBs);
|
||||
llvm::SmallPtrSet<BlockT*, 8> VisitSet;
|
||||
VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
|
||||
df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> >
|
||||
BI = df_ext_begin(getHeader(), VisitSet),
|
||||
BE = df_ext_end(getHeader(), VisitSet);
|
||||
|
||||
// Keep track of the number of BBs visited.
|
||||
unsigned NumVisited = 0;
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
// Check the individual blocks.
|
||||
for ( ; BI != BE; ++BI) {
|
||||
BlockT *BB = *BI;
|
||||
bool HasInsideLoopSuccs = false;
|
||||
bool HasInsideLoopPreds = false;
|
||||
SmallVector<BlockT *, 2> OutsideLoopPreds;
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (typename BlockTraits::ChildIteratorType SI =
|
||||
BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
|
||||
SI != SE; ++SI)
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) {
|
||||
HasInsideLoopSuccs = true;
|
||||
break;
|
||||
}
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *N = *PI;
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
|
||||
HasInsideLoopPreds = true;
|
||||
else
|
||||
OutsideLoopPreds.push_back(N);
|
||||
}
|
||||
|
||||
if (BB == getHeader()) {
|
||||
assert(!OutsideLoopPreds.empty() && "Loop is unreachable!");
|
||||
} else if (!OutsideLoopPreds.empty()) {
|
||||
// A non-header loop shouldn't be reachable from outside the loop,
|
||||
// though it is permitted if the predecessor is not itself actually
|
||||
// reachable.
|
||||
BlockT *EntryBB = BB->getParent()->begin();
|
||||
for (df_iterator<BlockT *> NI = df_begin(EntryBB),
|
||||
NE = df_end(EntryBB); NI != NE; ++NI)
|
||||
for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
|
||||
assert(*NI != OutsideLoopPreds[i] &&
|
||||
"Loop has multiple entry points!");
|
||||
}
|
||||
assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
|
||||
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
|
||||
assert(BB != getHeader()->getParent()->begin() &&
|
||||
"Loop contains function entry block!");
|
||||
|
||||
NumVisited++;
|
||||
}
|
||||
|
||||
assert(NumVisited == getNumBlocks() && "Unreachable block in loop");
|
||||
|
||||
// Check the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
// Each block in each subloop should be contained within this loop.
|
||||
for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
|
||||
BI != BE; ++BI) {
|
||||
assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) &&
|
||||
"Loop does not contain all the blocks of a subloop!");
|
||||
}
|
||||
|
||||
// Check the parent loop pointer.
|
||||
if (ParentLoop) {
|
||||
assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) !=
|
||||
ParentLoop->end() &&
|
||||
"Loop is not a subloop of its parent!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure of this loop and all nested loops.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::verifyLoopNest(
|
||||
DenseSet<const LoopT*> *Loops) const {
|
||||
Loops->insert(static_cast<const LoopT *>(this));
|
||||
// Verify this loop.
|
||||
verifyLoop();
|
||||
// Verify the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
(*I)->verifyLoopNest(Loops);
|
||||
}
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const {
|
||||
OS.indent(Depth*2) << "Loop at depth " << getLoopDepth()
|
||||
<< " containing: ";
|
||||
|
||||
for (unsigned i = 0; i < getBlocks().size(); ++i) {
|
||||
if (i) OS << ",";
|
||||
BlockT *BB = getBlocks()[i];
|
||||
WriteAsOperand(OS, BB, false);
|
||||
if (BB == getHeader()) OS << "<header>";
|
||||
if (BB == getLoopLatch()) OS << "<latch>";
|
||||
if (isLoopExiting(BB)) OS << "<exiting>";
|
||||
}
|
||||
OS << "\n";
|
||||
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
(*I)->print(OS, Depth+2);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Stable LoopInfo Analysis - Build a loop tree using stable iterators so the
|
||||
/// result does / not depend on use list (block predecessor) order.
|
||||
///
|
||||
|
||||
/// Discover a subloop with the specified backedges such that: All blocks within
|
||||
/// this loop are mapped to this loop or a subloop. And all subloops within this
|
||||
/// loop have their parent loop set to this loop or a subloop.
|
||||
template<class BlockT, class LoopT>
|
||||
static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
|
||||
LoopInfoBase<BlockT, LoopT> *LI,
|
||||
DominatorTreeBase<BlockT> &DomTree) {
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
|
||||
unsigned NumBlocks = 0;
|
||||
unsigned NumSubloops = 0;
|
||||
|
||||
// Perform a backward CFG traversal using a worklist.
|
||||
std::vector<BlockT *> ReverseCFGWorklist(Backedges.begin(), Backedges.end());
|
||||
while (!ReverseCFGWorklist.empty()) {
|
||||
BlockT *PredBB = ReverseCFGWorklist.back();
|
||||
ReverseCFGWorklist.pop_back();
|
||||
|
||||
LoopT *Subloop = LI->getLoopFor(PredBB);
|
||||
if (!Subloop) {
|
||||
if (!DomTree.isReachableFromEntry(PredBB))
|
||||
continue;
|
||||
|
||||
// This is an undiscovered block. Map it to the current loop.
|
||||
LI->changeLoopFor(PredBB, L);
|
||||
++NumBlocks;
|
||||
if (PredBB == L->getHeader())
|
||||
continue;
|
||||
// Push all block predecessors on the worklist.
|
||||
ReverseCFGWorklist.insert(ReverseCFGWorklist.end(),
|
||||
InvBlockTraits::child_begin(PredBB),
|
||||
InvBlockTraits::child_end(PredBB));
|
||||
}
|
||||
else {
|
||||
// This is a discovered block. Find its outermost discovered loop.
|
||||
while (LoopT *Parent = Subloop->getParentLoop())
|
||||
Subloop = Parent;
|
||||
|
||||
// If it is already discovered to be a subloop of this loop, continue.
|
||||
if (Subloop == L)
|
||||
continue;
|
||||
|
||||
// Discover a subloop of this loop.
|
||||
Subloop->setParentLoop(L);
|
||||
++NumSubloops;
|
||||
NumBlocks += Subloop->getBlocks().capacity();
|
||||
PredBB = Subloop->getHeader();
|
||||
// Continue traversal along predecessors that are not loop-back edges from
|
||||
// within this subloop tree itself. Note that a predecessor may directly
|
||||
// reach another subloop that is not yet discovered to be a subloop of
|
||||
// this loop, which we must traverse.
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(PredBB),
|
||||
PE = InvBlockTraits::child_end(PredBB); PI != PE; ++PI) {
|
||||
if (LI->getLoopFor(*PI) != Subloop)
|
||||
ReverseCFGWorklist.push_back(*PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
L->getSubLoopsVector().reserve(NumSubloops);
|
||||
L->getBlocksVector().reserve(NumBlocks);
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Populate all loop data in a stable order during a single forward DFS.
|
||||
template<class BlockT, class LoopT>
|
||||
class PopulateLoopsDFS {
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
|
||||
|
||||
LoopInfoBase<BlockT, LoopT> *LI;
|
||||
DenseSet<const BlockT *> VisitedBlocks;
|
||||
std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack;
|
||||
|
||||
public:
|
||||
PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li):
|
||||
LI(li) {}
|
||||
|
||||
void traverse(BlockT *EntryBlock);
|
||||
|
||||
protected:
|
||||
void insertIntoLoop(BlockT *Block);
|
||||
|
||||
BlockT *dfsSource() { return DFSStack.back().first; }
|
||||
SuccIterTy &dfsSucc() { return DFSStack.back().second; }
|
||||
SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); }
|
||||
|
||||
void pushBlock(BlockT *Block) {
|
||||
DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block)));
|
||||
}
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
/// Top-level driver for the forward DFS within the loop.
|
||||
template<class BlockT, class LoopT>
|
||||
void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) {
|
||||
pushBlock(EntryBlock);
|
||||
VisitedBlocks.insert(EntryBlock);
|
||||
while (!DFSStack.empty()) {
|
||||
// Traverse the leftmost path as far as possible.
|
||||
while (dfsSucc() != dfsSuccEnd()) {
|
||||
BlockT *BB = *dfsSucc();
|
||||
++dfsSucc();
|
||||
if (!VisitedBlocks.insert(BB).second)
|
||||
continue;
|
||||
|
||||
// Push the next DFS successor onto the stack.
|
||||
pushBlock(BB);
|
||||
}
|
||||
// Visit the top of the stack in postorder and backtrack.
|
||||
insertIntoLoop(dfsSource());
|
||||
DFSStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a single Block to its ancestor loops in PostOrder. If the block is a
|
||||
/// subloop header, add the subloop to its parent in PostOrder, then reverse the
|
||||
/// Block and Subloop vectors of the now complete subloop to achieve RPO.
|
||||
template<class BlockT, class LoopT>
|
||||
void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
|
||||
LoopT *Subloop = LI->getLoopFor(Block);
|
||||
if (Subloop && Block == Subloop->getHeader()) {
|
||||
// We reach this point once per subloop after processing all the blocks in
|
||||
// the subloop.
|
||||
if (Subloop->getParentLoop())
|
||||
Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop);
|
||||
else
|
||||
LI->addTopLevelLoop(Subloop);
|
||||
|
||||
// For convenience, Blocks and Subloops are inserted in postorder. Reverse
|
||||
// the lists, except for the loop header, which is always at the beginning.
|
||||
std::reverse(Subloop->getBlocksVector().begin()+1,
|
||||
Subloop->getBlocksVector().end());
|
||||
std::reverse(Subloop->getSubLoopsVector().begin(),
|
||||
Subloop->getSubLoopsVector().end());
|
||||
|
||||
Subloop = Subloop->getParentLoop();
|
||||
}
|
||||
for (; Subloop; Subloop = Subloop->getParentLoop())
|
||||
Subloop->getBlocksVector().push_back(Block);
|
||||
}
|
||||
|
||||
/// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal
|
||||
/// interleaved with backward CFG traversals within each subloop
|
||||
/// (discoverAndMapSubloop). The backward traversal skips inner subloops, so
|
||||
/// this part of the algorithm is linear in the number of CFG edges. Subloop and
|
||||
/// Block vectors are then populated during a single forward CFG traversal
|
||||
/// (PopulateLoopDFS).
|
||||
///
|
||||
/// During the two CFG traversals each block is seen three times:
|
||||
/// 1) Discovered and mapped by a reverse CFG traversal.
|
||||
/// 2) Visited during a forward DFS CFG traversal.
|
||||
/// 3) Reverse-inserted in the loop in postorder following forward DFS.
|
||||
///
|
||||
/// The Block vectors are inclusive, so step 3 requires loop-depth number of
|
||||
/// insertions per block.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopInfoBase<BlockT, LoopT>::
|
||||
Analyze(DominatorTreeBase<BlockT> &DomTree) {
|
||||
|
||||
// Postorder traversal of the dominator tree.
|
||||
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
|
||||
for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot),
|
||||
DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) {
|
||||
|
||||
BlockT *Header = DomIter->getBlock();
|
||||
SmallVector<BlockT *, 4> Backedges;
|
||||
|
||||
// Check each predecessor of the potential loop header.
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header),
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
|
||||
|
||||
BlockT *Backedge = *PI;
|
||||
|
||||
// If Header dominates predBB, this is a new loop. Collect the backedges.
|
||||
if (DomTree.dominates(Header, Backedge)
|
||||
&& DomTree.isReachableFromEntry(Backedge)) {
|
||||
Backedges.push_back(Backedge);
|
||||
}
|
||||
}
|
||||
// Perform a backward CFG traversal to discover and map blocks in this loop.
|
||||
if (!Backedges.empty()) {
|
||||
LoopT *L = new LoopT(Header);
|
||||
discoverAndMapSubloop(L, ArrayRef<BlockT*>(Backedges), this, DomTree);
|
||||
}
|
||||
}
|
||||
// Perform a single forward CFG traversal to populate block and subloop
|
||||
// vectors for all loops.
|
||||
PopulateLoopsDFS<BlockT, LoopT> DFS(this);
|
||||
DFS.traverse(DomRoot->getBlock());
|
||||
}
|
||||
|
||||
// Debugging
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
|
||||
for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
|
||||
TopLevelLoops[i]->print(OS);
|
||||
#if 0
|
||||
for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
|
||||
E = BBMap.end(); I != E; ++I)
|
||||
OS << "BB '" << I->first->getName() << "' level = "
|
||||
<< I->second->getLoopDepth() << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
181
thirdparty/clang/include/llvm/Analysis/LoopIterator.h
vendored
Normal file
181
thirdparty/clang/include/llvm/Analysis/LoopIterator.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
//===--------- LoopIterator.h - Iterate over loop blocks --------*- 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 iterators to visit the basic blocks within a loop.
|
||||
//
|
||||
// These iterators currently visit blocks within subloops as well.
|
||||
// Unfortunately we have no efficient way of summarizing loop exits which would
|
||||
// allow skipping subloops during traversal.
|
||||
//
|
||||
// If you want to visit all blocks in a loop and don't need an ordered traveral,
|
||||
// use Loop::block_begin() instead.
|
||||
//
|
||||
// This is intentionally designed to work with ill-formed loops in which the
|
||||
// backedge has been deleted. The only prerequisite is that all blocks
|
||||
// contained within the loop according to the most recent LoopInfo analysis are
|
||||
// reachable from the loop header.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPITERATOR_H
|
||||
#define LLVM_ANALYSIS_LOOPITERATOR_H
|
||||
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoopBlocksTraversal;
|
||||
|
||||
/// Store the result of a depth first search within basic blocks contained by a
|
||||
/// single loop.
|
||||
///
|
||||
/// TODO: This could be generalized for any CFG region, or the entire CFG.
|
||||
class LoopBlocksDFS {
|
||||
public:
|
||||
/// Postorder list iterators.
|
||||
typedef std::vector<BasicBlock*>::const_iterator POIterator;
|
||||
typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
|
||||
|
||||
friend class LoopBlocksTraversal;
|
||||
|
||||
private:
|
||||
Loop *L;
|
||||
|
||||
/// Map each block to its postorder number. A block is only mapped after it is
|
||||
/// preorder visited by DFS. It's postorder number is initially zero and set
|
||||
/// to nonzero after it is finished by postorder traversal.
|
||||
DenseMap<BasicBlock*, unsigned> PostNumbers;
|
||||
std::vector<BasicBlock*> PostBlocks;
|
||||
|
||||
public:
|
||||
LoopBlocksDFS(Loop *Container) :
|
||||
L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
|
||||
PostBlocks.reserve(Container->getNumBlocks());
|
||||
}
|
||||
|
||||
Loop *getLoop() const { return L; }
|
||||
|
||||
/// Traverse the loop blocks and store the DFS result.
|
||||
void perform(LoopInfo *LI);
|
||||
|
||||
/// Return true if postorder numbers are assigned to all loop blocks.
|
||||
bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
|
||||
|
||||
/// Iterate over the cached postorder blocks.
|
||||
POIterator beginPostorder() const {
|
||||
assert(isComplete() && "bad loop DFS");
|
||||
return PostBlocks.begin();
|
||||
}
|
||||
POIterator endPostorder() const { return PostBlocks.end(); }
|
||||
|
||||
/// Reverse iterate over the cached postorder blocks.
|
||||
RPOIterator beginRPO() const {
|
||||
assert(isComplete() && "bad loop DFS");
|
||||
return PostBlocks.rbegin();
|
||||
}
|
||||
RPOIterator endRPO() const { return PostBlocks.rend(); }
|
||||
|
||||
/// Return true if this block has been preorder visited.
|
||||
bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
|
||||
|
||||
/// Return true if this block has a postorder number.
|
||||
bool hasPostorder(BasicBlock *BB) const {
|
||||
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
|
||||
return I != PostNumbers.end() && I->second;
|
||||
}
|
||||
|
||||
/// Get a block's postorder number.
|
||||
unsigned getPostorder(BasicBlock *BB) const {
|
||||
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
|
||||
assert(I != PostNumbers.end() && "block not visited by DFS");
|
||||
assert(I->second && "block not finished by DFS");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// Get a block's reverse postorder number.
|
||||
unsigned getRPO(BasicBlock *BB) const {
|
||||
return 1 + PostBlocks.size() - getPostorder(BB);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
PostNumbers.clear();
|
||||
PostBlocks.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/// Specialize po_iterator_storage to record postorder numbers.
|
||||
template<> class po_iterator_storage<LoopBlocksTraversal, true> {
|
||||
LoopBlocksTraversal &LBT;
|
||||
public:
|
||||
po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {}
|
||||
// These functions are defined below.
|
||||
bool insertEdge(BasicBlock *From, BasicBlock *To);
|
||||
void finishPostorder(BasicBlock *BB);
|
||||
};
|
||||
|
||||
/// Traverse the blocks in a loop using a depth-first search.
|
||||
class LoopBlocksTraversal {
|
||||
public:
|
||||
/// Graph traversal iterator.
|
||||
typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
|
||||
|
||||
private:
|
||||
LoopBlocksDFS &DFS;
|
||||
LoopInfo *LI;
|
||||
|
||||
public:
|
||||
LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) :
|
||||
DFS(Storage), LI(LInfo) {}
|
||||
|
||||
/// Postorder traversal over the graph. This only needs to be done once.
|
||||
/// po_iterator "automatically" calls back to visitPreorder and
|
||||
/// finishPostorder to record the DFS result.
|
||||
POTIterator begin() {
|
||||
assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
|
||||
assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
|
||||
return po_ext_begin(DFS.L->getHeader(), *this);
|
||||
}
|
||||
POTIterator end() {
|
||||
// po_ext_end interface requires a basic block, but ignores its value.
|
||||
return po_ext_end(DFS.L->getHeader(), *this);
|
||||
}
|
||||
|
||||
/// Called by po_iterator upon reaching a block via a CFG edge. If this block
|
||||
/// is contained in the loop and has not been visited, then mark it preorder
|
||||
/// visited and return true.
|
||||
///
|
||||
/// TODO: If anyone is interested, we could record preorder numbers here.
|
||||
bool visitPreorder(BasicBlock *BB) {
|
||||
if (!DFS.L->contains(LI->getLoopFor(BB)))
|
||||
return false;
|
||||
|
||||
return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
|
||||
}
|
||||
|
||||
/// Called by po_iterator each time it advances, indicating a block's
|
||||
/// postorder.
|
||||
void finishPostorder(BasicBlock *BB) {
|
||||
assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
|
||||
DFS.PostBlocks.push_back(BB);
|
||||
DFS.PostNumbers[BB] = DFS.PostBlocks.size();
|
||||
}
|
||||
};
|
||||
|
||||
inline bool po_iterator_storage<LoopBlocksTraversal, true>::
|
||||
insertEdge(BasicBlock *From, BasicBlock *To) {
|
||||
return LBT.visitPreorder(To);
|
||||
}
|
||||
|
||||
inline void po_iterator_storage<LoopBlocksTraversal, true>::
|
||||
finishPostorder(BasicBlock *BB) {
|
||||
LBT.finishPostorder(BB);
|
||||
}
|
||||
|
||||
} // End namespace llvm
|
||||
|
||||
#endif
|
||||
160
thirdparty/clang/include/llvm/Analysis/LoopPass.h
vendored
Normal file
160
thirdparty/clang/include/llvm/Analysis/LoopPass.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
//===- LoopPass.h - LoopPass class ----------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines LoopPass class. All loop optimization
|
||||
// and transformation passes are derived from LoopPass.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPPASS_H
|
||||
#define LLVM_ANALYSIS_LOOPPASS_H
|
||||
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/PassManagers.h"
|
||||
#include <deque>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LPPassManager;
|
||||
class Function;
|
||||
class PMStack;
|
||||
|
||||
class LoopPass : public Pass {
|
||||
public:
|
||||
explicit LoopPass(char &pid) : Pass(PT_Loop, pid) {}
|
||||
|
||||
/// getPrinterPass - Get a pass to print the function corresponding
|
||||
/// to a Loop.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
// runOnLoop - This method should be implemented by the subclass to perform
|
||||
// whatever action is necessary for the specified Loop.
|
||||
virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0;
|
||||
|
||||
using llvm::Pass::doInitialization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
// Initialization and finalization hooks.
|
||||
virtual bool doInitialization(Loop *L, LPPassManager &LPM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finalization hook does not supply Loop because at this time
|
||||
// loop nest is completely different.
|
||||
virtual bool doFinalization() { return false; }
|
||||
|
||||
// Check if this pass is suitable for the current LPPassManager, if
|
||||
// available. This pass P is not suitable for a LPPassManager if P
|
||||
// is not preserving higher level analysis info used by other
|
||||
// LPPassManager passes. In such case, pop LPPassManager from the
|
||||
// stack. This will force assignPassManager() to create new
|
||||
// LPPassManger as expected.
|
||||
void preparePassManager(PMStack &PMS);
|
||||
|
||||
/// Assign pass manager to manage this pass
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_LoopPassManager;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SimpleAnalysis - Provides simple interface to update analysis info
|
||||
/// maintained by various passes. Note, if required this interface can
|
||||
/// be extracted into a separate abstract class but it would require
|
||||
/// additional use of multiple inheritance in Pass class hierarchy, something
|
||||
/// we are trying to avoid.
|
||||
|
||||
/// Each loop pass can override these simple analysis hooks to update
|
||||
/// desired analysis information.
|
||||
/// cloneBasicBlockAnalysis - Clone analysis info associated with basic block.
|
||||
virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {}
|
||||
|
||||
/// deleteAnalysisValue - Delete analysis info associated with value V.
|
||||
virtual void deleteAnalysisValue(Value *V, Loop *L) {}
|
||||
};
|
||||
|
||||
class LPPassManager : public FunctionPass, public PMDataManager {
|
||||
public:
|
||||
static char ID;
|
||||
explicit LPPassManager();
|
||||
|
||||
/// run - Execute all of the passes scheduled for execution. Keep track of
|
||||
/// whether any of the passes modifies the module, and if so, return true.
|
||||
bool runOnFunction(Function &F);
|
||||
|
||||
/// Pass Manager itself does not invalidate any analysis info.
|
||||
// LPPassManager needs LoopInfo.
|
||||
void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "Loop Pass Manager";
|
||||
}
|
||||
|
||||
virtual PMDataManager *getAsPMDataManager() { return this; }
|
||||
virtual Pass *getAsPass() { return this; }
|
||||
|
||||
/// Print passes managed by this manager
|
||||
void dumpPassStructure(unsigned Offset);
|
||||
|
||||
LoopPass *getContainedPass(unsigned N) {
|
||||
assert(N < PassVector.size() && "Pass number out of range!");
|
||||
LoopPass *LP = static_cast<LoopPass *>(PassVector[N]);
|
||||
return LP;
|
||||
}
|
||||
|
||||
virtual PassManagerType getPassManagerType() const {
|
||||
return PMT_LoopPassManager;
|
||||
}
|
||||
|
||||
public:
|
||||
// Delete loop from the loop queue and loop nest (LoopInfo).
|
||||
void deleteLoopFromQueue(Loop *L);
|
||||
|
||||
// Insert loop into the loop queue and add it as a child of the
|
||||
// given parent.
|
||||
void insertLoop(Loop *L, Loop *ParentLoop);
|
||||
|
||||
// Insert a loop into the loop queue.
|
||||
void insertLoopIntoQueue(Loop *L);
|
||||
|
||||
// Reoptimize this loop. LPPassManager will re-insert this loop into the
|
||||
// queue. This allows LoopPass to change loop nest for the loop. This
|
||||
// utility may send LPPassManager into infinite loops so use caution.
|
||||
void redoLoop(Loop *L);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SimpleAnalysis - Provides simple interface to update analysis info
|
||||
/// maintained by various passes. Note, if required this interface can
|
||||
/// be extracted into a separate abstract class but it would require
|
||||
/// additional use of multiple inheritance in Pass class hierarchy, something
|
||||
/// we are trying to avoid.
|
||||
|
||||
/// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for
|
||||
/// all passes that implement simple analysis interface.
|
||||
void cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L);
|
||||
|
||||
/// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes
|
||||
/// that implement simple analysis interface.
|
||||
void deleteSimpleAnalysisValue(Value *V, Loop *L);
|
||||
|
||||
private:
|
||||
std::deque<Loop *> LQ;
|
||||
bool skipThisLoop;
|
||||
bool redoThisLoop;
|
||||
LoopInfo *LI;
|
||||
Loop *CurrentLoop;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
268
thirdparty/clang/include/llvm/Analysis/MemoryBuiltins.h
vendored
Normal file
268
thirdparty/clang/include/llvm/Analysis/MemoryBuiltins.h
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This family of functions identifies calls to builtin functions that allocate
|
||||
// or free memory.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||
#define LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/InstVisitor.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/TargetFolder.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
|
||||
namespace llvm {
|
||||
class CallInst;
|
||||
class PointerType;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
||||
/// like).
|
||||
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a function that returns a
|
||||
/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
|
||||
bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates uninitialized memory (such as malloc).
|
||||
bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates zero-filled memory (such as calloc).
|
||||
bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates memory (either malloc, calloc, or strdup like).
|
||||
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// reallocates memory (such as realloc).
|
||||
bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// malloc Call Utility Functions.
|
||||
//
|
||||
|
||||
/// extractMallocCall - Returns the corresponding CallInst if the instruction
|
||||
/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we
|
||||
/// ignore InvokeInst here.
|
||||
const CallInst *extractMallocCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
static inline CallInst *extractMallocCall(Value *I,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
/// isArrayMalloc - Returns the corresponding CallInst if the instruction
|
||||
/// is a call to malloc whose array size can be determined and the array size
|
||||
/// is not constant 1. Otherwise, return NULL.
|
||||
const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocType - Returns the PointerType resulting from the malloc call.
|
||||
/// The PointerType depends on the number of bitcast uses of the malloc call:
|
||||
/// 0: PointerType is the malloc calls' return type.
|
||||
/// 1: PointerType is the bitcast's result type.
|
||||
/// >1: Unique PointerType cannot be determined, return NULL.
|
||||
PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocAllocatedType - Returns the Type allocated by malloc call.
|
||||
/// The Type depends on the number of bitcast uses of the malloc call:
|
||||
/// 0: PointerType is the malloc calls' return type.
|
||||
/// 1: PointerType is the bitcast's result type.
|
||||
/// >1: Unique PointerType cannot be determined, return NULL.
|
||||
Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocArraySize - Returns the array size of a malloc call. If the
|
||||
/// argument passed to malloc is a multiple of the size of the malloced type,
|
||||
/// then return that multiple. For non-array mallocs, the multiple is
|
||||
/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
|
||||
/// determined.
|
||||
Value *getMallocArraySize(CallInst *CI, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool LookThroughSExt = false);
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// calloc Call Utility Functions.
|
||||
//
|
||||
|
||||
/// extractCallocCall - Returns the corresponding CallInst if the instruction
|
||||
/// is a calloc call.
|
||||
const CallInst *extractCallocCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
static inline CallInst *extractCallocCall(Value *I,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(extractCallocCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// free Call Utility Functions.
|
||||
//
|
||||
|
||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||
const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
|
||||
static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions to compute size of objects.
|
||||
//
|
||||
|
||||
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
|
||||
/// object size in Size if successful, and false otherwise. In this context, by
|
||||
/// object we mean the region of memory starting at Ptr to the end of the
|
||||
/// underlying object pointed to by Ptr.
|
||||
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
|
||||
/// byval arguments, and global variables.
|
||||
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI, bool RoundToAlign = false);
|
||||
|
||||
|
||||
|
||||
typedef std::pair<APInt, APInt> SizeOffsetType;
|
||||
|
||||
/// \brief Evaluate the size and offset of an object ponted by a Value*
|
||||
/// statically. Fails if size or offset are not known at compile time.
|
||||
class ObjectSizeOffsetVisitor
|
||||
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
|
||||
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
bool RoundToAlign;
|
||||
unsigned IntTyBits;
|
||||
APInt Zero;
|
||||
SmallPtrSet<Instruction *, 8> SeenInsts;
|
||||
|
||||
APInt align(APInt Size, uint64_t Align);
|
||||
|
||||
SizeOffsetType unknown() {
|
||||
return std::make_pair(APInt(), APInt());
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI,
|
||||
LLVMContext &Context, bool RoundToAlign = false);
|
||||
|
||||
SizeOffsetType compute(Value *V);
|
||||
|
||||
bool knownSize(SizeOffsetType &SizeOffset) {
|
||||
return SizeOffset.first.getBitWidth() > 1;
|
||||
}
|
||||
|
||||
bool knownOffset(SizeOffsetType &SizeOffset) {
|
||||
return SizeOffset.second.getBitWidth() > 1;
|
||||
}
|
||||
|
||||
bool bothKnown(SizeOffsetType &SizeOffset) {
|
||||
return knownSize(SizeOffset) && knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
SizeOffsetType visitAllocaInst(AllocaInst &I);
|
||||
SizeOffsetType visitArgument(Argument &A);
|
||||
SizeOffsetType visitCallSite(CallSite CS);
|
||||
SizeOffsetType visitConstantPointerNull(ConstantPointerNull&);
|
||||
SizeOffsetType visitExtractElementInst(ExtractElementInst &I);
|
||||
SizeOffsetType visitExtractValueInst(ExtractValueInst &I);
|
||||
SizeOffsetType visitGEPOperator(GEPOperator &GEP);
|
||||
SizeOffsetType visitGlobalAlias(GlobalAlias &GA);
|
||||
SizeOffsetType visitGlobalVariable(GlobalVariable &GV);
|
||||
SizeOffsetType visitIntToPtrInst(IntToPtrInst&);
|
||||
SizeOffsetType visitLoadInst(LoadInst &I);
|
||||
SizeOffsetType visitPHINode(PHINode&);
|
||||
SizeOffsetType visitSelectInst(SelectInst &I);
|
||||
SizeOffsetType visitUndefValue(UndefValue&);
|
||||
SizeOffsetType visitInstruction(Instruction &I);
|
||||
};
|
||||
|
||||
typedef std::pair<Value*, Value*> SizeOffsetEvalType;
|
||||
|
||||
|
||||
/// \brief Evaluate the size and offset of an object ponted by a Value*.
|
||||
/// May create code to compute the result at run-time.
|
||||
class ObjectSizeOffsetEvaluator
|
||||
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
|
||||
|
||||
typedef IRBuilder<true, TargetFolder> BuilderTy;
|
||||
typedef std::pair<WeakVH, WeakVH> WeakEvalType;
|
||||
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
|
||||
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
|
||||
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
LLVMContext &Context;
|
||||
BuilderTy Builder;
|
||||
IntegerType *IntTy;
|
||||
Value *Zero;
|
||||
CacheMapTy CacheMap;
|
||||
PtrSetTy SeenVals;
|
||||
|
||||
SizeOffsetEvalType unknown() {
|
||||
return std::make_pair((Value*)0, (Value*)0);
|
||||
}
|
||||
SizeOffsetEvalType compute_(Value *V);
|
||||
|
||||
public:
|
||||
ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI,
|
||||
LLVMContext &Context);
|
||||
SizeOffsetEvalType compute(Value *V);
|
||||
|
||||
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
||||
return SizeOffset.first;
|
||||
}
|
||||
|
||||
bool knownOffset(SizeOffsetEvalType SizeOffset) {
|
||||
return SizeOffset.second;
|
||||
}
|
||||
|
||||
bool anyKnown(SizeOffsetEvalType SizeOffset) {
|
||||
return knownSize(SizeOffset) || knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
bool bothKnown(SizeOffsetEvalType SizeOffset) {
|
||||
return knownSize(SizeOffset) && knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
|
||||
SizeOffsetEvalType visitCallSite(CallSite CS);
|
||||
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I);
|
||||
SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I);
|
||||
SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP);
|
||||
SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&);
|
||||
SizeOffsetEvalType visitLoadInst(LoadInst &I);
|
||||
SizeOffsetEvalType visitPHINode(PHINode &PHI);
|
||||
SizeOffsetEvalType visitSelectInst(SelectInst &I);
|
||||
SizeOffsetEvalType visitInstruction(Instruction &I);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user