// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_BASE_MACROS_H_ #define V8_BASE_MACROS_H_ #include <limits> #include <type_traits> #include "include/v8config.h" #include "src/base/compiler-specific.h" #include "src/base/logging.h" // No-op macro which is used to work around MSVC's funky VA_ARGS support. #define EXPAND(X) … // This macro does nothing. That's all. #define NOTHING(...) … #define CONCAT_(a, ...) … #define CONCAT(a, ...) … // Creates an unique identifier. Useful for scopes to avoid shadowing names. #define UNIQUE_IDENTIFIER(base) … // COUNT_MACRO_ARGS(...) returns the number of arguments passed. Currently, up // to 8 arguments are supported. #define COUNT_MACRO_ARGS(...) … #define COUNT_MACRO_ARGS_IMPL(_8, _7, _6, _5, _4, _3, _2, _1, N, ...) … // GET_NTH_ARG(N, ...) returns the Nth argument in the list of arguments // following. Currently, up to N=8 is supported. #define GET_NTH_ARG(N, ...) … #define GET_NTH_ARG_IMPL_0(_0, ...) … #define GET_NTH_ARG_IMPL_1(_0, _1, ...) … #define GET_NTH_ARG_IMPL_2(_0, _1, _2, ...) … #define GET_NTH_ARG_IMPL_3(_0, _1, _2, _3, ...) … #define GET_NTH_ARG_IMPL_4(_0, _1, _2, _3, _4, ...) … #define GET_NTH_ARG_IMPL_5(_0, _1, _2, _3, _4, _5, ...) … #define GET_NTH_ARG_IMPL_6(_0, _1, _2, _3, _4, _5, _6, ...) … #define GET_NTH_ARG_IMPL_7(_0, _1, _2, _3, _4, _5, _6, _7, ...) … // UNPAREN(x) removes a layer of nested parentheses on x, if any. This means // that both UNPAREN(x) and UNPAREN((x)) expand to x. This is helpful for macros // that want to support multi argument templates with commas, e.g. // // #define FOO(Type, Name) UNPAREN(Type) Name; // // will work with both // // FOO(int, x); // FOO((Foo<int, double, float>), x); #define UNPAREN(X) … #define UNPAREN_(...) … #define DROP_UNPAREN_ #define OFFSET_OF(type, field) … // A comma, to be used in macro arguments where it would otherwise be // interpreted as separator of arguments. #define LITERAL_COMMA … // The arraysize(arr) macro returns the # of elements in an array arr. // The expression is a compile-time constant, and therefore can be // used in defining new arrays, for example. If you use arraysize on // a pointer by mistake, you will get a compile-time error. #define arraysize(array) … // This template function declaration is used in defining arraysize. // Note that the function doesn't need an implementation, as we only // use its type. template <typename T, size_t N> char (&ArraySizeHelper(T (&array)[N]))[N]; #if !V8_CC_MSVC // That gcc wants both of these prototypes seems mysterious. VC, for // its part, can't decide which to use (another mystery). Matching of // template overloads: the final frontier. template <typename T, size_t N> char (&ArraySizeHelper(const T (&array)[N]))[N]; #endif // This is an equivalent to C++20's std::bit_cast<>(), but with additional // warnings. It morally does what `*reinterpret_cast<Dest*>(&source)` does, but // the cast/deref pair is undefined behavior, while bit_cast<>() isn't. // // This is not a magic "get out of UB free" card. This must only be used on // values, not on references or pointers. For pointers, use // reinterpret_cast<>(), or static_cast<>() when casting between void* and other // pointers, and then look at https://eel.is/c++draft/basic.lval#11 as that's // probably UB also. namespace v8::base { template <class Dest, class Source> V8_INLINE Dest bit_cast(Source const& source) { … } } // namespace v8::base // Explicitly declare the assignment operator as deleted. // Note: This macro is deprecated and will be removed soon. Please explicitly // delete the assignment operator instead. #define DISALLOW_ASSIGN(TypeName) … // Explicitly declare all implicit constructors as deleted, namely the // default constructor, copy constructor and operator= functions. // This is especially useful for classes containing only static methods. #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) … // Disallow copying a type, but provide default construction, move construction // and move assignment. Especially useful for move-only structs. #define MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(TypeName) … // Disallow copying a type, and only provide move construction and move // assignment. Especially useful for move-only structs. #define MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName) … // A macro to disallow the dynamic allocation. // This should be used in the private: declarations for a class // Declaring operator new and delete as deleted is not spec compliant. // Extract from 3.2.2 of C++11 spec: // [...] A non-placement deallocation function for a class is // odr-used by the definition of the destructor of that class, [...] #define DISALLOW_NEW_AND_DELETE() … // Define V8_USE_ADDRESS_SANITIZER macro. #if defined(__has_feature) #if __has_feature(address_sanitizer) #define V8_USE_ADDRESS_SANITIZER … #endif #endif // Define V8_USE_HWADDRESS_SANITIZER macro. #if defined(__has_feature) #if __has_feature(hwaddress_sanitizer) #define V8_USE_HWADDRESS_SANITIZER … #endif #endif // Define V8_USE_MEMORY_SANITIZER macro. #if defined(__has_feature) #if __has_feature(memory_sanitizer) #define V8_USE_MEMORY_SANITIZER … #endif #endif // Define V8_USE_UNDEFINED_BEHAVIOR_SANITIZER macro. #if defined(__has_feature) #if __has_feature(undefined_behavior_sanitizer) #define V8_USE_UNDEFINED_BEHAVIOR_SANITIZER … #endif #endif // DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons. #define DISABLE_CFI_PERF … // DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks, // useful because calls into JITed code can not be CFI verified. Same for // UBSan's function pointer type checks. #ifdef V8_OS_WIN // On Windows, also needs __declspec(guard(nocf)) for CFG. #define DISABLE_CFI_ICALL … #else #define DISABLE_CFI_ICALL … #endif // V8_PRETTY_FUNCTION_VALUE_OR(ELSE) emits a pretty function value, if // available for this compiler, otherwise it emits ELSE. #if defined(V8_CC_GNU) #define V8_PRETTY_FUNCTION_VALUE_OR(ELSE) … #elif defined(V8_CC_MSVC) #define V8_PRETTY_FUNCTION_VALUE_OR … #else #define V8_PRETTY_FUNCTION_VALUE_OR … #endif namespace v8 { namespace base { // Note that some implementations of std::is_trivially_copyable mandate that at // least one of the copy constructor, move constructor, copy assignment or move // assignment is non-deleted, while others do not. Be aware that also // base::is_trivially_copyable will differ for these cases. template <typename T> struct is_trivially_copyable { … }; #define ASSERT_TRIVIALLY_COPYABLE(T) … #define ASSERT_NOT_TRIVIALLY_COPYABLE(T) … // The USE(x, ...) template is used to silence C++ compiler warnings // issued for (yet) unused variables (typically parameters). // The arguments are guaranteed to be evaluated from left to right. struct Use { … }; #define USE(...) … } // namespace base } // namespace v8 // implicit_cast<A>(x) triggers an implicit cast from {x} to type {A}. This is // useful in situations where static_cast<A>(x) would do too much. // Only use this for cheap-to-copy types, or use move semantics explicitly. template <class A> V8_INLINE A implicit_cast(A x) { … } // Define our own macros for writing 64-bit constants. This is less fragile // than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it // works on compilers that don't have it (like MSVC). #if V8_CC_MSVC # if V8_HOST_ARCH_64_BIT #define V8_PTR_PREFIX … # else #define V8_PTR_PREFIX … # endif // V8_HOST_ARCH_64_BIT #elif V8_CC_MINGW64 #define V8_PTR_PREFIX … #elif V8_HOST_ARCH_64_BIT #define V8_PTR_PREFIX … #else #if V8_OS_AIX #define V8_PTR_PREFIX … #else #define V8_PTR_PREFIX … #endif #endif #define V8PRIxPTR … #define V8PRIdPTR … #define V8PRIuPTR … #if V8_TARGET_ARCH_64_BIT #define V8_PTR_HEX_DIGITS … #define V8PRIxPTR_FMT … #else #define V8_PTR_HEX_DIGITS … #define V8PRIxPTR_FMT … #endif // ptrdiff_t is 't' according to the standard, but MSVC uses 'I'. #if V8_CC_MSVC #define V8PRIxPTRDIFF … #define V8PRIdPTRDIFF … #define V8PRIuPTRDIFF … #else #define V8PRIxPTRDIFF … #define V8PRIdPTRDIFF … #define V8PRIuPTRDIFF … #endif // Fix for Mac OS X defining uintptr_t as "unsigned long": #if V8_OS_DARWIN #undef V8PRIxPTR #define V8PRIxPTR … #undef V8PRIdPTR #define V8PRIdPTR … #undef V8PRIuPTR #define V8PRIuPTR … #endif // Make a uint64 from two uint32_t halves. inline uint64_t make_uint64(uint32_t high, uint32_t low) { … } // Return the largest multiple of m which is <= x. template <typename T> inline T RoundDown(T x, intptr_t m) { … } template <intptr_t m, typename T> constexpr inline T RoundDown(T x) { … } // Return the smallest multiple of m which is >= x. template <typename T> inline T RoundUp(T x, intptr_t m) { … } template <intptr_t m, typename T> constexpr inline T RoundUp(T x) { … } template <typename T, typename U> constexpr inline bool IsAligned(T value, U alignment) { … } inline void* AlignedAddress(void* address, size_t alignment) { … } inline void* RoundUpAddress(void* address, size_t alignment) { … } // Bounds checks for float to integer conversions, which does truncation. Hence, // the range of legal values is (min - 1, max + 1). template <typename int_t, typename float_t, typename biggest_int_t = int64_t> bool is_inbounds(float_t v) { … } #ifdef V8_OS_WIN // Setup for Windows shared library export. #define V8_EXPORT_ENUM #ifdef BUILDING_V8_SHARED_PRIVATE #define V8_EXPORT_PRIVATE … #elif USING_V8_SHARED_PRIVATE #define V8_EXPORT_PRIVATE … #else #define V8_EXPORT_PRIVATE #endif // BUILDING_V8_SHARED #else // V8_OS_WIN // Setup for Linux shared library export. #if V8_HAS_ATTRIBUTE_VISIBILITY #ifdef BUILDING_V8_SHARED_PRIVATE #define V8_EXPORT_PRIVATE … #define V8_EXPORT_ENUM … #else #define V8_EXPORT_PRIVATE #define V8_EXPORT_ENUM #endif #else #define V8_EXPORT_PRIVATE #define V8_EXPORT_ENUM #endif #endif // V8_OS_WIN // Defines IF_WASM, to be used in macro lists for elements that should only be // there if WebAssembly is enabled. #if V8_ENABLE_WEBASSEMBLY // EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion. #define IF_WASM(V, ...) … #else #define IF_WASM … #endif // V8_ENABLE_WEBASSEMBLY #ifdef V8_ENABLE_DRUMBRAKE #define IF_WASM_DRUMBRAKE … #else #define IF_WASM_DRUMBRAKE(V, ...) … #endif // V8_ENABLE_DRUMBRAKE #if defined(V8_ENABLE_DRUMBRAKE) && !defined(V8_DRUMBRAKE_BOUNDS_CHECKS) #define IF_WASM_DRUMBRAKE_INSTR_HANDLER … #else #define IF_WASM_DRUMBRAKE_INSTR_HANDLER(V, ...) … #endif // V8_ENABLE_DRUMBRAKE && !V8_DRUMBRAKE_BOUNDS_CHECKS // Defines IF_TSAN, to be used in macro lists for elements that should only be // there if TSAN is enabled. #ifdef V8_IS_TSAN // EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion. #define IF_TSAN … #else #define IF_TSAN(V, ...) … #endif // V8_IS_TSAN // Defines IF_INTL, to be used in macro lists for elements that should only be // there if INTL is enabled. #ifdef V8_INTL_SUPPORT // EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion. #define IF_INTL(V, ...) … #else #define IF_INTL … #endif // V8_INTL_SUPPORT // Defines IF_TARGET_ARCH_64_BIT, to be used in macro lists for elements that // should only be there if the target architecture is a 64-bit one. #if V8_TARGET_ARCH_64_BIT // EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion. #define IF_TARGET_ARCH_64_BIT(V, ...) … #else #define IF_TARGET_ARCH_64_BIT … #endif // V8_TARGET_ARCH_64_BIT // Defines IF_OFFICIAL_BUILD and IF_NO_OFFICIAL_BUILD, to be used in macro lists // for elements that should only be there in official / non-official builds. #ifdef OFFICIAL_BUILD // EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion. #define IF_OFFICIAL_BUILD … #define IF_NO_OFFICIAL_BUILD … #else #define IF_OFFICIAL_BUILD(V, ...) … #define IF_NO_OFFICIAL_BUILD(V, ...) … #endif // OFFICIAL_BUILD #ifdef GOOGLE3 // Disable FRIEND_TEST macro in Google3. #define FRIEND_TEST … #endif #endif // V8_BASE_MACROS_H_