mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-02 02:51:42 +00:00
[wpiutil] Upgrade to LLVM 18.1.1 (#6405)
This commit is contained in:
@@ -351,10 +351,10 @@ struct UniquePtrCast : public CastIsPossible<To, From *> {
|
||||
|
||||
static inline CastResultType castFailed() { return CastResultType(nullptr); }
|
||||
|
||||
static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
|
||||
if (!Self::isPossible(f))
|
||||
static inline CastResultType doCastIfPossible(std::unique_ptr<From> &f) {
|
||||
if (!Self::isPossible(f.get()))
|
||||
return castFailed();
|
||||
return doCast(f);
|
||||
return doCast(std::move(f));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -664,10 +664,9 @@ template <typename To, typename From>
|
||||
}
|
||||
|
||||
template <typename To, typename From>
|
||||
[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
|
||||
[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &Val) {
|
||||
assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
|
||||
return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
|
||||
std::forward<std::unique_ptr<From> &&>(Val));
|
||||
return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(Val);
|
||||
}
|
||||
|
||||
/// isa_and_present<X> - Functionally identical to isa, except that a null value
|
||||
|
||||
@@ -32,6 +32,19 @@ namespace sys {
|
||||
template <typename D = std::chrono::nanoseconds>
|
||||
using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;
|
||||
|
||||
// utc_clock and utc_time are only available since C++20. Add enough code to
|
||||
// support formatting date/time in UTC.
|
||||
class UtcClock : public std::chrono::system_clock {};
|
||||
|
||||
template <typename D = std::chrono::nanoseconds>
|
||||
using UtcTime = std::chrono::time_point<UtcClock, D>;
|
||||
|
||||
/// Convert a std::time_t to a UtcTime
|
||||
inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
|
||||
using namespace std::chrono;
|
||||
return UtcTime<seconds>(seconds(T));
|
||||
}
|
||||
|
||||
/// Convert a TimePoint to std::time_t
|
||||
inline std::time_t toTimeT(TimePoint<> TP) {
|
||||
using namespace std::chrono;
|
||||
@@ -39,6 +52,13 @@ inline std::time_t toTimeT(TimePoint<> TP) {
|
||||
time_point_cast<system_clock::time_point::duration>(TP));
|
||||
}
|
||||
|
||||
/// Convert a UtcTime to std::time_t
|
||||
inline std::time_t toTimeT(UtcTime<> TP) {
|
||||
using namespace std::chrono;
|
||||
return system_clock::to_time_t(time_point<system_clock, seconds>(
|
||||
duration_cast<seconds>(TP.time_since_epoch())));
|
||||
}
|
||||
|
||||
/// Convert a std::time_t to a TimePoint
|
||||
inline TimePoint<std::chrono::seconds>
|
||||
toTimePoint(std::time_t T) {
|
||||
@@ -57,6 +77,7 @@ toTimePoint(std::time_t T, uint32_t nsec) {
|
||||
} // namespace sys
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
|
||||
raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);
|
||||
|
||||
} // namespace wpi
|
||||
|
||||
|
||||
@@ -162,6 +162,25 @@
|
||||
#define LLVM_DEPRECATED(MSG, FIX) [[deprecated(MSG)]]
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
#elif defined(_MSC_VER)
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH \
|
||||
_Pragma("warning(push)") \
|
||||
_Pragma("warning(disable : 4996)")
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP \
|
||||
_Pragma("warning(pop)")
|
||||
#else
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH
|
||||
#define LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_POP
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
// Indicate that a non-static, non-const C++ member function reinitializes
|
||||
// the entire object to a known state, independent of the previous state of
|
||||
// the object.
|
||||
@@ -330,6 +349,12 @@
|
||||
#define LLVM_GSL_POINTER
|
||||
#endif
|
||||
|
||||
#if LLVM_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L
|
||||
#define LLVM_CTOR_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define LLVM_CTOR_NODISCARD
|
||||
#endif
|
||||
|
||||
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
|
||||
/// pedantic diagnostics.
|
||||
#ifndef LLVM_EXTENSION
|
||||
@@ -598,4 +623,12 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
|
||||
#define LLVM_NO_PROFILE_INSTRUMENT_FUNCTION
|
||||
#endif
|
||||
|
||||
/// \macro LLVM_PREFERRED_TYPE
|
||||
/// Adjust type of bit-field in debug info.
|
||||
#if __has_attribute(preferred_type)
|
||||
#define LLVM_PREFERRED_TYPE(T) __attribute__((preferred_type(T)))
|
||||
#else
|
||||
#define LLVM_PREFERRED_TYPE(T)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#ifndef WPIUTIL_WPI_ENDIAN_H
|
||||
#define WPIUTIL_WPI_ENDIAN_H
|
||||
|
||||
#include "wpi/bit.h"
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/SwapByteOrder.h"
|
||||
#include <cassert>
|
||||
@@ -24,8 +25,6 @@
|
||||
namespace wpi {
|
||||
namespace support {
|
||||
|
||||
enum endianness {big, little, native};
|
||||
|
||||
// These are named values for common alignments.
|
||||
enum {aligned = 0, unaligned = 1};
|
||||
|
||||
@@ -41,28 +40,24 @@ struct PickAlignment {
|
||||
|
||||
namespace endian {
|
||||
|
||||
constexpr endianness system_endianness() {
|
||||
return sys::IsBigEndianHost ? big : little;
|
||||
}
|
||||
|
||||
template <typename value_type>
|
||||
inline value_type byte_swap(value_type value, endianness endian) {
|
||||
if ((endian != native) && (endian != system_endianness()))
|
||||
[[nodiscard]] inline value_type byte_swap(value_type value, endianness endian) {
|
||||
if (endian != wpi::endianness::native)
|
||||
sys::swapByteOrder(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Swap the bytes of value to match the given endianness.
|
||||
template<typename value_type, endianness endian>
|
||||
inline value_type byte_swap(value_type value) {
|
||||
if constexpr ((endian != native) && (endian != system_endianness()))
|
||||
template <typename value_type, endianness endian>
|
||||
[[nodiscard]] inline value_type byte_swap(value_type value) {
|
||||
if constexpr (endian != wpi::endianness::native)
|
||||
sys::swapByteOrder(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Read a value of a particular endianness from memory.
|
||||
template <typename value_type, std::size_t alignment>
|
||||
inline value_type read(const void *memory, endianness endian) {
|
||||
template <typename value_type, std::size_t alignment = unaligned>
|
||||
[[nodiscard]] inline value_type read(const void *memory, endianness endian) {
|
||||
value_type ret;
|
||||
|
||||
memcpy(&ret,
|
||||
@@ -72,30 +67,29 @@ inline value_type read(const void *memory, endianness endian) {
|
||||
return byte_swap<value_type>(ret, endian);
|
||||
}
|
||||
|
||||
template<typename value_type,
|
||||
endianness endian,
|
||||
std::size_t alignment>
|
||||
inline value_type read(const void *memory) {
|
||||
template <typename value_type, endianness endian, std::size_t alignment>
|
||||
[[nodiscard]] inline value_type read(const void *memory) {
|
||||
return read<value_type, alignment>(memory, endian);
|
||||
}
|
||||
|
||||
/// Read a value of a particular endianness from a buffer, and increment the
|
||||
/// buffer past that value.
|
||||
template <typename value_type, std::size_t alignment, typename CharT>
|
||||
inline value_type readNext(const CharT *&memory, endianness endian) {
|
||||
[[nodiscard]] inline value_type readNext(const CharT *&memory,
|
||||
endianness endian) {
|
||||
value_type ret = read<value_type, alignment>(memory, endian);
|
||||
memory += sizeof(value_type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename value_type, endianness endian, std::size_t alignment,
|
||||
typename CharT>
|
||||
inline value_type readNext(const CharT *&memory) {
|
||||
template <typename value_type, endianness endian, std::size_t alignment,
|
||||
typename CharT>
|
||||
[[nodiscard]] inline value_type readNext(const CharT *&memory) {
|
||||
return readNext<value_type, alignment, CharT>(memory, endian);
|
||||
}
|
||||
|
||||
/// Write a value to memory with a particular endianness.
|
||||
template <typename value_type, std::size_t alignment>
|
||||
template <typename value_type, std::size_t alignment = unaligned>
|
||||
inline void write(void *memory, value_type value, endianness endian) {
|
||||
value = byte_swap<value_type>(value, endian);
|
||||
memcpy(LLVM_ASSUME_ALIGNED(
|
||||
@@ -116,7 +110,8 @@ using make_unsigned_t = std::make_unsigned_t<value_type>;
|
||||
/// Read a value of a particular endianness from memory, for a location
|
||||
/// that starts at the given bit offset within the first byte.
|
||||
template <typename value_type, endianness endian, std::size_t alignment>
|
||||
inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
|
||||
[[nodiscard]] inline value_type readAtBitAlignment(const void *memory,
|
||||
uint64_t startBit) {
|
||||
assert(startBit < 8);
|
||||
if (startBit == 0)
|
||||
return read<value_type, endian, alignment>(memory);
|
||||
@@ -269,125 +264,164 @@ public:
|
||||
} // end namespace detail
|
||||
|
||||
using ulittle16_t =
|
||||
detail::packed_endian_specific_integral<uint16_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
using ulittle32_t =
|
||||
detail::packed_endian_specific_integral<uint32_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
using ulittle64_t =
|
||||
detail::packed_endian_specific_integral<uint64_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
|
||||
using little16_t =
|
||||
detail::packed_endian_specific_integral<int16_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<int16_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
using little32_t =
|
||||
detail::packed_endian_specific_integral<int32_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<int32_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
using little64_t =
|
||||
detail::packed_endian_specific_integral<int64_t, little, unaligned>;
|
||||
detail::packed_endian_specific_integral<int64_t, wpi::endianness::little,
|
||||
unaligned>;
|
||||
|
||||
using aligned_ulittle16_t =
|
||||
detail::packed_endian_specific_integral<uint16_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
using aligned_ulittle32_t =
|
||||
detail::packed_endian_specific_integral<uint32_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
using aligned_ulittle64_t =
|
||||
detail::packed_endian_specific_integral<uint64_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
|
||||
using aligned_little16_t =
|
||||
detail::packed_endian_specific_integral<int16_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<int16_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
using aligned_little32_t =
|
||||
detail::packed_endian_specific_integral<int32_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<int32_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
using aligned_little64_t =
|
||||
detail::packed_endian_specific_integral<int64_t, little, aligned>;
|
||||
detail::packed_endian_specific_integral<int64_t, wpi::endianness::little,
|
||||
aligned>;
|
||||
|
||||
using ubig16_t =
|
||||
detail::packed_endian_specific_integral<uint16_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
using ubig32_t =
|
||||
detail::packed_endian_specific_integral<uint32_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
using ubig64_t =
|
||||
detail::packed_endian_specific_integral<uint64_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
|
||||
using big16_t =
|
||||
detail::packed_endian_specific_integral<int16_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<int16_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
using big32_t =
|
||||
detail::packed_endian_specific_integral<int32_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<int32_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
using big64_t =
|
||||
detail::packed_endian_specific_integral<int64_t, big, unaligned>;
|
||||
detail::packed_endian_specific_integral<int64_t, wpi::endianness::big,
|
||||
unaligned>;
|
||||
|
||||
using aligned_ubig16_t =
|
||||
detail::packed_endian_specific_integral<uint16_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
using aligned_ubig32_t =
|
||||
detail::packed_endian_specific_integral<uint32_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
using aligned_ubig64_t =
|
||||
detail::packed_endian_specific_integral<uint64_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
|
||||
using aligned_big16_t =
|
||||
detail::packed_endian_specific_integral<int16_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<int16_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
using aligned_big32_t =
|
||||
detail::packed_endian_specific_integral<int32_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<int32_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
using aligned_big64_t =
|
||||
detail::packed_endian_specific_integral<int64_t, big, aligned>;
|
||||
detail::packed_endian_specific_integral<int64_t, wpi::endianness::big,
|
||||
aligned>;
|
||||
|
||||
using unaligned_uint16_t =
|
||||
detail::packed_endian_specific_integral<uint16_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint16_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
using unaligned_uint32_t =
|
||||
detail::packed_endian_specific_integral<uint32_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint32_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
using unaligned_uint64_t =
|
||||
detail::packed_endian_specific_integral<uint64_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<uint64_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
|
||||
using unaligned_int16_t =
|
||||
detail::packed_endian_specific_integral<int16_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<int16_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
using unaligned_int32_t =
|
||||
detail::packed_endian_specific_integral<int32_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<int32_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
using unaligned_int64_t =
|
||||
detail::packed_endian_specific_integral<int64_t, native, unaligned>;
|
||||
detail::packed_endian_specific_integral<int64_t, wpi::endianness::native,
|
||||
unaligned>;
|
||||
|
||||
template <typename T>
|
||||
using little_t = detail::packed_endian_specific_integral<T, little, unaligned>;
|
||||
using little_t =
|
||||
detail::packed_endian_specific_integral<T, wpi::endianness::little,
|
||||
unaligned>;
|
||||
template <typename T>
|
||||
using big_t = detail::packed_endian_specific_integral<T, big, unaligned>;
|
||||
using big_t = detail::packed_endian_specific_integral<T, wpi::endianness::big,
|
||||
unaligned>;
|
||||
|
||||
template <typename T>
|
||||
using aligned_little_t =
|
||||
detail::packed_endian_specific_integral<T, little, aligned>;
|
||||
detail::packed_endian_specific_integral<T, wpi::endianness::little,
|
||||
aligned>;
|
||||
template <typename T>
|
||||
using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>;
|
||||
using aligned_big_t =
|
||||
detail::packed_endian_specific_integral<T, wpi::endianness::big, aligned>;
|
||||
|
||||
namespace endian {
|
||||
|
||||
template <typename T> inline T read(const void *P, endianness E) {
|
||||
return read<T, unaligned>(P, E);
|
||||
}
|
||||
|
||||
template <typename T, endianness E> inline T read(const void *P) {
|
||||
template <typename T, endianness E> [[nodiscard]] inline T read(const void *P) {
|
||||
return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
|
||||
}
|
||||
|
||||
inline uint16_t read16(const void *P, endianness E) {
|
||||
[[nodiscard]] inline uint16_t read16(const void *P, endianness E) {
|
||||
return read<uint16_t>(P, E);
|
||||
}
|
||||
inline uint32_t read32(const void *P, endianness E) {
|
||||
[[nodiscard]] inline uint32_t read32(const void *P, endianness E) {
|
||||
return read<uint32_t>(P, E);
|
||||
}
|
||||
inline uint64_t read64(const void *P, endianness E) {
|
||||
[[nodiscard]] inline uint64_t read64(const void *P, endianness E) {
|
||||
return read<uint64_t>(P, E);
|
||||
}
|
||||
|
||||
template <endianness E> inline uint16_t read16(const void *P) {
|
||||
template <endianness E> [[nodiscard]] inline uint16_t read16(const void *P) {
|
||||
return read<uint16_t, E>(P);
|
||||
}
|
||||
template <endianness E> inline uint32_t read32(const void *P) {
|
||||
template <endianness E> [[nodiscard]] inline uint32_t read32(const void *P) {
|
||||
return read<uint32_t, E>(P);
|
||||
}
|
||||
template <endianness E> inline uint64_t read64(const void *P) {
|
||||
template <endianness E> [[nodiscard]] inline uint64_t read64(const void *P) {
|
||||
return read<uint64_t, E>(P);
|
||||
}
|
||||
|
||||
inline uint16_t read16le(const void *P) { return read16<little>(P); }
|
||||
inline uint32_t read32le(const void *P) { return read32<little>(P); }
|
||||
inline uint64_t read64le(const void *P) { return read64<little>(P); }
|
||||
inline uint16_t read16be(const void *P) { return read16<big>(P); }
|
||||
inline uint32_t read32be(const void *P) { return read32<big>(P); }
|
||||
inline uint64_t read64be(const void *P) { return read64<big>(P); }
|
||||
|
||||
template <typename T> inline void write(void *P, T V, endianness E) {
|
||||
write<T, unaligned>(P, V, E);
|
||||
[[nodiscard]] inline uint16_t read16le(const void *P) {
|
||||
return read16<wpi::endianness::little>(P);
|
||||
}
|
||||
[[nodiscard]] inline uint32_t read32le(const void *P) {
|
||||
return read32<wpi::endianness::little>(P);
|
||||
}
|
||||
[[nodiscard]] inline uint64_t read64le(const void *P) {
|
||||
return read64<wpi::endianness::little>(P);
|
||||
}
|
||||
[[nodiscard]] inline uint16_t read16be(const void *P) {
|
||||
return read16<wpi::endianness::big>(P);
|
||||
}
|
||||
[[nodiscard]] inline uint32_t read32be(const void *P) {
|
||||
return read32<wpi::endianness::big>(P);
|
||||
}
|
||||
[[nodiscard]] inline uint64_t read64be(const void *P) {
|
||||
return read64<wpi::endianness::big>(P);
|
||||
}
|
||||
|
||||
template <typename T, endianness E> inline void write(void *P, T V) {
|
||||
@@ -414,12 +448,24 @@ template <endianness E> inline void write64(void *P, uint64_t V) {
|
||||
write<uint64_t, E>(P, V);
|
||||
}
|
||||
|
||||
inline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
|
||||
inline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
|
||||
inline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
|
||||
inline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
|
||||
inline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
|
||||
inline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
|
||||
inline void write16le(void *P, uint16_t V) {
|
||||
write16<wpi::endianness::little>(P, V);
|
||||
}
|
||||
inline void write32le(void *P, uint32_t V) {
|
||||
write32<wpi::endianness::little>(P, V);
|
||||
}
|
||||
inline void write64le(void *P, uint64_t V) {
|
||||
write64<wpi::endianness::little>(P, V);
|
||||
}
|
||||
inline void write16be(void *P, uint16_t V) {
|
||||
write16<wpi::endianness::big>(P, V);
|
||||
}
|
||||
inline void write32be(void *P, uint32_t V) {
|
||||
write32<wpi::endianness::big>(P, V);
|
||||
}
|
||||
inline void write64be(void *P, uint64_t V) {
|
||||
write64<wpi::endianness::big>(P, V);
|
||||
}
|
||||
|
||||
} // end namespace endian
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "wpi/PointerIntPair.h"
|
||||
#include "wpi/PointerUnion.h"
|
||||
#include "wpi/STLForwardCompat.h"
|
||||
#include "wpi/Compiler.h"
|
||||
#include "wpi/MemAlloc.h"
|
||||
#include "wpi/type_traits.h"
|
||||
#include <cstddef>
|
||||
@@ -324,8 +325,10 @@ protected:
|
||||
// Clear the old callback and inline flag to get back to as-if-null.
|
||||
RHS.CallbackAndInlineFlag = {};
|
||||
|
||||
#ifndef NDEBUG
|
||||
// In debug builds, we also scribble across the rest of the storage.
|
||||
#if !defined(NDEBUG) && !LLVM_ADDRESS_SANITIZER_BUILD
|
||||
// In debug builds without ASan, we also scribble across the rest of the
|
||||
// storage. Scribbling under AddressSanitizer (ASan) is disabled to prevent
|
||||
// overwriting poisoned objects (e.g., annotated short strings).
|
||||
memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -682,12 +682,26 @@ template <typename T> hash_code hash_value(const std::optional<T> &arg) {
|
||||
template <> struct DenseMapInfo<hash_code, void> {
|
||||
static inline hash_code getEmptyKey() { return hash_code(-1); }
|
||||
static inline hash_code getTombstoneKey() { return hash_code(-2); }
|
||||
static unsigned getHashValue(hash_code val) { return val; }
|
||||
static unsigned getHashValue(hash_code val) {
|
||||
return static_cast<unsigned>(size_t(val));
|
||||
}
|
||||
static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; }
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
|
||||
/// Implement std::hash so that hash_code can be used in STL containers.
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<wpi::hash_code> {
|
||||
size_t operator()(wpi::hash_code const& Val) const {
|
||||
return Val;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std;
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -114,29 +114,50 @@ public:
|
||||
return Pos == Map.end()? ValueT() : Vector[Pos->second].second;
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
|
||||
std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
|
||||
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
|
||||
auto &I = Result.first->second;
|
||||
if (Result.second) {
|
||||
Vector.push_back(std::make_pair(KV.first, KV.second));
|
||||
I = Vector.size() - 1;
|
||||
template <typename... Ts>
|
||||
std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) {
|
||||
auto [It, Inserted] = Map.insert(std::make_pair(Key, 0));
|
||||
if (Inserted) {
|
||||
It->second = Vector.size();
|
||||
Vector.emplace_back(std::piecewise_construct, std::forward_as_tuple(Key),
|
||||
std::forward_as_tuple(std::forward<Ts>(Args)...));
|
||||
return std::make_pair(std::prev(end()), true);
|
||||
}
|
||||
return std::make_pair(begin() + I, false);
|
||||
return std::make_pair(begin() + It->second, false);
|
||||
}
|
||||
template <typename... Ts>
|
||||
std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) {
|
||||
auto [It, Inserted] = Map.insert(std::make_pair(Key, 0));
|
||||
if (Inserted) {
|
||||
It->second = Vector.size();
|
||||
Vector.emplace_back(std::piecewise_construct,
|
||||
std::forward_as_tuple(std::move(Key)),
|
||||
std::forward_as_tuple(std::forward<Ts>(Args)...));
|
||||
return std::make_pair(std::prev(end()), true);
|
||||
}
|
||||
return std::make_pair(begin() + It->second, false);
|
||||
}
|
||||
|
||||
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
|
||||
return try_emplace(KV.first, KV.second);
|
||||
}
|
||||
std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
|
||||
// Copy KV.first into the map, then move it into the vector.
|
||||
std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
|
||||
std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
|
||||
auto &I = Result.first->second;
|
||||
if (Result.second) {
|
||||
Vector.push_back(std::move(KV));
|
||||
I = Vector.size() - 1;
|
||||
return std::make_pair(std::prev(end()), true);
|
||||
}
|
||||
return std::make_pair(begin() + I, false);
|
||||
return try_emplace(std::move(KV.first), std::move(KV.second));
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) {
|
||||
auto Ret = try_emplace(Key, std::forward<V>(Val));
|
||||
if (!Ret.second)
|
||||
Ret.first->second = std::forward<V>(Val);
|
||||
return Ret;
|
||||
}
|
||||
template <typename V>
|
||||
std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) {
|
||||
auto Ret = try_emplace(std::move(Key), std::forward<V>(Val));
|
||||
if (!Ret.second)
|
||||
Ret.first->second = std::forward<V>(Val);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool contains(const KeyT &Key) const { return Map.find(Key) != Map.end(); }
|
||||
|
||||
@@ -333,9 +333,9 @@ constexpr inline uint64_t NextPowerOf2(uint64_t A) {
|
||||
/// Returns the power of two which is greater than or equal to the given value.
|
||||
/// Essentially, it is a ceil operation across the domain of powers of two.
|
||||
inline uint64_t PowerOf2Ceil(uint64_t A) {
|
||||
if (!A)
|
||||
if (!A || A > UINT64_MAX / 2)
|
||||
return 0;
|
||||
return NextPowerOf2(A - 1);
|
||||
return UINT64_C(1) << Log2_64_Ceil(A);
|
||||
}
|
||||
|
||||
/// Returns the next integer (mod 2**64) that is greater than or equal to
|
||||
|
||||
@@ -72,7 +72,7 @@ LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
|
||||
|
||||
/// Allocate a buffer of memory with the given size and alignment.
|
||||
///
|
||||
/// When the compiler supports aligned operator new, this will use it to to
|
||||
/// When the compiler supports aligned operator new, this will use it to
|
||||
/// handle even over-aligned allocations.
|
||||
///
|
||||
/// However, this doesn't make any attempt to leverage the fancier techniques
|
||||
|
||||
@@ -60,6 +60,13 @@ auto transformOptional(std::optional<T> &&O, const Function &F)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Returns underlying integer value of an enum. Backport of C++23
|
||||
/// std::to_underlying.
|
||||
template <typename Enum>
|
||||
[[nodiscard]] constexpr std::underlying_type_t<Enum> to_underlying(Enum E) {
|
||||
return static_cast<std::underlying_type_t<Enum>>(E);
|
||||
}
|
||||
|
||||
} // namespace wpi
|
||||
|
||||
#endif // WPIUTIL_WPI_STLFORWARDCOMPAT_H
|
||||
|
||||
@@ -88,9 +88,10 @@ public:
|
||||
/// @name String Comparison
|
||||
/// @{
|
||||
|
||||
/// Compare two strings; the result is -1, 0, or 1 if this string is
|
||||
/// lexicographically less than, equal to, or greater than the \p RHS.
|
||||
int compare(std::string_view RHS) const {
|
||||
/// compare - Compare two strings; the result is negative, zero, or positive
|
||||
/// if this string is lexicographically less than, equal to, or greater than
|
||||
/// the \p RHS.
|
||||
[[nodiscard]] int compare(std::string_view RHS) const {
|
||||
return str().compare(RHS);
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ public:
|
||||
///
|
||||
/// \return - The index of the first occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find(char C, size_t From = 0) const {
|
||||
return str().find(C, From);
|
||||
}
|
||||
|
||||
@@ -110,7 +111,7 @@ public:
|
||||
///
|
||||
/// \returns The index of the first occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t find(std::string_view Str, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find(std::string_view Str, size_t From = 0) const {
|
||||
return str().find(Str, From);
|
||||
}
|
||||
|
||||
@@ -118,7 +119,8 @@ public:
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p C, or npos if not
|
||||
/// found.
|
||||
size_t rfind(char C, size_t From = std::string_view::npos) const {
|
||||
[[nodiscard]] size_t rfind(char C,
|
||||
size_t From = std::string_view::npos) const {
|
||||
return str().rfind(C, From);
|
||||
}
|
||||
|
||||
@@ -126,13 +128,13 @@ public:
|
||||
///
|
||||
/// \returns The index of the last occurrence of \p Str, or npos if not
|
||||
/// found.
|
||||
size_t rfind(std::string_view Str) const {
|
||||
[[nodiscard]] size_t rfind(std::string_view Str) const {
|
||||
return str().rfind(Str);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is \p C, or npos if not
|
||||
/// found. Same as find.
|
||||
size_t find_first_of(char C, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find_first_of(char C, size_t From = 0) const {
|
||||
return str().find_first_of(C, From);
|
||||
}
|
||||
|
||||
@@ -140,13 +142,14 @@ public:
|
||||
/// not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_of(std::string_view Chars, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find_first_of(std::string_view Chars,
|
||||
size_t From = 0) const {
|
||||
return str().find_first_of(Chars, From);
|
||||
}
|
||||
|
||||
/// Find the first character in the string that is not \p C or npos if not
|
||||
/// found.
|
||||
size_t find_first_not_of(char C, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find_first_not_of(char C, size_t From = 0) const {
|
||||
return str().find_first_not_of(C, From);
|
||||
}
|
||||
|
||||
@@ -154,13 +157,15 @@ public:
|
||||
/// \p Chars, or npos if not found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_first_not_of(std::string_view Chars, size_t From = 0) const {
|
||||
[[nodiscard]] size_t find_first_not_of(std::string_view Chars,
|
||||
size_t From = 0) const {
|
||||
return str().find_first_not_of(Chars, From);
|
||||
}
|
||||
|
||||
/// Find the last character in the string that is \p C, or npos if not
|
||||
/// found.
|
||||
size_t find_last_of(char C, size_t From = std::string_view::npos) const {
|
||||
[[nodiscard]] size_t find_last_of(
|
||||
char C, size_t From = std::string_view::npos) const {
|
||||
return str().find_last_of(C, From);
|
||||
}
|
||||
|
||||
@@ -168,7 +173,7 @@ public:
|
||||
/// found.
|
||||
///
|
||||
/// Complexity: O(size() + Chars.size())
|
||||
size_t find_last_of(
|
||||
[[nodiscard]] size_t find_last_of(
|
||||
std::string_view Chars, size_t From = std::string_view::npos) const {
|
||||
return str().find_last_of(Chars, From);
|
||||
}
|
||||
@@ -178,7 +183,9 @@ public:
|
||||
// Extra methods.
|
||||
|
||||
/// Explicit conversion to std::string_view.
|
||||
std::string_view str() const { return std::string_view(this->begin(), this->size()); }
|
||||
[[nodiscard]] std::string_view str() const {
|
||||
return std::string_view(this->begin(), this->size());
|
||||
}
|
||||
|
||||
// TODO: Make this const, if it's safe...
|
||||
const char* c_str() {
|
||||
|
||||
@@ -61,7 +61,7 @@ protected:
|
||||
void *BeginX;
|
||||
unsigned Size = 0, Capacity;
|
||||
|
||||
/// The maximum value of the Size_T used.
|
||||
/// The maximum value of the unsigned used.
|
||||
static constexpr size_t SizeTypeMax() {
|
||||
return (std::numeric_limits<unsigned>::max)();
|
||||
}
|
||||
@@ -106,9 +106,19 @@ protected:
|
||||
///
|
||||
/// This does not construct or destroy any elements in the vector.
|
||||
void set_size(size_t N) {
|
||||
assert(N <= capacity());
|
||||
assert(N <= capacity()); // implies no overflow in assignment
|
||||
Size = static_cast<unsigned>(N);
|
||||
}
|
||||
|
||||
/// Set the array data pointer to \p Begin and capacity to \p N.
|
||||
///
|
||||
/// This does not construct or destroy any elements in the vector.
|
||||
// This does not clean up any existing allocation.
|
||||
void set_allocation_range(void *Begin, size_t N) {
|
||||
assert(N <= SizeTypeMax());
|
||||
BeginX = Begin;
|
||||
Capacity = static_cast<unsigned>(N);
|
||||
}
|
||||
};
|
||||
|
||||
/// Figure out the offset of the first element.
|
||||
@@ -469,8 +479,7 @@ void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
|
||||
if (!this->isSmall())
|
||||
free(this->begin());
|
||||
|
||||
this->BeginX = NewElts;
|
||||
this->Capacity = static_cast<unsigned>(NewCapacity);
|
||||
this->set_allocation_range(NewElts, NewCapacity);
|
||||
}
|
||||
|
||||
/// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
|
||||
@@ -603,9 +612,6 @@ protected:
|
||||
RHS.resetToSmall();
|
||||
}
|
||||
|
||||
public:
|
||||
SmallVectorImpl(const SmallVectorImpl &) = delete;
|
||||
|
||||
~SmallVectorImpl() {
|
||||
// Subclass has already destructed this vector's elements.
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
@@ -613,6 +619,9 @@ public:
|
||||
free(this->begin());
|
||||
}
|
||||
|
||||
public:
|
||||
SmallVectorImpl(const SmallVectorImpl &) = delete;
|
||||
|
||||
void clear() {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->Size = 0;
|
||||
|
||||
@@ -14,45 +14,17 @@
|
||||
#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
|
||||
#define WPIUTIL_WPI_SWAPBYTEORDER_H
|
||||
|
||||
#include "wpi/STLForwardCompat.h"
|
||||
#include "wpi/bit.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
|
||||
defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
|
||||
#include <endian.h>
|
||||
#elif defined(_AIX)
|
||||
#include <sys/machine.h>
|
||||
#elif defined(__sun)
|
||||
/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
|
||||
#include <sys/types.h>
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#if defined(_BIG_ENDIAN)
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
#elif defined(__MVS__)
|
||||
#define BIG_ENDIAN 4321
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#define BYTE_ORDER BIG_ENDIAN
|
||||
#else
|
||||
#if !defined(BYTE_ORDER) && !defined(_WIN32)
|
||||
#include <machine/endian.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace wpi {
|
||||
|
||||
namespace sys {
|
||||
|
||||
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
|
||||
constexpr bool IsBigEndianHost = true;
|
||||
#else
|
||||
constexpr bool IsBigEndianHost = false;
|
||||
#endif
|
||||
constexpr bool IsBigEndianHost =
|
||||
wpi::endianness::native == wpi::endianness::big;
|
||||
|
||||
static const bool IsLittleEndianHost = !IsBigEndianHost;
|
||||
|
||||
@@ -73,29 +45,16 @@ inline unsigned long long getSwappedBytes(unsigned long long C) { return wpi::by
|
||||
inline signed long long getSwappedBytes( signed long long C) { return wpi::byteswap(C); }
|
||||
|
||||
inline float getSwappedBytes(float C) {
|
||||
union {
|
||||
uint32_t i;
|
||||
float f;
|
||||
} in, out;
|
||||
in.f = C;
|
||||
out.i = wpi::byteswap(in.i);
|
||||
return out.f;
|
||||
return wpi::bit_cast<float>(wpi::byteswap(wpi::bit_cast<uint32_t>(C)));
|
||||
}
|
||||
|
||||
inline double getSwappedBytes(double C) {
|
||||
union {
|
||||
uint64_t i;
|
||||
double d;
|
||||
} in, out;
|
||||
in.d = C;
|
||||
out.i = wpi::byteswap(in.i);
|
||||
return out.d;
|
||||
return wpi::bit_cast<double>(wpi::byteswap(wpi::bit_cast<uint64_t>(C)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) {
|
||||
return static_cast<T>(
|
||||
wpi::byteswap(static_cast<std::underlying_type_t<T>>(C)));
|
||||
return static_cast<T>(wpi::byteswap(wpi::to_underlying(C)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
#include "wpi/DenseMapInfo.h"
|
||||
#include "wpi/Hashing.h"
|
||||
#include "wpi/Endian.h"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace wpi {
|
||||
template <typename HasherT, support::endianness Endianness>
|
||||
class HashBuilderImpl;
|
||||
template <typename HasherT, wpi::endianness Endianness> class HashBuilder;
|
||||
class raw_ostream;
|
||||
|
||||
/// Represents a version number in the form major[.minor[.subminor[.build]]].
|
||||
|
||||
@@ -29,6 +29,16 @@
|
||||
|
||||
namespace wpi {
|
||||
|
||||
enum class endianness {
|
||||
big,
|
||||
little,
|
||||
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
|
||||
native = big
|
||||
#else
|
||||
native = little
|
||||
#endif
|
||||
};
|
||||
|
||||
// This implementation of bit_cast is different from the C++20 one in two ways:
|
||||
// - It isn't constexpr because that requires compiler support.
|
||||
// - It requires trivially-constructible To, to avoid UB in the implementation.
|
||||
|
||||
@@ -43,8 +43,8 @@ class iterator_range {
|
||||
IteratorT begin_iterator, end_iterator;
|
||||
|
||||
public:
|
||||
#if __GNUC__ == 7
|
||||
// Be careful no to break gcc-7 on the mlir target.
|
||||
#if __GNUC__ == 7 || (__GNUC__ == 8 && __GNUC_MINOR__ < 4)
|
||||
// Be careful no to break gcc-7 and gcc-8 < 8.4 on the mlir target.
|
||||
// See https://github.com/llvm/llvm-project/issues/63843
|
||||
template <typename Container>
|
||||
#else
|
||||
@@ -53,8 +53,7 @@ public:
|
||||
detail::IterOfRange<Container>, IteratorT>::value> * = nullptr>
|
||||
#endif
|
||||
iterator_range(Container &&c)
|
||||
: begin_iterator(adl_begin(std::forward<Container>(c))),
|
||||
end_iterator(adl_end(std::forward<Container>(c))) {
|
||||
: begin_iterator(adl_begin(c)), end_iterator(adl_end(c)) {
|
||||
}
|
||||
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
|
||||
: begin_iterator(std::move(begin_iterator)),
|
||||
|
||||
Reference in New Issue
Block a user