|
9 | 9 | #ifndef LLVM_LIBC_SRC___SUPPORT_RPC_RPC_UTIL_H
|
10 | 10 | #define LLVM_LIBC_SRC___SUPPORT_RPC_RPC_UTIL_H
|
11 | 11 |
|
12 |
| -#include "src/__support/CPP/type_traits.h" |
| 12 | +#include "src/__support/macros/attributes.h" |
13 | 13 | #include "src/__support/macros/config.h"
|
14 |
| -#include "src/__support/threads/sleep.h" |
| 14 | + |
| 15 | +#include <stddef.h> |
| 16 | +#include <stdint.h> |
15 | 17 |
|
16 | 18 | #if defined(__NVPTX__) || defined(__AMDGPU__)
|
17 | 19 | #include <gpuintrin.h>
|
|
21 | 23 | namespace LIBC_NAMESPACE_DECL {
|
22 | 24 | namespace rpc {
|
23 | 25 |
|
| 26 | +template <typename T> struct type_identity { |
| 27 | + using type = T; |
| 28 | +}; |
| 29 | + |
| 30 | +template <class T, T v> struct type_constant { |
| 31 | + static inline constexpr T value = v; |
| 32 | +}; |
| 33 | + |
| 34 | +template <class T> struct remove_reference : type_identity<T> {}; |
| 35 | +template <class T> struct remove_reference<T &> : type_identity<T> {}; |
| 36 | +template <class T> struct remove_reference<T &&> : type_identity<T> {}; |
| 37 | + |
| 38 | +template <class T> struct is_const : type_constant<bool, false> {}; |
| 39 | +template <class T> struct is_const<const T> : type_constant<bool, true> {}; |
| 40 | + |
| 41 | +/// Freestanding implementation of std::move. |
| 42 | +template <class T> |
| 43 | +LIBC_INLINE constexpr typename remove_reference<T>::type &&move(T &&t) { |
| 44 | + return static_cast<typename remove_reference<T>::type &&>(t); |
| 45 | +} |
| 46 | + |
| 47 | +/// Freestanding implementation of std::forward. |
| 48 | +template <typename T> |
| 49 | +LIBC_INLINE constexpr T &&forward(typename remove_reference<T>::type &value) { |
| 50 | + return static_cast<T &&>(value); |
| 51 | +} |
| 52 | +template <typename T> |
| 53 | +LIBC_INLINE constexpr T &&forward(typename remove_reference<T>::type &&value) { |
| 54 | + return static_cast<T &&>(value); |
| 55 | +} |
| 56 | + |
| 57 | +struct in_place_t { |
| 58 | + LIBC_INLINE explicit in_place_t() = default; |
| 59 | +}; |
| 60 | + |
| 61 | +struct nullopt_t { |
| 62 | + LIBC_INLINE constexpr explicit nullopt_t() = default; |
| 63 | +}; |
| 64 | + |
| 65 | +constexpr inline in_place_t in_place{}; |
| 66 | +constexpr inline nullopt_t nullopt{}; |
| 67 | + |
| 68 | +/// Freestanding and minimal implementation of std::optional. |
| 69 | +template <typename T> class optional { |
| 70 | + template <typename U> struct OptionalStorage { |
| 71 | + union { |
| 72 | + char empty; |
| 73 | + U stored_value; |
| 74 | + }; |
| 75 | + |
| 76 | + bool in_use = false; |
| 77 | + |
| 78 | + LIBC_INLINE ~OptionalStorage() { reset(); } |
| 79 | + |
| 80 | + LIBC_INLINE constexpr OptionalStorage() : empty() {} |
| 81 | + |
| 82 | + template <typename... Args> |
| 83 | + LIBC_INLINE constexpr explicit OptionalStorage(in_place_t, Args &&...args) |
| 84 | + : stored_value(forward<Args>(args)...) {} |
| 85 | + |
| 86 | + LIBC_INLINE constexpr void reset() { |
| 87 | + if (in_use) |
| 88 | + stored_value.~U(); |
| 89 | + in_use = false; |
| 90 | + } |
| 91 | + }; |
| 92 | + |
| 93 | + OptionalStorage<T> storage; |
| 94 | + |
| 95 | +public: |
| 96 | + LIBC_INLINE constexpr optional() = default; |
| 97 | + LIBC_INLINE constexpr optional(nullopt_t) {} |
| 98 | + |
| 99 | + LIBC_INLINE constexpr optional(const T &t) : storage(in_place, t) { |
| 100 | + storage.in_use = true; |
| 101 | + } |
| 102 | + LIBC_INLINE constexpr optional(const optional &) = default; |
| 103 | + |
| 104 | + LIBC_INLINE constexpr optional(T &&t) : storage(in_place, move(t)) { |
| 105 | + storage.in_use = true; |
| 106 | + } |
| 107 | + LIBC_INLINE constexpr optional(optional &&O) = default; |
| 108 | + |
| 109 | + LIBC_INLINE constexpr optional &operator=(T &&t) { |
| 110 | + storage = move(t); |
| 111 | + return *this; |
| 112 | + } |
| 113 | + LIBC_INLINE constexpr optional &operator=(optional &&) = default; |
| 114 | + |
| 115 | + LIBC_INLINE constexpr optional &operator=(const T &t) { |
| 116 | + storage = t; |
| 117 | + return *this; |
| 118 | + } |
| 119 | + LIBC_INLINE constexpr optional &operator=(const optional &) = default; |
| 120 | + |
| 121 | + LIBC_INLINE constexpr void reset() { storage.reset(); } |
| 122 | + |
| 123 | + LIBC_INLINE constexpr const T &value() const & { |
| 124 | + return storage.stored_value; |
| 125 | + } |
| 126 | + |
| 127 | + LIBC_INLINE constexpr T &value() & { return storage.stored_value; } |
| 128 | + |
| 129 | + LIBC_INLINE constexpr explicit operator bool() const { |
| 130 | + return storage.in_use; |
| 131 | + } |
| 132 | + LIBC_INLINE constexpr bool has_value() const { return storage.in_use; } |
| 133 | + LIBC_INLINE constexpr const T *operator->() const { |
| 134 | + return &storage.stored_value; |
| 135 | + } |
| 136 | + LIBC_INLINE constexpr T *operator->() { return &storage.stored_value; } |
| 137 | + LIBC_INLINE constexpr const T &operator*() const & { |
| 138 | + return storage.stored_value; |
| 139 | + } |
| 140 | + LIBC_INLINE constexpr T &operator*() & { return storage.stored_value; } |
| 141 | + |
| 142 | + LIBC_INLINE constexpr T &&value() && { return move(storage.stored_value); } |
| 143 | + LIBC_INLINE constexpr T &&operator*() && { |
| 144 | + return move(storage.stored_value); |
| 145 | + } |
| 146 | +}; |
| 147 | + |
| 148 | +/// Suspend the thread briefly to assist the thread scheduler during busy loops. |
| 149 | +LIBC_INLINE void sleep_briefly() { |
| 150 | +#if defined(LIBC_TARGET_ARCH_IS_NVPTX) |
| 151 | + if (__nvvm_reflect("__CUDA_ARCH") >= 700) |
| 152 | + asm("nanosleep.u32 64;" ::: "memory"); |
| 153 | +#elif defined(LIBC_TARGET_ARCH_IS_AMDGPU) |
| 154 | + __builtin_amdgcn_s_sleep(2); |
| 155 | +#elif defined(LIBC_TARGET_ARCH_IS_X86) |
| 156 | + __builtin_ia32_pause(); |
| 157 | +#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) && __has_builtin(__builtin_arm_isb) |
| 158 | + __builtin_arm_isb(0xf); |
| 159 | +#elif defined(LIBC_TARGET_ARCH_IS_AARCH64) |
| 160 | + asm volatile("isb\n" ::: "memory"); |
| 161 | +#else |
| 162 | + // Simply do nothing if sleeping isn't supported on this platform. |
| 163 | +#endif |
| 164 | +} |
| 165 | + |
24 | 166 | /// Conditional to indicate if this process is running on the GPU.
|
25 | 167 | LIBC_INLINE constexpr bool is_process_gpu() {
|
26 | 168 | #ifdef RPC_TARGET_IS_GPU
|
@@ -109,7 +251,7 @@ template <typename V> LIBC_INLINE V &lane_value(V *val, uint32_t id) {
|
109 | 251 |
|
110 | 252 | /// Advance the \p p by \p bytes.
|
111 | 253 | template <typename T, typename U> LIBC_INLINE T *advance(T *ptr, U bytes) {
|
112 |
| - if constexpr (cpp::is_const_v<T>) |
| 254 | + if constexpr (is_const<T>::value) |
113 | 255 | return reinterpret_cast<T *>(reinterpret_cast<const uint8_t *>(ptr) +
|
114 | 256 | bytes);
|
115 | 257 | else
|
|
0 commit comments