CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
587 lines
19 KiB
C++
587 lines
19 KiB
C++
//===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_ADT_ARRAYREF_H
|
|
#define LLVM_ADT_ARRAYREF_H
|
|
|
|
#include "llvm/ADT/Hashing.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/xxhash.h"
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <initializer_list>
|
|
#include <iterator>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
template <typename T> class [[nodiscard]] MutableArrayRef;
|
|
|
|
/// 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 LLVM_GSL_POINTER [[nodiscard]] ArrayRef {
|
|
public:
|
|
using value_type = T;
|
|
using pointer = value_type *;
|
|
using const_pointer = const value_type *;
|
|
using reference = value_type &;
|
|
using const_reference = const value_type &;
|
|
using iterator = const_pointer;
|
|
using const_iterator = const_pointer;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
|
|
private:
|
|
/// The start of the array, in an external buffer.
|
|
const T *Data = nullptr;
|
|
|
|
/// The number of elements.
|
|
size_type Length = 0;
|
|
|
|
public:
|
|
/// @name Constructors
|
|
/// @{
|
|
|
|
/// Construct an empty ArrayRef.
|
|
/*implicit*/ ArrayRef() = default;
|
|
|
|
/// Construct an ArrayRef from a single element.
|
|
/*implicit*/ ArrayRef(const T &OneElt LLVM_LIFETIME_BOUND)
|
|
: Data(&OneElt), Length(1) {}
|
|
|
|
/// Construct an ArrayRef from a pointer and length.
|
|
constexpr /*implicit*/ ArrayRef(const T *data LLVM_LIFETIME_BOUND,
|
|
size_t length)
|
|
: Data(data), Length(length) {}
|
|
|
|
/// Construct an ArrayRef from a range.
|
|
constexpr ArrayRef(const T *begin LLVM_LIFETIME_BOUND, const T *end)
|
|
: Data(begin), Length(end - begin) {
|
|
assert(begin <= end);
|
|
}
|
|
|
|
/// Construct an ArrayRef from a type that has a data() method that returns
|
|
/// a pointer convertible to const T *.
|
|
template <
|
|
typename C,
|
|
typename = std::enable_if_t<
|
|
std::conjunction_v<
|
|
std::is_convertible<decltype(std::declval<const C &>().data()) *,
|
|
const T *const *>,
|
|
std::is_integral<decltype(std::declval<const C &>().size())>>,
|
|
void>>
|
|
/*implicit*/ constexpr ArrayRef(const C &V)
|
|
: Data(V.data()), Length(V.size()) {}
|
|
|
|
/// Construct an ArrayRef from a C array.
|
|
template <size_t N>
|
|
/*implicit*/ constexpr ArrayRef(const T (&Arr LLVM_LIFETIME_BOUND)[N])
|
|
: Data(Arr), Length(N) {}
|
|
|
|
/// Construct an ArrayRef from a std::initializer_list.
|
|
#if LLVM_GNUC_PREREQ(9, 0, 0)
|
|
// Disable gcc's warning in this constructor as it generates an enormous amount
|
|
// of messages. Anyone using ArrayRef should already be aware of the fact that
|
|
// it does not do lifetime extension.
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Winit-list-lifetime"
|
|
#endif
|
|
constexpr /*implicit*/ ArrayRef(
|
|
std::initializer_list<T> Vec LLVM_LIFETIME_BOUND)
|
|
: Data(Vec.begin() == Vec.end() ? (T *)nullptr : Vec.begin()),
|
|
Length(Vec.size()) {}
|
|
#if LLVM_GNUC_PREREQ(9, 0, 0)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
/// Construct an ArrayRef<T> from iterator_range<U*>. This uses SFINAE
|
|
/// to ensure that this is only used for iterator ranges over plain pointer
|
|
/// iterators.
|
|
template <typename U, typename = std::enable_if_t<
|
|
std::is_convertible_v<U *const *, T *const *>>>
|
|
ArrayRef(const iterator_range<U *> &Range)
|
|
: Data(Range.begin()), Length(llvm::size(Range)) {}
|
|
|
|
/// @}
|
|
/// @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()); }
|
|
|
|
/// Check if the array is empty.
|
|
bool empty() const { return Length == 0; }
|
|
|
|
const T *data() const { return Data; }
|
|
|
|
/// Get the array size.
|
|
size_t size() const { return Length; }
|
|
|
|
/// Get the first element.
|
|
const T &front() const {
|
|
assert(!empty());
|
|
return Data[0];
|
|
}
|
|
|
|
/// Get the last element.
|
|
const T &back() const {
|
|
assert(!empty());
|
|
return Data[Length - 1];
|
|
}
|
|
|
|
/// consume_front() - Returns the first element and drops it from ArrayRef.
|
|
const T &consume_front() {
|
|
const T &Ret = front();
|
|
*this = drop_front();
|
|
return Ret;
|
|
}
|
|
|
|
/// consume_back() - Returns the last element and drops it from ArrayRef.
|
|
const T &consume_back() {
|
|
const T &Ret = back();
|
|
*this = drop_back();
|
|
return Ret;
|
|
}
|
|
|
|
// copy - Allocate copy in Allocator and return ArrayRef<T> to it.
|
|
template <typename Allocator> MutableArrayRef<T> copy(Allocator &A) {
|
|
T *Buff = A.template Allocate<T>(Length);
|
|
llvm::uninitialized_copy(*this, Buff);
|
|
return MutableArrayRef<T>(Buff, Length);
|
|
}
|
|
|
|
/// Check for element-wise equality.
|
|
bool equals(ArrayRef RHS) const {
|
|
if (Length != RHS.Length)
|
|
return false;
|
|
return std::equal(begin(), end(), RHS.begin());
|
|
}
|
|
|
|
/// slice(n, m) - Chop off the first N elements of the array, and keep M
|
|
/// elements in the array.
|
|
ArrayRef<T> slice(size_t N, size_t M) const {
|
|
assert(N + M <= size() && "Invalid specifier");
|
|
return ArrayRef<T>(data() + N, M);
|
|
}
|
|
|
|
/// slice(n) - Chop off the first N elements of the array.
|
|
ArrayRef<T> slice(size_t N) const { return drop_front(N); }
|
|
|
|
/// Drop the first \p N elements of the array.
|
|
ArrayRef<T> drop_front(size_t N = 1) const {
|
|
assert(size() >= N && "Dropping more elements than exist");
|
|
return slice(N, size() - N);
|
|
}
|
|
|
|
/// Drop the last \p N elements of the array.
|
|
ArrayRef<T> drop_back(size_t N = 1) const {
|
|
assert(size() >= N && "Dropping more elements than exist");
|
|
return slice(0, size() - N);
|
|
}
|
|
|
|
/// Return a copy of *this with the first N elements satisfying the
|
|
/// given predicate removed.
|
|
template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const {
|
|
return ArrayRef<T>(find_if_not(*this, Pred), end());
|
|
}
|
|
|
|
/// Return a copy of *this with the first N elements not satisfying
|
|
/// the given predicate removed.
|
|
template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const {
|
|
return ArrayRef<T>(find_if(*this, Pred), end());
|
|
}
|
|
|
|
/// Return a copy of *this with only the first \p N elements.
|
|
ArrayRef<T> take_front(size_t N = 1) const {
|
|
if (N >= size())
|
|
return *this;
|
|
return drop_back(size() - N);
|
|
}
|
|
|
|
/// Return a copy of *this with only the last \p N elements.
|
|
ArrayRef<T> take_back(size_t N = 1) const {
|
|
if (N >= size())
|
|
return *this;
|
|
return drop_front(size() - N);
|
|
}
|
|
|
|
/// Return the first N elements of this Array that satisfy the given
|
|
/// predicate.
|
|
template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const {
|
|
return ArrayRef<T>(begin(), find_if_not(*this, Pred));
|
|
}
|
|
|
|
/// Return the first N elements of this Array that don't satisfy the
|
|
/// given predicate.
|
|
template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const {
|
|
return ArrayRef<T>(begin(), find_if(*this, Pred));
|
|
}
|
|
|
|
/// @}
|
|
/// @name Operator Overloads
|
|
/// @{
|
|
const T &operator[](size_t Index) const {
|
|
assert(Index < Length && "Invalid index!");
|
|
return Data[Index];
|
|
}
|
|
|
|
/// Disallow accidental assignment from a temporary.
|
|
///
|
|
/// The declaration here is extra complicated so that "arrayRef = {}"
|
|
/// continues to select the move assignment operator.
|
|
template <typename U>
|
|
std::enable_if_t<std::is_same<U, T>::value, ArrayRef<T>> &
|
|
operator=(U &&Temporary) = delete;
|
|
|
|
/// Disallow accidental assignment from a temporary.
|
|
///
|
|
/// The declaration here is extra complicated so that "arrayRef = {}"
|
|
/// continues to select the move assignment operator.
|
|
template <typename U>
|
|
std::enable_if_t<std::is_same<U, T>::value, ArrayRef<T>> &
|
|
operator=(std::initializer_list<U>) = delete;
|
|
|
|
/// @}
|
|
/// @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);
|
|
}
|
|
|
|
/// @}
|
|
};
|
|
|
|
/// 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 [[nodiscard]] MutableArrayRef : public ArrayRef<T> {
|
|
public:
|
|
using value_type = T;
|
|
using pointer = value_type *;
|
|
using const_pointer = const value_type *;
|
|
using reference = value_type &;
|
|
using const_reference = const value_type &;
|
|
using iterator = pointer;
|
|
using const_iterator = const_pointer;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
|
|
/// Construct an empty MutableArrayRef.
|
|
/*implicit*/ MutableArrayRef() = default;
|
|
|
|
/// Construct a MutableArrayRef from a single element.
|
|
/*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
|
|
|
|
/// Construct a MutableArrayRef from a pointer and length.
|
|
/*implicit*/ MutableArrayRef(T *data, size_t length)
|
|
: ArrayRef<T>(data, length) {}
|
|
|
|
/// Construct a MutableArrayRef from a range.
|
|
MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
|
|
|
|
/// Construct a MutableArrayRef from a type that has data() and size(),
|
|
/// where data() returns a pointer convertible to T *const *.
|
|
template <typename C,
|
|
typename = std::enable_if_t<
|
|
std::conjunction_v<
|
|
std::is_convertible<decltype(std::declval<C &>().data()) *,
|
|
T *const *>,
|
|
std::is_integral<decltype(std::declval<C &>().size())>>,
|
|
void>>
|
|
/*implicit*/ constexpr MutableArrayRef(C &&V) : ArrayRef<T>(V) {}
|
|
|
|
/// Construct a MutableArrayRef from a C array.
|
|
template <size_t N>
|
|
/*implicit*/ constexpr 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(); }
|
|
|
|
reverse_iterator rbegin() const { return reverse_iterator(end()); }
|
|
reverse_iterator rend() const { return reverse_iterator(begin()); }
|
|
|
|
/// Get the first element.
|
|
T &front() const {
|
|
assert(!this->empty());
|
|
return data()[0];
|
|
}
|
|
|
|
/// Get the last element.
|
|
T &back() const {
|
|
assert(!this->empty());
|
|
return data()[this->size() - 1];
|
|
}
|
|
|
|
/// Returns the first element and drops it from ArrayRef.
|
|
T &consume_front() {
|
|
T &Ret = front();
|
|
*this = drop_front();
|
|
return Ret;
|
|
}
|
|
|
|
/// Returns the last element and drops it from ArrayRef.
|
|
T &consume_back() {
|
|
T &Ret = back();
|
|
*this = drop_back();
|
|
return Ret;
|
|
}
|
|
|
|
/// Chop off the first \p N elements of the array, and keep \p M elements
|
|
/// in the array.
|
|
MutableArrayRef<T> slice(size_t N, size_t M) const {
|
|
assert(N + M <= this->size() && "Invalid specifier");
|
|
return MutableArrayRef<T>(this->data() + N, M);
|
|
}
|
|
|
|
/// Chop off the first \p N elements of the array.
|
|
MutableArrayRef<T> slice(size_t N) const {
|
|
return slice(N, this->size() - N);
|
|
}
|
|
|
|
/// Drop the first \p N elements of the array.
|
|
MutableArrayRef<T> drop_front(size_t N = 1) const {
|
|
assert(this->size() >= N && "Dropping more elements than exist");
|
|
return slice(N, this->size() - N);
|
|
}
|
|
|
|
MutableArrayRef<T> drop_back(size_t N = 1) const {
|
|
assert(this->size() >= N && "Dropping more elements than exist");
|
|
return slice(0, this->size() - N);
|
|
}
|
|
|
|
/// Return a copy of *this with the first N elements satisfying the
|
|
/// given predicate removed.
|
|
template <class PredicateT>
|
|
MutableArrayRef<T> drop_while(PredicateT Pred) const {
|
|
return MutableArrayRef<T>(find_if_not(*this, Pred), end());
|
|
}
|
|
|
|
/// Return a copy of *this with the first N elements not satisfying
|
|
/// the given predicate removed.
|
|
template <class PredicateT>
|
|
MutableArrayRef<T> drop_until(PredicateT Pred) const {
|
|
return MutableArrayRef<T>(find_if(*this, Pred), end());
|
|
}
|
|
|
|
/// Return a copy of *this with only the first \p N elements.
|
|
MutableArrayRef<T> take_front(size_t N = 1) const {
|
|
if (N >= this->size())
|
|
return *this;
|
|
return drop_back(this->size() - N);
|
|
}
|
|
|
|
/// Return a copy of *this with only the last \p N elements.
|
|
MutableArrayRef<T> take_back(size_t N = 1) const {
|
|
if (N >= this->size())
|
|
return *this;
|
|
return drop_front(this->size() - N);
|
|
}
|
|
|
|
/// Return the first N elements of this Array that satisfy the given
|
|
/// predicate.
|
|
template <class PredicateT>
|
|
MutableArrayRef<T> take_while(PredicateT Pred) const {
|
|
return MutableArrayRef<T>(begin(), find_if_not(*this, Pred));
|
|
}
|
|
|
|
/// Return the first N elements of this Array that don't satisfy the
|
|
/// given predicate.
|
|
template <class PredicateT>
|
|
MutableArrayRef<T> take_until(PredicateT Pred) const {
|
|
return MutableArrayRef<T>(begin(), find_if(*this, Pred));
|
|
}
|
|
|
|
/// @}
|
|
/// @name Operator Overloads
|
|
/// @{
|
|
T &operator[](size_t Index) const {
|
|
assert(Index < this->size() && "Invalid index!");
|
|
return data()[Index];
|
|
}
|
|
};
|
|
|
|
/// @name ArrayRef Deduction guides
|
|
/// @{
|
|
/// Deduction guide to construct an ArrayRef from a single element.
|
|
template <typename T> ArrayRef(const T &OneElt) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a pointer and length
|
|
template <typename T> ArrayRef(const T *data, size_t length) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a range
|
|
template <typename T> ArrayRef(const T *data, const T *end) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a SmallVector
|
|
template <typename T> ArrayRef(const SmallVectorImpl<T> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a SmallVector
|
|
template <typename T, unsigned N>
|
|
ArrayRef(const SmallVector<T, N> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a std::vector
|
|
template <typename T> ArrayRef(const std::vector<T> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a std::array
|
|
template <typename T, std::size_t N>
|
|
ArrayRef(const std::array<T, N> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from an ArrayRef (const)
|
|
template <typename T> ArrayRef(const ArrayRef<T> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from an ArrayRef
|
|
template <typename T> ArrayRef(ArrayRef<T> &Vec) -> ArrayRef<T>;
|
|
|
|
/// Deduction guide to construct an ArrayRef from a C array.
|
|
template <typename T, size_t N> ArrayRef(const T (&Arr)[N]) -> ArrayRef<T>;
|
|
|
|
/// @}
|
|
|
|
/// @name MutableArrayRef Deduction guides
|
|
/// @{
|
|
/// Deduction guide to construct a `MutableArrayRef` from a single element
|
|
template <class T> MutableArrayRef(T &OneElt) -> MutableArrayRef<T>;
|
|
|
|
/// Deduction guide to construct a `MutableArrayRef` from a pointer and
|
|
/// length.
|
|
template <class T>
|
|
MutableArrayRef(T *data, size_t length) -> MutableArrayRef<T>;
|
|
|
|
/// Deduction guide to construct a `MutableArrayRef` from a `SmallVector`.
|
|
template <class T>
|
|
MutableArrayRef(SmallVectorImpl<T> &Vec) -> MutableArrayRef<T>;
|
|
|
|
template <class T, unsigned N>
|
|
MutableArrayRef(SmallVector<T, N> &Vec) -> MutableArrayRef<T>;
|
|
|
|
/// Deduction guide to construct a `MutableArrayRef` from a `std::vector`.
|
|
template <class T> MutableArrayRef(std::vector<T> &Vec) -> MutableArrayRef<T>;
|
|
|
|
/// Deduction guide to construct a `MutableArrayRef` from a `std::array`.
|
|
template <class T, std::size_t N>
|
|
MutableArrayRef(std::array<T, N> &Vec) -> MutableArrayRef<T>;
|
|
|
|
/// Deduction guide to construct a `MutableArrayRef` from a C array.
|
|
template <typename T, size_t N>
|
|
MutableArrayRef(T (&Arr)[N]) -> MutableArrayRef<T>;
|
|
|
|
/// @}
|
|
/// @name ArrayRef Comparison Operators
|
|
/// @{
|
|
|
|
template <typename T> inline bool operator==(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return LHS.equals(RHS);
|
|
}
|
|
|
|
template <typename T>
|
|
[[nodiscard]] inline bool operator==(const SmallVectorImpl<T> &LHS,
|
|
ArrayRef<T> RHS) {
|
|
return ArrayRef<T>(LHS).equals(RHS);
|
|
}
|
|
|
|
template <typename T> inline bool operator!=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return !(LHS == RHS);
|
|
}
|
|
|
|
template <typename T>
|
|
[[nodiscard]] inline bool operator!=(const SmallVectorImpl<T> &LHS,
|
|
ArrayRef<T> RHS) {
|
|
return !(LHS == RHS);
|
|
}
|
|
|
|
template <typename T> inline bool operator<(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(),
|
|
RHS.end());
|
|
}
|
|
|
|
template <typename T> inline bool operator>(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return RHS < LHS;
|
|
}
|
|
|
|
template <typename T> inline bool operator<=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return !(LHS > RHS);
|
|
}
|
|
|
|
template <typename T> inline bool operator>=(ArrayRef<T> LHS, ArrayRef<T> RHS) {
|
|
return !(LHS < RHS);
|
|
}
|
|
|
|
/// @}
|
|
|
|
template <typename T> hash_code hash_value(ArrayRef<T> S) {
|
|
return hash_combine_range(S);
|
|
}
|
|
|
|
/// Inline ArrayRef overloads of the xxhash entry points declared
|
|
/// out-of-line in llvm/Support/xxhash.h. They live here so xxhash.h can stay
|
|
/// free of ADT dependencies.
|
|
inline uint64_t xxh3_64bits(ArrayRef<uint8_t> data) {
|
|
return xxh3_64bits(data.data(), data.size());
|
|
}
|
|
inline XXH128_hash_t xxh3_128bits(ArrayRef<uint8_t> data) {
|
|
return xxh3_128bits(data.data(), data.size());
|
|
}
|
|
|
|
// Provide DenseMapInfo for ArrayRefs.
|
|
template <typename T> struct DenseMapInfo<ArrayRef<T>, void> {
|
|
static inline ArrayRef<T> getEmptyKey() {
|
|
return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
|
|
size_t(0));
|
|
}
|
|
|
|
static unsigned getHashValue(ArrayRef<T> Val) {
|
|
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty 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();
|
|
return LHS == RHS;
|
|
}
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_ADT_ARRAYREF_H
|