Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,336 @@
//===-- 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 LLVM_NODISCARD 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(APInt I, bool isUnsigned = true)
: APInt(std::move(I)), IsUnsigned(isUnsigned) {}
/// Construct an APSInt from a string representation.
///
/// This constructor interprets the string \p Str using the radix of 10.
/// The interpretation stops at the end of the string. The bit width of the
/// constructed APSInt is determined automatically.
///
/// \param Str the string to be interpreted.
explicit APSInt(StringRef Str);
APSInt &operator=(APInt RHS) {
// Retain our current sign.
APInt::operator=(std::move(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; you should prefer passing in a SmallString instead.
std::string toString(unsigned Radix) const {
return APInt::toString(Radix, isSigned());
}
using APInt::toString;
/// \brief Get the correctly-extended \c int64_t value.
int64_t getExtValue() const {
assert(getMinSignedBits() <= 64 && "Too many bits for int64_t");
return isSigned() ? getSExtValue() : getZExtValue();
}
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) {
if (IsUnsigned)
lshrInPlace(Amt);
else
ashrInPlace(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!=(const APSInt& RHS) const {
return !((*this) == RHS);
}
bool operator==(int64_t RHS) const {
return compareValues(*this, get(RHS)) == 0;
}
bool operator!=(int64_t RHS) const {
return compareValues(*this, get(RHS)) != 0;
}
bool operator<=(int64_t RHS) const {
return compareValues(*this, get(RHS)) <= 0;
}
bool operator>=(int64_t RHS) const {
return compareValues(*this, get(RHS)) >= 0;
}
bool operator<(int64_t RHS) const {
return compareValues(*this, get(RHS)) < 0;
}
bool operator>(int64_t RHS) const {
return compareValues(*this, get(RHS)) > 0;
}
// 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) {
static_cast<APInt&>(*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 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 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) {
return !compareValues(I1, I2);
}
/// \brief Compare underlying values of two numbers.
static int compareValues(const APSInt &I1, const APSInt &I2) {
if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned())
return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2);
// Check for a bit-width mismatch.
if (I1.getBitWidth() > I2.getBitWidth())
return compareValues(I1, I2.extend(I1.getBitWidth()));
if (I2.getBitWidth() > I1.getBitWidth())
return compareValues(I1.extend(I2.getBitWidth()), I2);
// We have a signedness mismatch. Check for negative values and do an
// unsigned compare if both are positive.
if (I1.isSigned()) {
assert(!I2.isSigned() && "Expected signed mismatch");
if (I1.isNegative())
return -1;
} else {
assert(I2.isSigned() && "Expected signed mismatch");
if (I2.isNegative())
return 1;
}
return I1.compare(I2);
}
static APSInt get(int64_t X) { return APSInt(APInt(64, X), false); }
static APSInt getUnsigned(uint64_t X) { return APSInt(APInt(64, X), 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 bool operator<=(int64_t V1, const APSInt &V2) { return V2 >= V1; }
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 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

View File

@@ -0,0 +1,241 @@
//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ALLOCATORLIST_H
#define LLVM_ADT_ALLOCATORLIST_H
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/simple_ilist.h"
#include "llvm/Support/Allocator.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <iterator>
#include <type_traits>
#include <utility>
namespace llvm {
/// A linked-list with a custom, local allocator.
///
/// Expose a std::list-like interface that owns and uses a custom LLVM-style
/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the
/// implementation details.
///
/// Because this list owns the allocator, calling \a splice() with a different
/// list isn't generally safe. As such, \a splice has been left out of the
/// interface entirely.
template <class T, class AllocatorT> class AllocatorList : AllocatorT {
struct Node : ilist_node<Node> {
Node(Node &&) = delete;
Node(const Node &) = delete;
Node &operator=(Node &&) = delete;
Node &operator=(const Node &) = delete;
Node(T &&V) : V(std::move(V)) {}
Node(const T &V) : V(V) {}
template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {}
T V;
};
using list_type = simple_ilist<Node>;
list_type List;
AllocatorT &getAlloc() { return *this; }
const AllocatorT &getAlloc() const { return *this; }
template <class... ArgTs> Node *create(ArgTs &&... Args) {
return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
}
struct Cloner {
AllocatorList &AL;
Cloner(AllocatorList &AL) : AL(AL) {}
Node *operator()(const Node &N) const { return AL.create(N.V); }
};
struct Disposer {
AllocatorList &AL;
Disposer(AllocatorList &AL) : AL(AL) {}
void operator()(Node *N) const {
N->~Node();
AL.getAlloc().Deallocate(N);
}
};
public:
using value_type = T;
using pointer = T *;
using reference = T &;
using const_pointer = const T *;
using const_reference = const T &;
using size_type = typename list_type::size_type;
using difference_type = typename list_type::difference_type;
private:
template <class ValueT, class IteratorBase>
class IteratorImpl
: public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
IteratorBase,
std::bidirectional_iterator_tag, ValueT> {
template <class OtherValueT, class OtherIteratorBase>
friend class IteratorImpl;
friend AllocatorList;
using base_type =
iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
std::bidirectional_iterator_tag, ValueT>;
public:
using value_type = ValueT;
using pointer = ValueT *;
using reference = ValueT &;
IteratorImpl() = default;
IteratorImpl(const IteratorImpl &) = default;
IteratorImpl &operator=(const IteratorImpl &) = default;
explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
template <class OtherValueT, class OtherIteratorBase>
IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X,
typename std::enable_if<std::is_convertible<
OtherIteratorBase, IteratorBase>::value>::type * = nullptr)
: base_type(X.wrapped()) {}
~IteratorImpl() = default;
reference operator*() const { return base_type::wrapped()->V; }
pointer operator->() const { return &operator*(); }
friend bool operator==(const IteratorImpl &L, const IteratorImpl &R) {
return L.wrapped() == R.wrapped();
}
friend bool operator!=(const IteratorImpl &L, const IteratorImpl &R) {
return !(L == R);
}
};
public:
using iterator = IteratorImpl<T, typename list_type::iterator>;
using reverse_iterator =
IteratorImpl<T, typename list_type::reverse_iterator>;
using const_iterator =
IteratorImpl<const T, typename list_type::const_iterator>;
using const_reverse_iterator =
IteratorImpl<const T, typename list_type::const_reverse_iterator>;
AllocatorList() = default;
AllocatorList(AllocatorList &&X)
: AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
AllocatorList(const AllocatorList &X) {
List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
}
AllocatorList &operator=(AllocatorList &&X) {
clear(); // Dispose of current nodes explicitly.
List = std::move(X.List);
getAlloc() = std::move(X.getAlloc());
return *this;
}
AllocatorList &operator=(const AllocatorList &X) {
List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
return *this;
}
~AllocatorList() { clear(); }
void swap(AllocatorList &RHS) {
List.swap(RHS.List);
std::swap(getAlloc(), RHS.getAlloc());
}
bool empty() { return List.empty(); }
size_t size() { return List.size(); }
iterator begin() { return iterator(List.begin()); }
iterator end() { return iterator(List.end()); }
const_iterator begin() const { return const_iterator(List.begin()); }
const_iterator end() const { return const_iterator(List.end()); }
reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); }
reverse_iterator rend() { return reverse_iterator(List.rend()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(List.rbegin());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(List.rend());
}
T &back() { return List.back().V; }
T &front() { return List.front().V; }
const T &back() const { return List.back().V; }
const T &front() const { return List.front().V; }
template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) {
return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...)));
}
iterator insert(iterator I, T &&V) {
return iterator(List.insert(I.wrapped(), *create(std::move(V))));
}
iterator insert(iterator I, const T &V) {
return iterator(List.insert(I.wrapped(), *create(V)));
}
template <class Iterator>
void insert(iterator I, Iterator First, Iterator Last) {
for (; First != Last; ++First)
List.insert(I.wrapped(), *create(*First));
}
iterator erase(iterator I) {
return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this)));
}
iterator erase(iterator First, iterator Last) {
return iterator(
List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this)));
}
void clear() { List.clearAndDispose(Disposer(*this)); }
void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); }
void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); }
void push_back(T &&V) { insert(end(), std::move(V)); }
void push_front(T &&V) { insert(begin(), std::move(V)); }
void push_back(const T &V) { insert(end(), V); }
void push_front(const T &V) { insert(begin(), V); }
template <class... Ts> void emplace_back(Ts &&... Vs) {
emplace(end(), std::forward<Ts>(Vs)...);
}
template <class... Ts> void emplace_front(Ts &&... Vs) {
emplace(begin(), std::forward<Ts>(Vs)...);
}
/// Reset the underlying allocator.
///
/// \pre \c empty()
void resetAlloc() {
assert(empty() && "Cannot reset allocator if not empty");
getAlloc().Reset();
}
};
template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>;
} // end namespace llvm
#endif // LLVM_ADT_ALLOCATORLIST_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,153 @@
//===-- llvm/ADT/BitmaskEnum.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_BITMASKENUM_H
#define LLVM_ADT_BITMASKENUM_H
#include <cassert>
#include <type_traits>
#include <utility>
#include "llvm/Support/MathExtras.h"
/// LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can
/// perform bitwise operations on it without putting static_cast everywhere.
///
/// \code
/// enum MyEnum {
/// E1 = 1, E2 = 2, E3 = 4, E4 = 8,
/// LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ E4)
/// };
///
/// void Foo() {
/// MyEnum A = (E1 | E2) & E3 ^ ~E4; // Look, ma: No static_cast!
/// }
/// \endcode
///
/// Normally when you do a bitwise operation on an enum value, you get back an
/// instance of the underlying type (e.g. int). But using this macro, bitwise
/// ops on your enum will return you back instances of the enum. This is
/// particularly useful for enums which represent a combination of flags.
///
/// The parameter to LLVM_MARK_AS_BITMASK_ENUM should be the largest individual
/// value in your enum.
///
/// All of the enum's values must be non-negative.
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue) \
LLVM_BITMASK_LARGEST_ENUMERATOR = LargestValue
/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used
/// by LLVM_MARK_AS_BITMASK_ENUM into the current namespace.
///
/// Suppose you have an enum foo::bar::MyEnum. Before using
/// LLVM_MARK_AS_BITMASK_ENUM on MyEnum, you must put
/// LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() somewhere inside namespace foo or
/// namespace foo::bar. This allows the relevant operator overloads to be found
/// by ADL.
///
/// You don't need to use this macro in namespace llvm; it's done at the bottom
/// of this file.
#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() \
using ::llvm::BitmaskEnumDetail::operator~; \
using ::llvm::BitmaskEnumDetail::operator|; \
using ::llvm::BitmaskEnumDetail::operator&; \
using ::llvm::BitmaskEnumDetail::operator^; \
using ::llvm::BitmaskEnumDetail::operator|=; \
using ::llvm::BitmaskEnumDetail::operator&=; \
/* Force a semicolon at the end of this macro. */ \
using ::llvm::BitmaskEnumDetail::operator^=
namespace llvm {
/// Traits class to determine whether an enum has a
/// LLVM_BITMASK_LARGEST_ENUMERATOR enumerator.
template <typename E, typename Enable = void>
struct is_bitmask_enum : std::false_type {};
template <typename E>
struct is_bitmask_enum<
E, typename std::enable_if<sizeof(E::LLVM_BITMASK_LARGEST_ENUMERATOR) >=
0>::type> : std::true_type {};
namespace BitmaskEnumDetail {
/// Get a bitmask with 1s in all places up to the high-order bit of E's largest
/// value.
template <typename E> typename std::underlying_type<E>::type Mask() {
// On overflow, NextPowerOf2 returns zero with the type uint64_t, so
// subtracting 1 gives us the mask with all bits set, like we want.
return NextPowerOf2(static_cast<typename std::underlying_type<E>::type>(
E::LLVM_BITMASK_LARGEST_ENUMERATOR)) -
1;
}
/// Check that Val is in range for E, and return Val cast to E's underlying
/// type.
template <typename E> typename std::underlying_type<E>::type Underlying(E Val) {
auto U = static_cast<typename std::underlying_type<E>::type>(Val);
assert(U >= 0 && "Negative enum values are not allowed.");
assert(U <= Mask<E>() && "Enum value too large (or largest val too small?)");
return U;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator~(E Val) {
return static_cast<E>(~Underlying(Val) & Mask<E>());
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator|(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) | Underlying(RHS));
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator&(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) & Underlying(RHS));
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E operator^(E LHS, E RHS) {
return static_cast<E>(Underlying(LHS) ^ Underlying(RHS));
}
// |=, &=, and ^= return a reference to LHS, to match the behavior of the
// operators on builtin types.
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator|=(E &LHS, E RHS) {
LHS = LHS | RHS;
return LHS;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator&=(E &LHS, E RHS) {
LHS = LHS & RHS;
return LHS;
}
template <typename E,
typename = typename std::enable_if<is_bitmask_enum<E>::value>::type>
E &operator^=(E &LHS, E RHS) {
LHS = LHS ^ RHS;
return LHS;
}
} // namespace BitmaskEnumDetail
// Enable bitmask enums in namespace ::llvm and all nested namespaces.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
} // namespace llvm
#endif

View File

@@ -0,0 +1,163 @@
//===- llvm/ADT/BreadthFirstIterator.h - Breadth 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 a generic breadth
// first graph iterator. This file exposes the following functions/types:
//
// bf_begin/bf_end/bf_iterator
// * Normal breadth-first iteration - visit a graph level-by-level.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_BREADTHFIRSTITERATOR_H
#define LLVM_ADT_BREADTHFIRSTITERATOR_H
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator_range.h"
#include <iterator>
#include <queue>
#include <utility>
namespace llvm {
// bf_iterator_storage - A private class which is used to figure out where to
// store the visited set. We only provide a non-external variant for now.
template <class SetType> class bf_iterator_storage {
public:
SetType Visited;
};
// The visited state for the iteration is a simple set.
template <typename NodeRef, unsigned SmallSize = 8>
using bf_iterator_default_set = SmallPtrSet<NodeRef, SmallSize>;
// Generic Breadth first search iterator.
template <class GraphT,
class SetType =
bf_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
class GT = GraphTraits<GraphT>>
class bf_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public bf_iterator_storage<SetType> {
using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>;
using NodeRef = typename GT::NodeRef;
using ChildItTy = typename GT::ChildIteratorType;
// First element is the node reference, second is the next child to visit.
using QueueElement = std::pair<NodeRef, Optional<ChildItTy>>;
// Visit queue - used to maintain BFS ordering.
// Optional<> because we need markers for levels.
std::queue<Optional<QueueElement>> VisitQueue;
// Current level.
unsigned Level;
private:
inline bf_iterator(NodeRef Node) {
this->Visited.insert(Node);
Level = 0;
// Also, insert a dummy node as marker.
VisitQueue.push(QueueElement(Node, None));
VisitQueue.push(None);
}
inline bf_iterator() = default;
inline void toNext() {
Optional<QueueElement> Head = VisitQueue.front();
QueueElement H = Head.getValue();
NodeRef Node = H.first;
Optional<ChildItTy> &ChildIt = H.second;
if (!ChildIt)
ChildIt.emplace(GT::child_begin(Node));
while (*ChildIt != GT::child_end(Node)) {
NodeRef Next = *(*ChildIt)++;
// Already visited?
if (this->Visited.insert(Next).second)
VisitQueue.push(QueueElement(Next, None));
}
VisitQueue.pop();
// Go to the next element skipping markers if needed.
if (!VisitQueue.empty()) {
Head = VisitQueue.front();
if (Head != None)
return;
Level += 1;
VisitQueue.pop();
// Don't push another marker if this is the last
// element.
if (!VisitQueue.empty())
VisitQueue.push(None);
}
}
public:
using pointer = typename super::pointer;
// Provide static begin and end methods as our public "constructors"
static bf_iterator begin(const GraphT &G) {
return bf_iterator(GT::getEntryNode(G));
}
static bf_iterator end(const GraphT &G) { return bf_iterator(); }
bool operator==(const bf_iterator &RHS) const {
return VisitQueue == RHS.VisitQueue;
}
bool operator!=(const bf_iterator &RHS) const { return !(*this == RHS); }
const NodeRef &operator*() const { return VisitQueue.front()->first; }
// This is a nonstandard operator-> that dereferenfces the pointer an extra
// time so that you can actually call methods on the node, because the
// contained type is a pointer.
NodeRef operator->() const { return **this; }
bf_iterator &operator++() { // Pre-increment
toNext();
return *this;
}
bf_iterator operator++(int) { // Post-increment
bf_iterator ItCopy = *this;
++*this;
return ItCopy;
}
unsigned getLevel() const { return Level; }
};
// Provide global constructors that automatically figure out correct types.
template <class T> bf_iterator<T> bf_begin(const T &G) {
return bf_iterator<T>::begin(G);
}
template <class T> bf_iterator<T> bf_end(const T &G) {
return bf_iterator<T>::end(G);
}
// Provide an accessor method to use them in range-based patterns.
template <class T> iterator_range<bf_iterator<T>> breadth_first(const T &G) {
return make_range(bf_begin(G), bf_end(G));
}
} // end namespace llvm
#endif // LLVM_ADT_BREADTHFIRSTITERATOR_H

View File

@@ -0,0 +1,184 @@
//===- llvm/ADT/CachedHashString.h - Prehashed string/StringRef -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines CachedHashString and CachedHashStringRef. These are owning
// and not-owning string types that store their hash in addition to their string
// data.
//
// Unlike std::string, CachedHashString can be used in DenseSet/DenseMap
// (because, unlike std::string, CachedHashString lets us have empty and
// tombstone values).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_CACHED_HASH_STRING_H
#define LLVM_ADT_CACHED_HASH_STRING_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
/// A container which contains a StringRef plus a precomputed hash.
class CachedHashStringRef {
const char *P;
uint32_t Size;
uint32_t Hash;
public:
// Explicit because hashing a string isn't free.
explicit CachedHashStringRef(StringRef S)
: CachedHashStringRef(S, DenseMapInfo<StringRef>::getHashValue(S)) {}
CachedHashStringRef(StringRef S, uint32_t Hash)
: P(S.data()), Size(S.size()), Hash(Hash) {
assert(S.size() <= std::numeric_limits<uint32_t>::max());
}
StringRef val() const { return StringRef(P, Size); }
uint32_t size() const { return Size; }
uint32_t hash() const { return Hash; }
};
template <> struct DenseMapInfo<CachedHashStringRef> {
static CachedHashStringRef getEmptyKey() {
return CachedHashStringRef(DenseMapInfo<StringRef>::getEmptyKey(), 0);
}
static CachedHashStringRef getTombstoneKey() {
return CachedHashStringRef(DenseMapInfo<StringRef>::getTombstoneKey(), 1);
}
static unsigned getHashValue(const CachedHashStringRef &S) {
assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!");
assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!");
return S.hash();
}
static bool isEqual(const CachedHashStringRef &LHS,
const CachedHashStringRef &RHS) {
return LHS.hash() == RHS.hash() &&
DenseMapInfo<StringRef>::isEqual(LHS.val(), RHS.val());
}
};
/// A container which contains a string, which it owns, plus a precomputed hash.
///
/// We do not null-terminate the string.
class CachedHashString {
friend struct DenseMapInfo<CachedHashString>;
char *P;
uint32_t Size;
uint32_t Hash;
static char *getEmptyKeyPtr() { return DenseMapInfo<char *>::getEmptyKey(); }
static char *getTombstoneKeyPtr() {
return DenseMapInfo<char *>::getTombstoneKey();
}
bool isEmptyOrTombstone() const {
return P == getEmptyKeyPtr() || P == getTombstoneKeyPtr();
}
struct ConstructEmptyOrTombstoneTy {};
CachedHashString(ConstructEmptyOrTombstoneTy, char *EmptyOrTombstonePtr)
: P(EmptyOrTombstonePtr), Size(0), Hash(0) {
assert(isEmptyOrTombstone());
}
// TODO: Use small-string optimization to avoid allocating.
public:
explicit CachedHashString(const char *S) : CachedHashString(StringRef(S)) {}
// Explicit because copying and hashing a string isn't free.
explicit CachedHashString(StringRef S)
: CachedHashString(S, DenseMapInfo<StringRef>::getHashValue(S)) {}
CachedHashString(StringRef S, uint32_t Hash)
: P(new char[S.size()]), Size(S.size()), Hash(Hash) {
memcpy(P, S.data(), S.size());
}
// Ideally this class would not be copyable. But SetVector requires copyable
// keys, and we want this to be usable there.
CachedHashString(const CachedHashString &Other)
: Size(Other.Size), Hash(Other.Hash) {
if (Other.isEmptyOrTombstone()) {
P = Other.P;
} else {
P = new char[Size];
memcpy(P, Other.P, Size);
}
}
CachedHashString &operator=(CachedHashString Other) {
swap(*this, Other);
return *this;
}
CachedHashString(CachedHashString &&Other) noexcept
: P(Other.P), Size(Other.Size), Hash(Other.Hash) {
Other.P = getEmptyKeyPtr();
}
~CachedHashString() {
if (!isEmptyOrTombstone())
delete[] P;
}
StringRef val() const { return StringRef(P, Size); }
uint32_t size() const { return Size; }
uint32_t hash() const { return Hash; }
operator StringRef() const { return val(); }
operator CachedHashStringRef() const {
return CachedHashStringRef(val(), Hash);
}
friend void swap(CachedHashString &LHS, CachedHashString &RHS) {
using std::swap;
swap(LHS.P, RHS.P);
swap(LHS.Size, RHS.Size);
swap(LHS.Hash, RHS.Hash);
}
};
template <> struct DenseMapInfo<CachedHashString> {
static CachedHashString getEmptyKey() {
return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(),
CachedHashString::getEmptyKeyPtr());
}
static CachedHashString getTombstoneKey() {
return CachedHashString(CachedHashString::ConstructEmptyOrTombstoneTy(),
CachedHashString::getTombstoneKeyPtr());
}
static unsigned getHashValue(const CachedHashString &S) {
assert(!isEqual(S, getEmptyKey()) && "Cannot hash the empty key!");
assert(!isEqual(S, getTombstoneKey()) && "Cannot hash the tombstone key!");
return S.hash();
}
static bool isEqual(const CachedHashString &LHS,
const CachedHashString &RHS) {
if (LHS.hash() != RHS.hash())
return false;
if (LHS.P == CachedHashString::getEmptyKeyPtr())
return RHS.P == CachedHashString::getEmptyKeyPtr();
if (LHS.P == CachedHashString::getTombstoneKeyPtr())
return RHS.P == CachedHashString::getTombstoneKeyPtr();
// This is safe because if RHS.P is the empty or tombstone key, it will have
// length 0, so we'll never dereference its pointer.
return LHS.val() == RHS.val();
}
};
} // namespace llvm
#endif

View File

@@ -0,0 +1,79 @@
//===- 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 <utility>
#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:
using change_ty = unsigned;
using edge_ty = std::pair<change_ty, change_ty>;
// FIXME: Use a decent data structure.
using changeset_ty = std::set<change_ty>;
using changesetlist_ty = std::vector<changeset_ty>;
public:
virtual ~DAGDeltaAlgorithm() = default;
/// Run - Minimize the DAG formed by the \p Changes vertices and the
/// \p Dependencies edges by executing \see ExecuteOneTest() on subsets of
/// 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 // LLVM_ADT_DAGDELTAALGORITHM_H

View File

@@ -0,0 +1,93 @@
//===- 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:
using change_ty = unsigned;
// FIXME: Use a decent data structure.
using changeset_ty = std::set<change_ty>;
using changesetlist_ty = std::vector<changeset_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;
DeltaAlgorithm& operator=(const DeltaAlgorithm&) = default;
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 // LLVM_ADT_DELTAALGORITHM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,267 @@
//===- 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/ADT/ArrayRef.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <utility>
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 shorts.
template <> struct DenseMapInfo<unsigned short> {
static inline unsigned short getEmptyKey() { return 0xFFFF; }
static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
static bool isEqual(const unsigned short &LHS, const unsigned short &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 shorts.
template <> struct DenseMapInfo<short> {
static inline short getEmptyKey() { return 0x7FFF; }
static inline short getTombstoneKey() { return -0x7FFF - 1; }
static unsigned getHashValue(const short &Val) { return Val * 37U; }
static bool isEqual(const short &LHS, const short &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>> {
using Pair = std::pair<T, U>;
using FirstInfo = DenseMapInfo<T>;
using SecondInfo = DenseMapInfo<U>;
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);
}
};
// Provide DenseMapInfo for StringRefs.
template <> struct DenseMapInfo<StringRef> {
static inline StringRef getEmptyKey() {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
0);
}
static inline StringRef getTombstoneKey() {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
0);
}
static unsigned getHashValue(StringRef Val) {
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
assert(Val.data() != getTombstoneKey().data() &&
"Cannot hash the tombstone key!");
return (unsigned)(hash_value(Val));
}
static bool isEqual(StringRef LHS, StringRef RHS) {
if (RHS.data() == getEmptyKey().data())
return LHS.data() == getEmptyKey().data();
if (RHS.data() == getTombstoneKey().data())
return LHS.data() == getTombstoneKey().data();
return LHS == RHS;
}
};
// Provide DenseMapInfo for ArrayRefs.
template <typename T> struct DenseMapInfo<ArrayRef<T>> {
static inline ArrayRef<T> getEmptyKey() {
return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
size_t(0));
}
static inline ArrayRef<T> getTombstoneKey() {
return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
size_t(0));
}
static unsigned getHashValue(ArrayRef<T> Val) {
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
assert(Val.data() != getTombstoneKey().data() &&
"Cannot hash the tombstone key!");
return (unsigned)(hash_value(Val));
}
static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
if (RHS.data() == getEmptyKey().data())
return LHS.data() == getEmptyKey().data();
if (RHS.data() == getTombstoneKey().data())
return LHS.data() == getTombstoneKey().data();
return LHS == RHS;
}
};
} // end namespace llvm
#endif // LLVM_ADT_DENSEMAPINFO_H

View File

@@ -0,0 +1,255 @@
//===- 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 and SmallDenseSet classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_DENSESET_H
#define LLVM_ADT_DENSESET_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/type_traits.h"
#include <algorithm>
#include <cstddef>
#include <initializer_list>
#include <iterator>
#include <utility>
namespace llvm {
namespace detail {
struct DenseSetEmpty {};
// Use the empty base class trick so we can create a DenseMap where the buckets
// contain only a single item.
template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
KeyT key;
public:
KeyT &getFirst() { return key; }
const KeyT &getFirst() const { return key; }
DenseSetEmpty &getSecond() { return *this; }
const DenseSetEmpty &getSecond() const { return *this; }
};
/// Base class for DenseSet and DenseSmallSet.
///
/// MapTy should be either
///
/// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
/// detail::DenseSetPair<ValueT>>
///
/// or the equivalent SmallDenseMap type. ValueInfoT must implement the
/// DenseMapInfo "concept".
template <typename ValueT, typename MapTy, typename ValueInfoT>
class DenseSetImpl {
static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
"DenseMap buckets unexpectedly large!");
MapTy TheMap;
template <typename T>
using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
using key_type = ValueT;
using value_type = ValueT;
using size_type = unsigned;
explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
DenseSetImpl(std::initializer_list<ValueT> Elems)
: DenseSetImpl(Elems.size()) {
insert(Elems.begin(), Elems.end());
}
bool empty() const { return TheMap.empty(); }
size_type 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); }
/// Grow the DenseSet so that it can contain at least \p NumEntries items
/// before resizing again.
void reserve(size_t Size) { TheMap.reserve(Size); }
void clear() {
TheMap.clear();
}
/// Return 1 if the specified key is in the set, 0 otherwise.
size_type count(const_arg_type_t<ValueT> V) const {
return TheMap.count(V);
}
bool erase(const ValueT &V) {
return TheMap.erase(V);
}
void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
// Iterators.
class ConstIterator;
class Iterator {
typename MapTy::iterator I;
friend class DenseSetImpl;
friend class ConstIterator;
public:
using difference_type = typename MapTy::iterator::difference_type;
using value_type = ValueT;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;
Iterator() = default;
Iterator(const typename MapTy::iterator &i) : I(i) {}
ValueT &operator*() { return I->getFirst(); }
const ValueT &operator*() const { return I->getFirst(); }
ValueT *operator->() { return &I->getFirst(); }
const ValueT *operator->() const { return &I->getFirst(); }
Iterator& operator++() { ++I; return *this; }
Iterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const ConstIterator& X) const { return I == X.I; }
bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
class ConstIterator {
typename MapTy::const_iterator I;
friend class DenseSet;
friend class Iterator;
public:
using difference_type = typename MapTy::const_iterator::difference_type;
using value_type = ValueT;
using pointer = value_type *;
using reference = value_type &;
using iterator_category = std::forward_iterator_tag;
ConstIterator() = default;
ConstIterator(const Iterator &B) : I(B.I) {}
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
const ValueT &operator*() const { return I->getFirst(); }
const ValueT *operator->() const { return &I->getFirst(); }
ConstIterator& operator++() { ++I; return *this; }
ConstIterator operator++(int) { auto T = *this; ++I; return T; }
bool operator==(const ConstIterator& X) const { return I == X.I; }
bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
using iterator = Iterator;
using const_iterator = ConstIterator;
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_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
const_iterator find(const_arg_type_t<ValueT> V) const {
return ConstIterator(TheMap.find(V));
}
/// Alternative version of find() which allows a different, and possibly less
/// expensive, key type.
/// The DenseMapInfo is responsible for supplying methods
/// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
/// used.
template <class LookupKeyT>
iterator find_as(const LookupKeyT &Val) {
return Iterator(TheMap.find_as(Val));
}
template <class LookupKeyT>
const_iterator find_as(const LookupKeyT &Val) const {
return ConstIterator(TheMap.find_as(Val));
}
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) {
detail::DenseSetEmpty Empty;
return TheMap.try_emplace(V, Empty);
}
std::pair<iterator, bool> insert(ValueT &&V) {
detail::DenseSetEmpty Empty;
return TheMap.try_emplace(std::move(V), Empty);
}
/// Alternative version of insert that uses a different (and possibly less
/// expensive) key type.
template <typename LookupKeyT>
std::pair<iterator, bool> insert_as(const ValueT &V,
const LookupKeyT &LookupKey) {
return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
}
template <typename LookupKeyT>
std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
}
// Range insertion of values.
template<typename InputIt>
void insert(InputIt I, InputIt E) {
for (; I != E; ++I)
insert(*I);
}
};
} // end namespace detail
/// Implements a dense probed hash-table based set.
template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
class DenseSet : public detail::DenseSetImpl<
ValueT, DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
detail::DenseSetPair<ValueT>>,
ValueInfoT> {
using BaseT =
detail::DenseSetImpl<ValueT,
DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
detail::DenseSetPair<ValueT>>,
ValueInfoT>;
public:
using BaseT::BaseT;
};
/// Implements a dense probed hash-table based set with some number of buckets
/// stored inline.
template <typename ValueT, unsigned InlineBuckets = 4,
typename ValueInfoT = DenseMapInfo<ValueT>>
class SmallDenseSet
: public detail::DenseSetImpl<
ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
ValueInfoT, detail::DenseSetPair<ValueT>>,
ValueInfoT> {
using BaseT = detail::DenseSetImpl<
ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
ValueInfoT, detail::DenseSetPair<ValueT>>,
ValueInfoT>;
public:
using BaseT::BaseT;
};
} // end namespace llvm
#endif // LLVM_ADT_DENSESET_H

View File

@@ -0,0 +1,308 @@
//===- 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/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator_range.h"
#include <iterator>
#include <set>
#include <utility>
#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;
};
// The visited stated for the iteration is a simple set augmented with
// one more method, completed, which is invoked when all children of a
// node have been processed. It is intended to distinguish of back and
// cross edges in the spanning tree but is not used in the common case.
template <typename NodeRef, unsigned SmallSize=8>
struct df_iterator_default_set : public SmallPtrSet<NodeRef, SmallSize> {
using BaseSet = SmallPtrSet<NodeRef, SmallSize>;
using iterator = typename BaseSet::iterator;
std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); }
template <typename IterT>
void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); }
void completed(NodeRef) {}
};
// Generic Depth First Iterator
template <class GraphT,
class SetType =
df_iterator_default_set<typename GraphTraits<GraphT>::NodeRef>,
bool ExtStorage = false, class GT = GraphTraits<GraphT>>
class df_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public df_iterator_storage<SetType, ExtStorage> {
using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>;
using NodeRef = typename GT::NodeRef;
using ChildItTy = typename GT::ChildIteratorType;
// First element is node reference, second is the 'next child' to visit.
// The second child is initialized lazily to pick up graph changes during the
// DFS.
using StackElement = std::pair<NodeRef, Optional<ChildItTy>>;
// VisitStack - Used to maintain the ordering. Top = current block
std::vector<StackElement> VisitStack;
private:
inline df_iterator(NodeRef Node) {
this->Visited.insert(Node);
VisitStack.push_back(StackElement(Node, None));
}
inline df_iterator() = default; // End is when stack is empty
inline df_iterator(NodeRef Node, SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
if (this->Visited.insert(Node).second)
VisitStack.push_back(StackElement(Node, None));
}
inline df_iterator(SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
// End is when stack is empty
}
inline void toNext() {
do {
NodeRef Node = VisitStack.back().first;
Optional<ChildItTy> &Opt = VisitStack.back().second;
if (!Opt)
Opt.emplace(GT::child_begin(Node));
// Notice that we directly mutate *Opt here, so that
// VisitStack.back().second actually gets updated as the iterator
// increases.
while (*Opt != GT::child_end(Node)) {
NodeRef Next = *(*Opt)++;
// Has our next sibling been visited?
if (this->Visited.insert(Next).second) {
// No, do it now.
VisitStack.push_back(StackElement(Next, None));
return;
}
}
this->Visited.completed(Node);
// Oops, ran out of successors... go up a level on the stack.
VisitStack.pop_back();
} while (!VisitStack.empty());
}
public:
using pointer = typename super::pointer;
// Provide static begin and end methods as our public "constructors"
static df_iterator begin(const GraphT &G) {
return df_iterator(GT::getEntryNode(G));
}
static df_iterator end(const GraphT &G) { return df_iterator(); }
// Static begin and end methods as our public ctors for external iterators
static df_iterator begin(const GraphT &G, SetType &S) {
return df_iterator(GT::getEntryNode(G), S);
}
static df_iterator end(const GraphT &G, SetType &S) { return df_iterator(S); }
bool operator==(const df_iterator &x) const {
return VisitStack == x.VisitStack;
}
bool operator!=(const df_iterator &x) const { return !(*this == x); }
const NodeRef &operator*() const { return VisitStack.back().first; }
// This is a nonstandard operator-> that dereferences the pointer an extra
// time... so that you can actually call methods ON the Node, because
// the contained type is a pointer. This allows BBIt->getTerminator() f.e.
//
NodeRef operator->() const { return **this; }
df_iterator &operator++() { // Preincrement
toNext();
return *this;
}
/// \brief Skips all children of the current node and traverses to next node
///
/// Note: This function takes care of incrementing the iterator. If you
/// always increment and call this function, you risk walking off the end.
df_iterator &skipChildren() {
VisitStack.pop_back();
if (!VisitStack.empty())
toNext();
return *this;
}
df_iterator operator++(int) { // Postincrement
df_iterator 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.
//
bool nodeVisited(NodeRef 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.
NodeRef getPath(unsigned n) const { return VisitStack[n].first; }
};
// 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 an accessor method to use them in range-based patterns.
template <class T>
iterator_range<df_iterator<T>> depth_first(const T& G) {
return make_range(df_begin(G), df_end(G));
}
// Provide global definitions of external depth first iterators...
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeRef>>
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);
}
template <class T, class SetTy>
iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G,
SetTy &S) {
return make_range(df_ext_begin(G, S), df_ext_end(G, S));
}
// Provide global definitions of inverse depth first iterators...
template <class T,
class SetTy =
df_iterator_default_set<typename GraphTraits<T>::NodeRef>,
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 an accessor method to use them in range-based patterns.
template <class T>
iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) {
return make_range(idf_begin(G), idf_end(G));
}
// Provide global definitions of external inverse depth first iterators...
template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeRef>>
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);
}
template <class T, class SetTy>
iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G,
SetTy &S) {
return make_range(idf_ext_begin(G, S), idf_ext_end(G, S));
}
} // end namespace llvm
#endif // LLVM_ADT_DEPTHFIRSTITERATOR_H

View File

@@ -0,0 +1,100 @@
//===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
// These can be used to write iterators that are fail-fast when LLVM is built
// with asserts enabled.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_EPOCH_TRACKER_H
#define LLVM_ADT_EPOCH_TRACKER_H
#include "llvm/Config/abi-breaking.h"
#include "llvm/Config/llvm-config.h"
#include <cstdint>
namespace llvm {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
/// \brief A base class for data structure classes wishing to make iterators
/// ("handles") pointing into themselves fail-fast. When building without
/// asserts, this class is empty and does nothing.
///
/// DebugEpochBase does not by itself track handles pointing into itself. The
/// expectation is that routines touching the handles will poll on
/// isHandleInSync at appropriate points to assert that the handle they're using
/// is still valid.
///
class DebugEpochBase {
uint64_t Epoch;
public:
DebugEpochBase() : Epoch(0) {}
/// \brief Calling incrementEpoch invalidates all handles pointing into the
/// calling instance.
void incrementEpoch() { ++Epoch; }
/// \brief The destructor calls incrementEpoch to make use-after-free bugs
/// more likely to crash deterministically.
~DebugEpochBase() { incrementEpoch(); }
/// \brief A base class for iterator classes ("handles") that wish to poll for
/// iterator invalidating modifications in the underlying data structure.
/// When LLVM is built without asserts, this class is empty and does nothing.
///
/// HandleBase does not track the parent data structure by itself. It expects
/// the routines modifying the data structure to call incrementEpoch when they
/// make an iterator-invalidating modification.
///
class HandleBase {
const uint64_t *EpochAddress;
uint64_t EpochAtCreation;
public:
HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
explicit HandleBase(const DebugEpochBase *Parent)
: EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
/// \brief Returns true if the DebugEpochBase this Handle is linked to has
/// not called incrementEpoch on itself since the creation of this
/// HandleBase instance.
bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
/// \brief Returns a pointer to the epoch word stored in the data structure
/// this handle points into. Can be used to check if two iterators point
/// into the same data structure.
const void *getEpochAddress() const { return EpochAddress; }
};
};
#else
class DebugEpochBase {
public:
void incrementEpoch() {}
class HandleBase {
public:
HandleBase() = default;
explicit HandleBase(const DebugEpochBase *) {}
bool isHandleInSync() const { return true; }
const void *getEpochAddress() const { return nullptr; }
};
};
#endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
} // namespace llvm
#endif

View File

@@ -0,0 +1,298 @@
//===- 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 <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#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() == nullptr && "Already has a next pointer!");
Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader());
}
public:
ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1),
Data(RHS.Data) {
// Only support copying of singleton nodes.
assert(RHS.isLeader() && RHS.getNext() == nullptr && "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() = default;
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.
using iterator = typename std::set<ECValue>::const_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 : nullptr);
}
member_iterator member_end() const {
return member_iterator(nullptr);
}
/// 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;
}
// isEquivalent - Return true if V1 is equivalent to V2. This can happen if
// V1 is equal to V2 or if they belong to one equivalence class.
bool isEquivalent(const ElemTy &V1, const ElemTy &V2) const {
// Fast path: any element is equivalent to itself.
if (V1 == V2)
return true;
auto It = findLeader(V1);
return It != member_end() && It == findLeader(V2);
}
class member_iterator : public std::iterator<std::forward_iterator_tag,
const ElemTy, ptrdiff_t> {
friend class EquivalenceClasses;
using super = std::iterator<std::forward_iterator_tag,
const ElemTy, ptrdiff_t>;
const ECValue *Node;
public:
using size_type = size_t;
using pointer = typename super::pointer;
using reference = typename super::reference;
explicit member_iterator() = default;
explicit member_iterator(const ECValue *N) : Node(N) {}
reference operator*() const {
assert(Node != nullptr && "Dereferencing end()!");
return Node->getData();
}
pointer operator->() const { return &operator*(); }
member_iterator &operator++() {
assert(Node != nullptr && "++'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 namespace llvm
#endif // LLVM_ADT_EQUIVALENCECLASSES_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
//===- 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
#include "llvm/ADT/iterator_range.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 NodeRef - Type of Node token in the graph, which should
// be cheap to copy.
// typedef ChildIteratorType - Type used to iterate over children in graph,
// dereference to a NodeRef.
// static NodeRef getEntryNode(const GraphType &)
// Return the entry node of the graph
// static ChildIteratorType child_begin(NodeRef)
// static ChildIteratorType child_end (NodeRef)
// Return iterators that point to the beginning and ending of the child
// node list for the specified node.
// typedef ...iterator nodes_iterator; - dereference to a NodeRef
// static nodes_iterator nodes_begin(GraphType *G)
// static nodes_iterator nodes_end (GraphType *G)
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
// 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.
using NodeRef = typename GraphType::UnknownGraphTypeError;
};
// 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>>> : GraphTraits<T> {};
// Provide iterator ranges for the graph traits nodes and children
template <class GraphType>
iterator_range<typename GraphTraits<GraphType>::nodes_iterator>
nodes(const GraphType &G) {
return make_range(GraphTraits<GraphType>::nodes_begin(G),
GraphTraits<GraphType>::nodes_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<Inverse<GraphType>>::nodes_iterator>
inverse_nodes(const GraphType &G) {
return make_range(GraphTraits<Inverse<GraphType>>::nodes_begin(G),
GraphTraits<Inverse<GraphType>>::nodes_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<GraphType>::ChildIteratorType>
children(const typename GraphTraits<GraphType>::NodeRef &G) {
return make_range(GraphTraits<GraphType>::child_begin(G),
GraphTraits<GraphType>::child_end(G));
}
template <class GraphType>
iterator_range<typename GraphTraits<Inverse<GraphType>>::ChildIteratorType>
inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G),
GraphTraits<Inverse<GraphType>>::child_end(G));
}
} // end namespace llvm
#endif // LLVM_ADT_GRAPHTRAITS_H

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More