1 /* 2 * Copyright (c) 2022 NVIDIA Corporation 3 * 4 * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * https://llvm.org/LICENSE.txt 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #if __cplusplus < 202002L 19 #error This library requires the use of C++20. 20 #endif 21 22 #include <cassert> 23 24 #define STDEXEC_CAT_(_XP, ...) _XP##__VA_ARGS__ 25 #define STDEXEC_CAT(_XP, ...) STDEXEC_CAT_(_XP, __VA_ARGS__) 26 27 #define STDEXEC_EXPAND(...) __VA_ARGS__ 28 #define STDEXEC_EVAL(_MACRO, ...) _MACRO(__VA_ARGS__) 29 30 #define STDEXEC_NOT(_XP) STDEXEC_CAT(STDEXEC_NOT_, _XP) 31 #define STDEXEC_NOT_0 1 32 #define STDEXEC_NOT_1 0 33 34 #define STDEXEC_IIF_0(_YP, ...) __VA_ARGS__ 35 #define STDEXEC_IIF_1(_YP, ...) _YP 36 #define STDEXEC_IIF(_XP, _YP, ...) \ 37 STDEXEC_EVAL(STDEXEC_CAT(STDEXEC_IIF_, _XP), _YP, __VA_ARGS__) 38 39 #define STDEXEC_COUNT(...) \ 40 STDEXEC_EXPAND(STDEXEC_COUNT_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) 41 #define STDEXEC_COUNT_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _NP, ...) _NP 42 43 #define STDEXEC_CHECK(...) STDEXEC_EXPAND(STDEXEC_CHECK_N(__VA_ARGS__, 0, )) 44 #define STDEXEC_CHECK_N(_XP, _NP, ...) _NP 45 #define STDEXEC_PROBE(_XP) _XP, 1, 46 47 #if defined(__NVCOMPILER) 48 #define STDEXEC_NVHPC() 1 49 #elif defined(__clang__) 50 #define STDEXEC_CLANG() 1 51 #elif defined(__GNUC__) 52 #define STDEXEC_GCC() 1 53 #elif defined(_MSC_VER) 54 #define STDEXEC_MSVC() 1 55 #endif 56 57 #ifndef STDEXEC_NVHPC 58 #define STDEXEC_NVHPC() 0 59 #endif 60 #ifndef STDEXEC_CLANG 61 #define STDEXEC_CLANG() 0 62 #endif 63 #ifndef STDEXEC_GCC 64 #define STDEXEC_GCC() 0 65 #endif 66 #ifndef STDEXEC_MSVC 67 #define STDEXEC_MSVC() 0 68 #endif 69 70 #if STDEXEC_CLANG() 71 #define STDEXEC_STRINGIZE(_ARG) #_ARG 72 #define STDEXEC_PRAGMA_PUSH() _Pragma("GCC diagnostic push") 73 #define STDEXEC_PRAGMA_POP() _Pragma("GCC diagnostic pop") 74 #define STDEXEC_PRAGMA_IGNORE(_ARG) \ 75 _Pragma(STDEXEC_STRINGIZE(GCC diagnostic ignored _ARG)) 76 #else 77 #define STDEXEC_PRAGMA_PUSH() 78 #define STDEXEC_PRAGMA_POP() 79 #define STDEXEC_PRAGMA_IGNORE(_ARG) 80 #endif 81 82 #ifdef __has_builtin 83 #define STDEXEC_HAS_BUILTIN __has_builtin 84 #else 85 #define STDEXEC_HAS_BUILTIN(...) 0 86 #endif 87 88 // Before gcc-12, gcc really didn't like tuples or variants of immovable types 89 #if STDEXEC_GCC() && (__GNUC__ < 12) 90 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&) 91 #else 92 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&) = delete 93 #endif 94 95 // NVBUG #4067067 96 #if STDEXEC_NVHPC() 97 #define STDEXEC_NO_UNIQUE_ADDRESS 98 #else 99 #define STDEXEC_NO_UNIQUE_ADDRESS [[no_unique_address]] 100 #endif 101 102 // BUG (gcc PR93711): copy elision fails when initializing a 103 // [[no_unique_address]] field from a function returning an object 104 // of class type by value 105 #if STDEXEC_GCC() 106 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS 107 #else 108 #define STDEXEC_IMMOVABLE_NO_UNIQUE_ADDRESS [[no_unique_address]] 109 #endif 110 111 #if STDEXEC_CLANG() && defined(__CUDACC__) 112 #define STDEXEC_DETAIL_CUDACC_HOST_DEVICE __host__ __device__ 113 #else 114 #define STDEXEC_DETAIL_CUDACC_HOST_DEVICE 115 #endif 116 117 #if STDEXEC_NVHPC() 118 #include <nv/target> 119 #define STDEXEC_TERMINATE() \ 120 NV_IF_TARGET(NV_IS_HOST, (std::terminate();), (__trap();)) void() 121 #elif STDEXEC_CLANG() && defined(__CUDACC__) && defined(__CUDA_ARCH__) 122 #define STDEXEC_TERMINATE() \ 123 __trap(); \ 124 __builtin_unreachable() 125 #else 126 #define STDEXEC_TERMINATE() std::terminate() 127 #endif 128 129 #ifdef STDEXEC_ASSERT 130 #error \ 131 "Redefinition of STDEXEC_ASSERT is not permitted. Define STDEXEC_ASSERT_FN instead." 132 #endif 133 134 #define STDEXEC_ASSERT(_XP) \ 135 do \ 136 { \ 137 static_assert(noexcept(_XP)); \ 138 STDEXEC_ASSERT_FN(_XP); \ 139 } while (false) 140 141 #ifndef STDEXEC_ASSERT_FN 142 #define STDEXEC_ASSERT_FN assert 143 #endif 144 145 namespace stdexec 146 {} 147