github.com/moontrade/nogc@v0.1.7/sync/Portability.h (about) 1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 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 17 #pragma once 18 19 #include <cstddef> 20 21 #include "CPortability.h" 22 #include "PortabilityConfig.h" 23 24 #if defined(_MSC_VER) 25 #define FOLLY_CPLUSPLUS _MSVC_LANG 26 #else 27 #define FOLLY_CPLUSPLUS __cplusplus 28 #endif 29 30 static_assert(FOLLY_CPLUSPLUS >= 201402L, "__cplusplus >= 201402L"); 31 32 #if defined(__GNUC__) && !defined(__clang__) 33 static_assert(__GNUC__ >= 5, "__GNUC__ >= 5"); 34 #endif 35 36 // Unaligned loads and stores 37 namespace folly { 38 #if FOLLY_HAVE_UNALIGNED_ACCESS 39 constexpr bool kHasUnalignedAccess = true; 40 #else 41 constexpr bool kHasUnalignedAccess = false; 42 #endif 43 } // namespace folly 44 45 // compiler specific attribute translation 46 // msvc should come first, so if clang is in msvc mode it gets the right defines 47 48 // NOTE: this will only do checking in msvc with versions that support /analyze 49 #if _MSC_VER 50 #ifdef _USE_ATTRIBUTES_FOR_SAL 51 #undef _USE_ATTRIBUTES_FOR_SAL 52 #endif 53 /* nolint */ 54 #define _USE_ATTRIBUTES_FOR_SAL 1 55 #include <sal.h> // @manual 56 #define FOLLY_PRINTF_FORMAT _Printf_format_string_ 57 #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/ 58 #else 59 #define FOLLY_PRINTF_FORMAT /**/ 60 #define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \ 61 __attribute__((__format__(__printf__, format_param, dots_param))) 62 #endif 63 64 // warn unused result 65 #if defined(__has_cpp_attribute) 66 #if __has_cpp_attribute(nodiscard) 67 #define FOLLY_NODISCARD [[nodiscard]] 68 #endif 69 #endif 70 #if !defined FOLLY_NODISCARD 71 #if defined(_MSC_VER) && (_MSC_VER >= 1700) 72 #define FOLLY_NODISCARD _Check_return_ 73 #elif defined(__GNUC__) 74 #define FOLLY_NODISCARD __attribute__((__warn_unused_result__)) 75 #else 76 #define FOLLY_NODISCARD 77 #endif 78 #endif 79 80 // target 81 #ifdef _MSC_VER 82 #define FOLLY_TARGET_ATTRIBUTE(target) 83 #else 84 #define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) 85 #endif 86 87 // detection for 64 bit 88 #if defined(__x86_64__) || defined(_M_X64) 89 #define FOLLY_X64 1 90 #else 91 #define FOLLY_X64 0 92 #endif 93 94 #if defined(__arm__) 95 #define FOLLY_ARM 1 96 #else 97 #define FOLLY_ARM 0 98 #endif 99 100 #if defined(__aarch64__) 101 #define FOLLY_AARCH64 1 102 #else 103 #define FOLLY_AARCH64 0 104 #endif 105 106 #if defined(__powerpc64__) 107 #define FOLLY_PPC64 1 108 #else 109 #define FOLLY_PPC64 0 110 #endif 111 112 #if defined(__s390x__) 113 #define FOLLY_S390X 1 114 #else 115 #define FOLLY_S390X 0 116 #endif 117 118 namespace folly { 119 constexpr bool kIsArchArm = FOLLY_ARM == 1; 120 constexpr bool kIsArchAmd64 = FOLLY_X64 == 1; 121 constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1; 122 constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1; 123 constexpr bool kIsArchS390X = FOLLY_S390X == 1; 124 } // namespace folly 125 126 namespace folly { 127 128 /** 129 * folly::kIsLibrarySanitizeAddress reports if folly was compiled with ASAN 130 * enabled. Note that for compilation units outside of folly that include 131 * folly/Portability.h, the value of kIsLibrarySanitizeAddress may be different 132 * from whether or not the current compilation unit is being compiled with ASAN. 133 */ 134 #if FOLLY_LIBRARY_SANITIZE_ADDRESS 135 constexpr bool kIsLibrarySanitizeAddress = true; 136 #else 137 constexpr bool kIsLibrarySanitizeAddress = false; 138 #endif 139 140 #if FOLLY_SANITIZE_ADDRESS 141 constexpr bool kIsSanitizeAddress = true; 142 #else 143 constexpr bool kIsSanitizeAddress = false; 144 #endif 145 146 #if FOLLY_SANITIZE_THREAD 147 constexpr bool kIsSanitizeThread = true; 148 #else 149 constexpr bool kIsSanitizeThread = false; 150 #endif 151 152 #if FOLLY_SANITIZE 153 constexpr bool kIsSanitize = true; 154 #else 155 constexpr bool kIsSanitize = false; 156 #endif 157 } // namespace folly 158 159 // packing is very ugly in msvc 160 #ifdef _MSC_VER 161 #define FOLLY_PACK_ATTR /**/ 162 #define FOLLY_PACK_PUSH __pragma(pack(push, 1)) 163 #define FOLLY_PACK_POP __pragma(pack(pop)) 164 #elif defined(__GNUC__) 165 #define FOLLY_PACK_ATTR __attribute__((__packed__)) 166 #define FOLLY_PACK_PUSH /**/ 167 #define FOLLY_PACK_POP /**/ 168 #else 169 #define FOLLY_PACK_ATTR /**/ 170 #define FOLLY_PACK_PUSH /**/ 171 #define FOLLY_PACK_POP /**/ 172 #endif 173 174 // Generalize warning push/pop. 175 #if defined(__GNUC__) || defined(__clang__) 176 // Clang & GCC 177 #define FOLLY_PUSH_WARNING _Pragma("GCC diagnostic push") 178 #define FOLLY_POP_WARNING _Pragma("GCC diagnostic pop") 179 #define FOLLY_GNU_DISABLE_WARNING_INTERNAL2(warningName) #warningName 180 #define FOLLY_GNU_DISABLE_WARNING(warningName) \ 181 _Pragma( \ 182 FOLLY_GNU_DISABLE_WARNING_INTERNAL2(GCC diagnostic ignored warningName)) 183 #ifdef __clang__ 184 #define FOLLY_CLANG_DISABLE_WARNING(warningName) \ 185 FOLLY_GNU_DISABLE_WARNING(warningName) 186 #define FOLLY_GCC_DISABLE_WARNING(warningName) 187 #else 188 #define FOLLY_CLANG_DISABLE_WARNING(warningName) 189 #define FOLLY_GCC_DISABLE_WARNING(warningName) \ 190 FOLLY_GNU_DISABLE_WARNING(warningName) 191 #endif 192 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) 193 #elif defined(_MSC_VER) 194 #define FOLLY_PUSH_WARNING __pragma(warning(push)) 195 #define FOLLY_POP_WARNING __pragma(warning(pop)) 196 // Disable the GCC warnings. 197 #define FOLLY_GNU_DISABLE_WARNING(warningName) 198 #define FOLLY_GCC_DISABLE_WARNING(warningName) 199 #define FOLLY_CLANG_DISABLE_WARNING(warningName) 200 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) \ 201 __pragma(warning(disable : warningNumber)) 202 #else 203 #define FOLLY_PUSH_WARNING 204 #define FOLLY_POP_WARNING 205 #define FOLLY_GNU_DISABLE_WARNING(warningName) 206 #define FOLLY_GCC_DISABLE_WARNING(warningName) 207 #define FOLLY_CLANG_DISABLE_WARNING(warningName) 208 #define FOLLY_MSVC_DISABLE_WARNING(warningNumber) 209 #endif 210 211 #ifdef FOLLY_HAVE_SHADOW_LOCAL_WARNINGS 212 #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \ 213 FOLLY_GNU_DISABLE_WARNING("-Wshadow-compatible-local") \ 214 FOLLY_GNU_DISABLE_WARNING("-Wshadow-local") \ 215 FOLLY_GNU_DISABLE_WARNING("-Wshadow") 216 #else 217 #define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */ 218 #endif 219 220 // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement 221 // the 'std' namespace; the latter uses inline namespaces. Wrap this decision 222 // up in a macro to make forward-declarations easier. 223 #if FOLLY_USE_LIBCPP 224 #include <__config> // @manual 225 #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD 226 #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD 227 #else 228 #define FOLLY_NAMESPACE_STD_BEGIN namespace std { 229 #define FOLLY_NAMESPACE_STD_END } 230 #endif 231 232 // If the new c++ ABI is used, __cxx11 inline namespace needs to be added to 233 // some types, e.g. std::list. 234 #if _GLIBCXX_USE_CXX11_ABI 235 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN \ 236 inline _GLIBCXX_BEGIN_NAMESPACE_CXX11 237 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END _GLIBCXX_END_NAMESPACE_CXX11 238 #else 239 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN 240 #define FOLLY_GLIBCXX_NAMESPACE_CXX11_END 241 #endif 242 243 // MSVC specific defines 244 // mainly for posix compat 245 #ifdef _MSC_VER 246 #include <folly/portability/SysTypes.h> 247 248 // Hide a GCC specific thing that breaks MSVC if left alone. 249 #define __extension__ 250 251 // We have compiler support for the newest of the new, but 252 // MSVC doesn't tell us that. 253 // 254 // Clang pretends to be MSVC on Windows, but it refuses to compile 255 // SSE4.2 intrinsics unless -march argument is specified. 256 // So cannot unconditionally define __SSE4_2__ in clang. 257 #ifndef __clang__ 258 #if !defined(_M_ARM) && !defined(_M_ARM64) 259 #define __SSE4_2__ 1 260 #endif // !defined(_M_ARM) && !defined(_M_ARM64) 261 262 // compiler specific to compiler specific 263 // nolint 264 #define __PRETTY_FUNCTION__ __FUNCSIG__ 265 #endif 266 267 #endif 268 269 // Define FOLLY_HAS_EXCEPTIONS 270 #if __cpp_exceptions >= 199711 || FOLLY_HAS_FEATURE(cxx_exceptions) 271 #define FOLLY_HAS_EXCEPTIONS 1 272 #elif __GNUC__ 273 #if __EXCEPTIONS 274 #define FOLLY_HAS_EXCEPTIONS 1 275 #else // __EXCEPTIONS 276 #define FOLLY_HAS_EXCEPTIONS 0 277 #endif // __EXCEPTIONS 278 #elif FOLLY_MICROSOFT_ABI_VER 279 #if _CPPUNWIND 280 #define FOLLY_HAS_EXCEPTIONS 1 281 #else // _CPPUNWIND 282 #define FOLLY_HAS_EXCEPTIONS 0 283 #endif // _CPPUNWIND 284 #else 285 #define FOLLY_HAS_EXCEPTIONS 1 // default assumption for unknown platforms 286 #endif 287 288 // Debug 289 namespace folly { 290 #ifdef NDEBUG 291 constexpr auto kIsDebug = false; 292 #else 293 constexpr auto kIsDebug = true; 294 #endif 295 } // namespace folly 296 297 // Exceptions 298 namespace folly { 299 #if FOLLY_HAS_EXCEPTIONS 300 constexpr auto kHasExceptions = true; 301 #else 302 constexpr auto kHasExceptions = false; 303 #endif 304 } // namespace folly 305 306 // Endianness 307 namespace folly { 308 #ifdef _MSC_VER 309 // It's MSVC, so we just have to guess ... and allow an override 310 #ifdef FOLLY_ENDIAN_BE 311 constexpr auto kIsLittleEndian = false; 312 #else 313 constexpr auto kIsLittleEndian = true; 314 #endif 315 #else 316 constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__; 317 #endif 318 constexpr auto kIsBigEndian = !kIsLittleEndian; 319 } // namespace folly 320 321 // Weak 322 namespace folly { 323 #if FOLLY_HAVE_WEAK_SYMBOLS 324 constexpr auto kHasWeakSymbols = true; 325 #else 326 constexpr auto kHasWeakSymbols = false; 327 #endif 328 } // namespace folly 329 330 #ifndef FOLLY_SSE 331 #if defined(__SSE4_2__) 332 #define FOLLY_SSE 4 333 #define FOLLY_SSE_MINOR 2 334 #elif defined(__SSE4_1__) 335 #define FOLLY_SSE 4 336 #define FOLLY_SSE_MINOR 1 337 #elif defined(__SSE4__) 338 #define FOLLY_SSE 4 339 #define FOLLY_SSE_MINOR 0 340 #elif defined(__SSE3__) 341 #define FOLLY_SSE 3 342 #define FOLLY_SSE_MINOR 0 343 #elif defined(__SSE2__) 344 #define FOLLY_SSE 2 345 #define FOLLY_SSE_MINOR 0 346 #elif defined(__SSE__) 347 #define FOLLY_SSE 1 348 #define FOLLY_SSE_MINOR 0 349 #else 350 #define FOLLY_SSE 0 351 #define FOLLY_SSE_MINOR 0 352 #endif 353 #endif 354 355 #ifndef FOLLY_SSSE 356 #if defined(__SSSE3__) 357 #define FOLLY_SSSE 3 358 #else 359 #define FOLLY_SSSE 0 360 #endif 361 #endif 362 363 #define FOLLY_SSE_PREREQ(major, minor) \ 364 (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor) 365 366 #ifndef FOLLY_NEON 367 #if defined(__ARM_NEON) || defined(__ARM_NEON__) 368 #define FOLLY_NEON 1 369 #endif 370 #endif 371 372 #if FOLLY_UNUSUAL_GFLAGS_NAMESPACE 373 namespace FOLLY_GFLAGS_NAMESPACE {} 374 namespace gflags { 375 using namespace FOLLY_GFLAGS_NAMESPACE; 376 } // namespace gflags 377 #endif 378 379 // RTTI may not be enabled for this compilation unit. 380 #if defined(__GXX_RTTI) || defined(__cpp_rtti) || \ 381 (defined(_MSC_VER) && defined(_CPPRTTI)) 382 #define FOLLY_HAS_RTTI 1 383 #else 384 #define FOLLY_HAS_RTTI 0 385 #endif 386 387 namespace folly { 388 constexpr bool const kHasRtti = FOLLY_HAS_RTTI; 389 } // namespace folly 390 391 #if defined(__APPLE__) || defined(_MSC_VER) 392 #define FOLLY_STATIC_CTOR_PRIORITY_MAX 393 #else 394 // 101 is the highest priority allowed by the init_priority attribute. 395 // This priority is already used by JEMalloc and other memory allocators so 396 // we will take the next one. 397 #define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102))) 398 #endif 399 400 #if defined(__APPLE__) && TARGET_OS_IOS 401 #define FOLLY_APPLE_IOS 1 402 #else 403 #define FOLLY_APPLE_IOS 0 404 #endif 405 406 #if defined(__APPLE__) && TARGET_OS_OSX 407 #define FOLLY_APPLE_MACOS 1 408 #else 409 #define FOLLY_APPLE_MACOS 0 410 #endif 411 412 #if defined(__APPLE__) && TARGET_OS_TV 413 #define FOLLY_APPLE_TVOS 1 414 #else 415 #define FOLLY_APPLE_TVOS 0 416 #endif 417 418 #if defined(__APPLE__) && TARGET_OS_WATCH 419 #define FOLLY_APPLE_WATCHOS 1 420 #else 421 #define FOLLY_APPLE_WATCHOS 0 422 #endif 423 424 namespace folly { 425 426 #if __OBJC__ 427 constexpr auto kIsObjC = true; 428 #else 429 constexpr auto kIsObjC = false; 430 #endif 431 432 #if FOLLY_MOBILE 433 constexpr auto kIsMobile = true; 434 #else 435 constexpr auto kIsMobile = false; 436 #endif 437 438 #if defined(__linux__) && !FOLLY_MOBILE 439 constexpr auto kIsLinux = true; 440 #else 441 constexpr auto kIsLinux = false; 442 #endif 443 444 #if defined(_WIN32) 445 constexpr auto kIsWindows = true; 446 #else 447 constexpr auto kIsWindows = false; 448 #endif 449 450 #if defined(__APPLE__) 451 constexpr auto kIsApple = true; 452 #else 453 constexpr auto kIsApple = false; 454 #endif 455 456 constexpr bool kIsAppleIOS = FOLLY_APPLE_IOS == 1; 457 constexpr bool kIsAppleMacOS = FOLLY_APPLE_MACOS == 1; 458 constexpr bool kIsAppleTVOS = FOLLY_APPLE_TVOS == 1; 459 constexpr bool kIsAppleWatchOS = FOLLY_APPLE_WATCHOS == 1; 460 461 #if __GLIBCXX__ 462 constexpr auto kIsGlibcxx = true; 463 #else 464 constexpr auto kIsGlibcxx = false; 465 #endif 466 467 #if __GLIBCXX__ && _GLIBCXX_RELEASE // major version, 7+ 468 constexpr auto kGlibcxxVer = _GLIBCXX_RELEASE; 469 #else 470 constexpr auto kGlibcxxVer = 0; 471 #endif 472 473 #if __GLIBCXX__ && defined(_GLIBCXX_ASSERTIONS) 474 constexpr auto kGlibcxxAssertions = true; 475 #else 476 constexpr auto kGlibcxxAssertions = false; 477 #endif 478 479 #if _LIBCPP_VERSION 480 constexpr auto kIsLibcpp = true; 481 #else 482 constexpr auto kIsLibcpp = false; 483 #endif 484 485 #if FOLLY_USE_LIBSTDCPP 486 constexpr auto kIsLibstdcpp = true; 487 #else 488 constexpr auto kIsLibstdcpp = false; 489 #endif 490 491 #if _MSC_VER 492 constexpr auto kMscVer = _MSC_VER; 493 #else 494 constexpr auto kMscVer = 0; 495 #endif 496 497 #if __GNUC__ 498 constexpr auto kGnuc = __GNUC__; 499 #else 500 constexpr auto kGnuc = 0; 501 #endif 502 503 #if __clang__ 504 constexpr auto kIsClang = true; 505 constexpr auto kClangVerMajor = __clang_major__; 506 #else 507 constexpr auto kIsClang = false; 508 constexpr auto kClangVerMajor = 0; 509 #endif 510 511 #if FOLLY_MICROSOFT_ABI_VER 512 constexpr auto kMicrosoftAbiVer = FOLLY_MICROSOFT_ABI_VER; 513 #else 514 constexpr auto kMicrosoftAbiVer = 0; 515 #endif 516 517 // cpplib is an implementation of the standard library, and is the one typically 518 // used with the msvc compiler 519 #if _CPPLIB_VER 520 constexpr auto kCpplibVer = _CPPLIB_VER; 521 #else 522 constexpr auto kCpplibVer = 0; 523 #endif 524 } // namespace folly 525 526 // MSVC does not permit: 527 // 528 // extern int const num; 529 // constexpr int const num = 3; 530 // 531 // Instead: 532 // 533 // extern int const num; 534 // FOLLY_STORAGE_CONSTEXPR int const num = 3; 535 // 536 // True as of MSVC 2017. 537 #if _MSC_VER 538 #define FOLLY_STORAGE_CONSTEXPR 539 #else 540 #define FOLLY_STORAGE_CONSTEXPR constexpr 541 #endif 542 543 #if __cplusplus >= 201703L 544 // folly::coro requires C++17 support 545 #if defined(_WIN32) && defined(__clang__) && !defined(LLVM_COROUTINES) 546 // LLVM and MSVC coroutines are ABI incompatible, so for the MSVC implementation 547 // of <experimental/coroutine> on Windows we *don't* have coroutines. 548 // 549 // LLVM_COROUTINES indicates that LLVM compatible header is added to include 550 // path and can be used. 551 // 552 // Worse, if we define FOLLY_HAS_COROUTINES 1 we will include 553 // <experimental/coroutine> which will conflict with anyone who wants to load 554 // the LLVM implementation of coroutines on Windows. 555 #define FOLLY_HAS_COROUTINES 0 556 #elif (__cpp_coroutines >= 201703L || __cpp_impl_coroutine >= 201902L) && \ 557 (__has_include(<coroutine>) || __has_include(<experimental/coroutine>)) 558 #define FOLLY_HAS_COROUTINES 1 559 // This is mainly to workaround bugs triggered by LTO, when stack allocated 560 // variables in await_suspend end up on a coroutine frame. 561 #define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE 562 #elif _MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED 563 // NOTE: MSVC 2017 does not currently support the full Coroutines TS since it 564 // does not yet support symmetric-transfer. 565 #define FOLLY_HAS_COROUTINES 0 566 #else 567 #define FOLLY_HAS_COROUTINES 0 568 #endif 569 #else 570 #define FOLLY_HAS_COROUTINES 0 571 #endif // __cplusplus >= 201703L 572 573 // MSVC 2017.5 && C++17 574 #if __cpp_noexcept_function_type >= 201510 || \ 575 (_MSC_FULL_VER >= 191225816 && _MSVC_LANG > 201402) 576 #define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1 577 #endif 578 579 #if __cpp_inline_variables >= 201606L 580 #define FOLLY_HAS_INLINE_VARIABLES 1 581 #define FOLLY_INLINE_VARIABLE inline 582 #else 583 #define FOLLY_HAS_INLINE_VARIABLES 0 584 #define FOLLY_INLINE_VARIABLE 585 #endif 586 587 // feature test __cpp_lib_string_view is defined in <string>, which is 588 // too heavy to include here. 589 #if __has_include(<string_view>) && FOLLY_CPLUSPLUS >= 201703L 590 #define FOLLY_HAS_STRING_VIEW 1 591 #else 592 #define FOLLY_HAS_STRING_VIEW 0 593 #endif