X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FPortability.h;h=6c140379de9e9920755e3eb70cb615c6bd8acb88;hp=7f7a8a1fe6e4defe03fce87bff918f146840c2c9;hb=614eb71734a284e1a9fefabcc48743a3c8efd653;hpb=f9651857d7a364e91ca74d07ad77765caf5fb161 diff --git a/folly/Portability.h b/folly/Portability.h index 7f7a8a1f..6c140379 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,55 +14,105 @@ * limitations under the License. */ -#ifndef FOLLY_PORTABILITY_H_ -#define FOLLY_PORTABILITY_H_ +#pragma once -#ifndef FOLLY_NO_CONFIG -#include -#endif +#include -#ifdef FOLLY_PLATFORM_CONFIG -#include FOLLY_PLATFORM_CONFIG -#endif +#include +#include -#if FOLLY_HAVE_FEATURES_H -#include -#endif +#include #include -#ifdef __APPLE__ -# include -#endif - -#if FOLLY_HAVE_SCHED_H - #include - #ifndef FOLLY_HAVE_PTHREAD_YIELD - #define pthread_yield sched_yield - #endif -#endif - -// A change in folly/MemoryMapping.cpp uses MAP_ANONYMOUS, which is named -// MAP_ANON on OSX/BSD. -#if defined(__APPLE__) || defined(__FreeBSD__) - #include - #ifndef MAP_ANONYMOUS - #ifdef MAP_ANON - #define MAP_ANONYMOUS MAP_ANON - #endif - #endif -#endif +// Unaligned loads and stores +namespace folly { +#if FOLLY_HAVE_UNALIGNED_ACCESS +constexpr bool kHasUnalignedAccess = true; +#else +constexpr bool kHasUnalignedAccess = false; +#endif + +namespace portability_detail { + +template +using integral_max = std::integral_constant; + +template +struct integral_sequence_max + : integral_max::value> {}; + +template +struct integral_sequence_max : std::integral_constant {}; + +template +using max_alignment = integral_sequence_max; + +using max_basic_alignment = max_alignment< + std::max_align_t, + long double, + double, + float, + long long int, + long int, + int, + short int, + bool, + char, + char16_t, + char32_t, + wchar_t, + std::nullptr_t>; +} // namespace portability_detail + +constexpr size_t max_align_v = portability_detail::max_basic_alignment::value; + +// max_align_t is a type which is aligned at least as strictly as the +// most-aligned basic type (see the specification of std::max_align_t). This +// implementation exists because 32-bit iOS platforms have a broken +// std::max_align_t (see below). +// +// You should refer to this as `::folly::max_align_t` in portable code, even if +// you have `using namespace folly;` because C11 defines a global namespace +// `max_align_t` type. +// +// To be certain, we consider every non-void fundamental type specified by the +// standard. On most platforms `long double` would be enough, but iOS 32-bit +// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned +// `long double`. +// +// So far we've covered locals and other non-allocated storage, but we also need +// confidence that allocated storage from `malloc`, `new`, etc will also be +// suitable for objects with this alignment reuirement. +// +// Apple document that their implementation of malloc will issue 16-byte +// granularity chunks for small allocations (large allocations are page-size +// granularity and page-aligned). We think that allocated storage will be +// suitable for these objects based on the following assumptions: +// +// 1. 16-byte granularity also means 16-byte aligned. +// 2. `new` and other allocators follow the `malloc` rules. +// +// We also have some anecdotal evidence: we don't see lots of misaligned-storage +// crashes on 32-bit iOS apps that use `double`. +// +// Apple's allocation reference: http://bit.ly/malloc-small +struct alignas(max_align_v) max_align_t {}; -// MaxAlign: max_align_t isn't supported by gcc -#ifdef __GNUC__ -struct MaxAlign { char c; } __attribute__((__aligned__)); -#else /* !__GNUC__ */ -# error Cannot define MaxAlign on this platform -#endif +} // namespace folly // compiler specific attribute translation // msvc should come first, so if clang is in msvc mode it gets the right defines +#if defined(__clang__) || defined(__GNUC__) +# define FOLLY_ALIGNED(size) __attribute__((__aligned__(size))) +#elif defined(_MSC_VER) +# define FOLLY_ALIGNED(size) __declspec(align(size)) +#else +# error Cannot define FOLLY_ALIGNED on this platform +#endif +#define FOLLY_ALIGNED_MAX FOLLY_ALIGNED(::folly::max_align_v) + // NOTE: this will only do checking in msvc with versions that support /analyze #if _MSC_VER # ifdef _USE_ATTRIBUTES_FOR_SAL @@ -70,7 +120,7 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); # endif /* nolint */ # define _USE_ATTRIBUTES_FOR_SAL 1 -# include +# include // @manual # define FOLLY_PRINTF_FORMAT _Printf_format_string_ # define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/ #else @@ -82,35 +132,33 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); // deprecated #if defined(__clang__) || defined(__GNUC__) # define FOLLY_DEPRECATED(msg) __attribute__((__deprecated__(msg))) +#elif defined(_MSC_VER) +# define FOLLY_DEPRECATED(msg) __declspec(deprecated(msg)) #else -# define FOLLY_DEPRECATED +# define FOLLY_DEPRECATED(msg) #endif -// noreturn -#if defined(_MSC_VER) -# define FOLLY_NORETURN __declspec(noreturn) -#elif defined(__clang__) || defined(__GNUC__) -# define FOLLY_NORETURN __attribute__((__noreturn__)) -#else -# define FOLLY_NORETURN +// warn unused result +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(nodiscard) +#define FOLLY_NODISCARD [[nodiscard]] #endif - -// noinline -#ifdef _MSC_VER -# define FOLLY_NOINLINE __declspec(noinline) +#endif +#if !defined FOLLY_NODISCARD +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +#define FOLLY_NODISCARD _Check_return_ #elif defined(__clang__) || defined(__GNUC__) -# define FOLLY_NOINLINE __attribute__((__noinline__)) +#define FOLLY_NODISCARD __attribute__((__warn_unused_result__)) #else -# define FOLLY_NOINLINE +#define FOLLY_NODISCARD +#endif #endif -// always inline +// target #ifdef _MSC_VER -# define FOLLY_ALWAYS_INLINE __forceinline -#elif defined(__clang__) || defined(__GNUC__) -# define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__)) +# define FOLLY_TARGET_ATTRIBUTE(target) #else -# define FOLLY_ALWAYS_INLINE +# define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) #endif // detection for 64 bit @@ -121,11 +169,44 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); #endif #if defined(__aarch64__) -# define FOLLY_A64 1 +# define FOLLY_AARCH64 1 #else -# define FOLLY_A64 0 +# define FOLLY_AARCH64 0 #endif +#if defined (__powerpc64__) +# define FOLLY_PPC64 1 +#else +# define FOLLY_PPC64 0 +#endif + +namespace folly { +constexpr bool kIsArchAmd64 = FOLLY_X64 == 1; +constexpr bool kIsArchAArch64 = FOLLY_AARCH64 == 1; +constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1; +} // namespace folly + +namespace folly { + +#if FOLLY_SANITIZE_ADDRESS +constexpr bool kIsSanitizeAddress = true; +#else +constexpr bool kIsSanitizeAddress = false; +#endif + +#if FOLLY_SANITIZE_THREAD +constexpr bool kIsSanitizeThread = true; +#else +constexpr bool kIsSanitizeThread = false; +#endif + +#if FOLLY_SANITIZE +constexpr bool kIsSanitize = true; +#else +constexpr bool kIsSanitize = false; +#endif +} // namespace folly + // packing is very ugly in msvc #ifdef _MSC_VER # define FOLLY_PACK_ATTR /**/ @@ -141,32 +222,35 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); # define FOLLY_PACK_POP /**/ #endif -// portable version check -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_MINOR__ -/* nolint */ -# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= \ - ((maj) << 16) + (min)) -# else -/* nolint */ -# define __GNUC_PREREQ(maj, min) 0 -# endif +// Generalize warning push/pop. +#if defined(_MSC_VER) +# define FOLLY_PUSH_WARNING __pragma(warning(push)) +# define FOLLY_POP_WARNING __pragma(warning(pop)) +// Disable the GCC warnings. +# define FOLLY_GCC_DISABLE_WARNING(warningName) +# define FOLLY_MSVC_DISABLE_WARNING(warningNumber) __pragma(warning(disable: warningNumber)) +#elif defined(__clang__) || defined(__GNUC__) +# define FOLLY_PUSH_WARNING _Pragma("GCC diagnostic push") +# define FOLLY_POP_WARNING _Pragma("GCC diagnostic pop") +# define FOLLY_GCC_DISABLE_WARNING_INTERNAL2(warningName) #warningName +# define FOLLY_GCC_DISABLE_WARNING(warningName) \ + _Pragma( \ + FOLLY_GCC_DISABLE_WARNING_INTERNAL2(GCC diagnostic ignored warningName)) +// Disable the MSVC warnings. +# define FOLLY_MSVC_DISABLE_WARNING(warningNumber) +#else +# define FOLLY_PUSH_WARNING +# define FOLLY_POP_WARNING +# define FOLLY_GCC_DISABLE_WARNING(warningName) +# define FOLLY_MSVC_DISABLE_WARNING(warningNumber) #endif - -/* Define macro wrappers for C++11's "final" and "override" keywords, which - * are supported in gcc 4.7 but not gcc 4.6. */ -#if !defined(FOLLY_FINAL) && !defined(FOLLY_OVERRIDE) -# if defined(__clang__) || __GNUC_PREREQ(4, 7) -# define FOLLY_FINAL final -# define FOLLY_OVERRIDE override -# elif defined(_MSC_VER) && _MSC_VER >= 1600 -# define FOLLY_FINAL final -# define FOLLY_OVERRIDE override -# else -# define FOLLY_FINAL /**/ -# define FOLLY_OVERRIDE /**/ -# endif +#ifdef FOLLY_HAVE_SHADOW_LOCAL_WARNINGS +#define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \ + FOLLY_GCC_DISABLE_WARNING("-Wshadow-compatible-local") \ + FOLLY_GCC_DISABLE_WARNING("-Wshadow-local") +#else +#define FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS /* empty */ #endif /* Platform specific TLS support @@ -183,21 +267,15 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); # error cannot define platform specific thread local storage #endif -// Define to 1 if you have the `preadv' and `pwritev' functions, respectively -#if !defined(FOLLY_HAVE_PREADV) && !defined(FOLLY_HAVE_PWRITEV) -# if defined(__GLIBC_PREREQ) -# if __GLIBC_PREREQ(2, 10) -# define FOLLY_HAVE_PREADV 1 -# define FOLLY_HAVE_PWRITEV 1 -# endif -# endif +#if FOLLY_MOBILE +#undef FOLLY_TLS #endif // It turns out that GNU libstdc++ and LLVM libc++ differ on how they implement -// the 'std' namespace; the latter uses inline namepsaces. Wrap this decision +// the 'std' namespace; the latter uses inline namespaces. Wrap this decision // up in a macro to make forward-declarations easier. #if FOLLY_USE_LIBCPP -#include <__config> +#include <__config> // @manual #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD #else @@ -205,58 +283,21 @@ struct MaxAlign { char c; } __attribute__((__aligned__)); #define FOLLY_NAMESPACE_STD_END } #endif -// Some platforms lack clock_gettime(2) and clock_getres(2). Inject our own -// versions of these into the global namespace. -#if FOLLY_HAVE_CLOCK_GETTIME -#include -#else -#include -#endif - -// Provide our own std::__throw_* wrappers for platforms that don't have them -#if FOLLY_HAVE_BITS_FUNCTEXCEPT_H -#include -#else -#include -#endif - -#if defined(__cplusplus) -// Unfortunately, boost::has_trivial_copy is broken in libc++ due to its -// usage of __has_trivial_copy(), so we can't use it as a -// least-common-denominator for C++11 implementations that don't support -// std::is_trivially_copyable. -// -// http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right -// -// As a result, use std::is_trivially_copyable() where it exists, and fall back -// to Boost otherwise. -#if FOLLY_HAVE_STD__IS_TRIVIALLY_COPYABLE -#include -#define FOLLY_IS_TRIVIALLY_COPYABLE(T) \ - (std::is_trivially_copyable::value) +// If the new c++ ABI is used, __cxx11 inline namespace needs to be added to +// some types, e.g. std::list. +#if _GLIBCXX_USE_CXX11_ABI +#define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN \ + inline _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define FOLLY_GLIBCXX_NAMESPACE_CXX11_END _GLIBCXX_END_NAMESPACE_CXX11 #else -#include -#define FOLLY_IS_TRIVIALLY_COPYABLE(T) \ - (boost::has_trivial_copy::value && \ - boost::has_trivial_destructor::value) +# define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN +# define FOLLY_GLIBCXX_NAMESPACE_CXX11_END #endif -#endif // __cplusplus // MSVC specific defines // mainly for posix compat #ifdef _MSC_VER - -// this definition is in a really silly place with a silly name -// and ifdefing it every time we want it is painful -#include -typedef SSIZE_T ssize_t; - -// sprintf semantics are not exactly identical -// but current usage is not a problem -# define snprintf _snprintf - -// semantics here are identical -# define strerror_r(errno,buf,len) strerror_s(buf,len,errno) +#include // compiler specific to compiler specific // nolint @@ -265,47 +306,74 @@ typedef SSIZE_T ssize_t; // Hide a GCC specific thing that breaks MSVC if left alone. # define __extension__ -#ifdef _M_IX86_FP -# define FOLLY_SSE _M_IX86_FP +// We have compiler support for the newest of the new, but +// MSVC doesn't tell us that. +#define __SSE4_2__ 1 + #endif +// Debug +namespace folly { +#ifdef NDEBUG +constexpr auto kIsDebug = false; +#else +constexpr auto kIsDebug = true; #endif +} // namespace folly + +// Endianness +namespace folly { +#ifdef _MSC_VER +// It's MSVC, so we just have to guess ... and allow an override +#ifdef FOLLY_ENDIAN_BE +constexpr auto kIsLittleEndian = false; +#else +constexpr auto kIsLittleEndian = true; +#endif +#else +constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__; +#endif +constexpr auto kIsBigEndian = !kIsLittleEndian; +} // namespace folly #ifndef FOLLY_SSE # if defined(__SSE4_2__) -# define FOLLY_SSE 4.2 +# define FOLLY_SSE 4 +# define FOLLY_SSE_MINOR 2 # elif defined(__SSE4_1__) -# define FOLLY_SSE 4.1 +# define FOLLY_SSE 4 +# define FOLLY_SSE_MINOR 1 # elif defined(__SSE4__) # define FOLLY_SSE 4 +# define FOLLY_SSE_MINOR 0 # elif defined(__SSE3__) # define FOLLY_SSE 3 +# define FOLLY_SSE_MINOR 0 # elif defined(__SSE2__) # define FOLLY_SSE 2 +# define FOLLY_SSE_MINOR 0 # elif defined(__SSE__) # define FOLLY_SSE 1 +# define FOLLY_SSE_MINOR 0 # else # define FOLLY_SSE 0 +# define FOLLY_SSE_MINOR 0 # endif #endif +#define FOLLY_SSE_PREREQ(major, minor) \ + (FOLLY_SSE > major || FOLLY_SSE == major && FOLLY_SSE_MINOR >= minor) + #if FOLLY_UNUSUAL_GFLAGS_NAMESPACE namespace FOLLY_GFLAGS_NAMESPACE { } namespace gflags { using namespace FOLLY_GFLAGS_NAMESPACE; -} // namespace gflags +} // namespace gflags #endif // for TARGET_OS_IPHONE #ifdef __APPLE__ -#include -#endif - -// MacOS doesn't have malloc_usable_size() -#if defined(__APPLE__) && !defined(FOLLY_HAVE_MALLOC_USABLE_SIZE) -inline size_t malloc_usable_size(void* ptr) { - return malloc_size(ptr); -} +#include // @manual #endif // RTTI may not be enabled for this compilation unit. @@ -314,31 +382,61 @@ inline size_t malloc_usable_size(void* ptr) { # define FOLLY_HAS_RTTI 1 #endif -#ifdef _MSC_VER -# include +#if defined(__APPLE__) || defined(_MSC_VER) +#define FOLLY_STATIC_CTOR_PRIORITY_MAX +#else +// 101 is the highest priority allowed by the init_priority attribute. +// This priority is already used by JEMalloc and other memory allocators so +// we will take the next one. +#define FOLLY_STATIC_CTOR_PRIORITY_MAX __attribute__((__init_priority__(102))) #endif namespace folly { -inline void asm_volatile_pause() { -#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) - ::_mm_pause(); -#elif defined(__i386__) || FOLLY_X64 - asm volatile ("pause"); -#elif FOLLY_A64 - asm volatile ("wfe"); +#if __OBJC__ +constexpr auto kIsObjC = true; +#else +constexpr auto kIsObjC = false; #endif -} -inline void asm_pause() { -#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) - ::_mm_pause(); -#elif defined(__i386__) || FOLLY_X64 - asm ("pause"); -#elif FOLLY_A64 - asm ("wfe"); + +#if defined(__linux__) && !FOLLY_MOBILE +constexpr auto kIsLinux = true; +#else +constexpr auto kIsLinux = false; +#endif + +#if defined(_WIN32) +constexpr auto kIsWindows = true; +constexpr auto kMscVer = _MSC_VER; +#else +constexpr auto kIsWindows = false; +constexpr auto kMscVer = 0; +#endif +} // namespace folly + +// Define FOLLY_USE_CPP14_CONSTEXPR to be true if the compiler's C++14 +// constexpr support is "good enough". +#ifndef FOLLY_USE_CPP14_CONSTEXPR +#if defined(__clang__) +#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201300L +#elif defined(__GNUC__) +#define FOLLY_USE_CPP14_CONSTEXPR __cplusplus >= 201304L +#else +#define FOLLY_USE_CPP14_CONSTEXPR 0 // MSVC? +#endif +#endif + +#if FOLLY_USE_CPP14_CONSTEXPR +#define FOLLY_CPP14_CONSTEXPR constexpr +#else +#define FOLLY_CPP14_CONSTEXPR inline #endif -} -} +#if __cpp_coroutines >= 201703L || (_MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED) +#define FOLLY_HAS_COROUTINES 1 +#endif -#endif // FOLLY_PORTABILITY_H_ +// MSVC 2017.5 +#if __cpp_noexcept_function_type >= 201510 || _MSC_FULL_VER >= 191225816 +#define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1 +#endif