X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FPortability.h;h=7b822cda2d60da1fe3849b32f4d7de09554d7ea8;hp=0a8989af3e4c3f002c4461b3ac20b27597a5f9fd;hb=5086391b848c323f58920b349937b9f91f92a6be;hpb=934a0b06a4ce6e85459c84dc2c6a0e61587fc62c diff --git a/folly/Portability.h b/folly/Portability.h index 0a8989af..7b822cda 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 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,102 +14,213 @@ * limitations under the License. */ -#ifndef FOLLY_PORTABILITY_H_ -#define FOLLY_PORTABILITY_H_ +#pragma once -#ifndef FOLLY_NO_CONFIG -#include "folly-config.h" +#include + +#include + +#include + +#include + +// Unaligned loads and stores +namespace folly { +#if FOLLY_HAVE_UNALIGNED_ACCESS +constexpr bool kHasUnalignedAccess = true; +#else +constexpr bool kHasUnalignedAccess = false; #endif +} -#if FOLLY_HAVE_FEATURES_H -#include +// 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(alignof(std::max_align_t)) -#include "CPortability.h" +// NOTE: this will only do checking in msvc with versions that support /analyze +#if _MSC_VER +# ifdef _USE_ATTRIBUTES_FOR_SAL +# undef _USE_ATTRIBUTES_FOR_SAL +# endif +/* nolint */ +# define _USE_ATTRIBUTES_FOR_SAL 1 +# include +# define FOLLY_PRINTF_FORMAT _Printf_format_string_ +# define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/ +#else +# define FOLLY_PRINTF_FORMAT /**/ +# define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \ + __attribute__((__format__(__printf__, format_param, dots_param))) +#endif -#if FOLLY_HAVE_SCHED_H - #include - #ifndef FOLLY_HAVE_PTHREAD_YIELD - #define pthread_yield sched_yield - #endif +// 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(msg) #endif +// warn unused result +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(nodiscard) +#define FOLLY_NODISCARD [[nodiscard]] +#endif +#endif +#if !defined FOLLY_NODISCARD +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +#define FOLLY_NODISCARD _Check_return_ +#elif defined(__clang__) || defined(__GNUC__) +#define FOLLY_NODISCARD __attribute__((__warn_unused_result__)) +#else +#define FOLLY_NODISCARD +#endif +#endif -// 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 +// target +#ifdef _MSC_VER +# define FOLLY_TARGET_ATTRIBUTE(target) +#else +# define FOLLY_TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) #endif -// compiler specific attribute translation -// msvc should come first, so if clang is in msvc mode it gets the right defines +// detection for 64 bit +#if defined(__x86_64__) || defined(_M_X64) +# define FOLLY_X64 1 +#else +# define FOLLY_X64 0 +#endif -// noreturn -#if defined(_MSC_VER) -# define FOLLY_NORETURN __declspec(noreturn) -#elif defined(__clang__) || defined(__GNUC__) -# define FOLLY_NORETURN __attribute__((noreturn)) +#if defined(__aarch64__) +# define FOLLY_A64 1 +#else +# define FOLLY_A64 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_A64 == 1; +constexpr bool kIsArchPPC64 = FOLLY_PPC64 == 1; +} + +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 -# define FOLLY_NORETURN +constexpr bool kIsSanitizeThread = false; #endif +} -// noinline +// packing is very ugly in msvc #ifdef _MSC_VER -# define FOLLY_NOINLINE __declspec(noinline) +# define FOLLY_PACK_ATTR /**/ +# define FOLLY_PACK_PUSH __pragma(pack(push, 1)) +# define FOLLY_PACK_POP __pragma(pack(pop)) #elif defined(__clang__) || defined(__GNUC__) -# define FOLLY_NOINLINE __attribute__((noinline)) +# define FOLLY_PACK_ATTR __attribute__((__packed__)) +# define FOLLY_PACK_PUSH /**/ +# define FOLLY_PACK_POP /**/ #else -# define FOLLY_NOINLINE +# define FOLLY_PACK_ATTR /**/ +# define FOLLY_PACK_PUSH /**/ +# define FOLLY_PACK_POP /**/ #endif -// always inline -#ifdef _MSC_VER -# define FOLLY_ALWAYS_INLINE __forceinline +// 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_ALWAYS_INLINE inline __attribute__((always_inline)) +# 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_ALWAYS_INLINE +# define FOLLY_PUSH_WARNING +# define FOLLY_POP_WARNING +# define FOLLY_GCC_DISABLE_WARNING(warningName) +# define FOLLY_MSVC_DISABLE_WARNING(warningNumber) #endif -// portable version check -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= \ - ((maj) << 16) + (min)) -# else -# define __GNUC_PREREQ(maj, min) 0 -# endif +#ifdef 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 +#if defined(__GNUC__) && !defined(__APPLE__) && !__GNUC_PREREQ(4,9) +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56019 +// gcc 4.8.x incorrectly placed max_align_t in the root namespace +// Alias it into std (where it's found in 4.9 and later) +namespace std { typedef ::max_align_t max_align_t; } +#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 +// portable version check for clang +#ifndef __CLANG_PREREQ +# if defined __clang__ && defined __clang_major__ && defined __clang_minor__ +/* nolint */ +# define __CLANG_PREREQ(maj, min) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) # else -# define FOLLY_FINAL /**/ -# define FOLLY_OVERRIDE /**/ +/* nolint */ +# define __CLANG_PREREQ(maj, min) 0 # endif #endif +/* Platform specific TLS support + * gcc implements __thread + * msvc implements __declspec(thread) + * the semantics are the same + * (but remember __thread has different semantics when using emutls (ex. apple)) + */ +#if defined(_MSC_VER) +# define FOLLY_TLS __declspec(thread) +#elif defined(__GNUC__) || defined(__clang__) +# define FOLLY_TLS __thread +#else +# 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> #define FOLLY_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD #define FOLLY_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD #else @@ -117,41 +228,131 @@ 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 +// 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 "folly/detail/Clock.h" +# define FOLLY_GLIBCXX_NAMESPACE_CXX11_BEGIN +# define FOLLY_GLIBCXX_NAMESPACE_CXX11_END #endif -// Provide our own std::__throw_* wrappers for platforms that don't have them -#if FOLLY_HAVE_BITS_FUNCTEXCEPT_H -#include +// MSVC specific defines +// mainly for posix compat +#ifdef _MSC_VER +#include + +// compiler specific to compiler specific +// nolint +# define __PRETTY_FUNCTION__ __FUNCSIG__ + +// Hide a GCC specific thing that breaks MSVC if left alone. +# define __extension__ + +// 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 -#include "folly/detail/FunctionalExcept.h" +constexpr auto kIsDebug = true; #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) +// 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 -#include -#define FOLLY_IS_TRIVIALLY_COPYABLE(T) \ - (boost::has_trivial_copy::value && \ - boost::has_trivial_destructor::value) +constexpr auto kIsLittleEndian = true; #endif -#endif // __cplusplus +#else +constexpr auto kIsLittleEndian = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__; +#endif +constexpr auto kIsBigEndian = !kIsLittleEndian; +} -#endif // FOLLY_PORTABILITY_H_ +#ifndef FOLLY_SSE +# if defined(__SSE4_2__) +# define FOLLY_SSE 4 +# define FOLLY_SSE_MINOR 2 +# elif defined(__SSE4_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 +#endif + +// for TARGET_OS_IPHONE +#ifdef __APPLE__ +#include +#endif + +// RTTI may not be enabled for this compilation unit. +#if defined(__GXX_RTTI) || defined(__cpp_rtti) || \ + (defined(_MSC_VER) && defined(_CPPRTTI)) +# define FOLLY_HAS_RTTI 1 +#endif + +#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 { + +#if __OBJC__ +constexpr auto kIsObjC = true; +#else +constexpr auto kIsObjC = false; +#endif + +#if defined(__linux__) && !FOLLY_MOBILE +constexpr auto kIsLinux = true; +#else +constexpr auto kIsLinux = false; +#endif + +#if defined(_WIN32) +constexpr auto kIsWindows = true; +#else +constexpr auto kIsWindows = false; +#endif +}