Home | History | Annotate | Download | only in base
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_BASE_MACROS_H_
      6 #define V8_BASE_MACROS_H_
      7 
      8 #include "src/base/compiler-specific.h"
      9 #include "src/base/format-macros.h"
     10 #include "src/base/logging.h"
     11 
     12 
     13 // TODO(all) Replace all uses of this macro with C++'s offsetof. To do that, we
     14 // have to make sure that only standard-layout types and simple field
     15 // designators are used.
     16 #define OFFSET_OF(type, field) \
     17   (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(16)->field)) - 16)
     18 
     19 
     20 // The arraysize(arr) macro returns the # of elements in an array arr.
     21 // The expression is a compile-time constant, and therefore can be
     22 // used in defining new arrays, for example.  If you use arraysize on
     23 // a pointer by mistake, you will get a compile-time error.
     24 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
     25 
     26 
     27 // This template function declaration is used in defining arraysize.
     28 // Note that the function doesn't need an implementation, as we only
     29 // use its type.
     30 template <typename T, size_t N>
     31 char (&ArraySizeHelper(T (&array)[N]))[N];
     32 
     33 
     34 #if !V8_CC_MSVC
     35 // That gcc wants both of these prototypes seems mysterious. VC, for
     36 // its part, can't decide which to use (another mystery). Matching of
     37 // template overloads: the final frontier.
     38 template <typename T, size_t N>
     39 char (&ArraySizeHelper(const T (&array)[N]))[N];
     40 #endif
     41 
     42 
     43 // bit_cast<Dest,Source> is a template function that implements the
     44 // equivalent of "*reinterpret_cast<Dest*>(&source)".  We need this in
     45 // very low-level functions like the protobuf library and fast math
     46 // support.
     47 //
     48 //   float f = 3.14159265358979;
     49 //   int i = bit_cast<int32>(f);
     50 //   // i = 0x40490fdb
     51 //
     52 // The classical address-casting method is:
     53 //
     54 //   // WRONG
     55 //   float f = 3.14159265358979;            // WRONG
     56 //   int i = * reinterpret_cast<int*>(&f);  // WRONG
     57 //
     58 // The address-casting method actually produces undefined behavior
     59 // according to ISO C++ specification section 3.10 -15 -.  Roughly, this
     60 // section says: if an object in memory has one type, and a program
     61 // accesses it with a different type, then the result is undefined
     62 // behavior for most values of "different type".
     63 //
     64 // This is true for any cast syntax, either *(int*)&f or
     65 // *reinterpret_cast<int*>(&f).  And it is particularly true for
     66 // conversions between integral lvalues and floating-point lvalues.
     67 //
     68 // The purpose of 3.10 -15- is to allow optimizing compilers to assume
     69 // that expressions with different types refer to different memory.  gcc
     70 // 4.0.1 has an optimizer that takes advantage of this.  So a
     71 // non-conforming program quietly produces wildly incorrect output.
     72 //
     73 // The problem is not the use of reinterpret_cast.  The problem is type
     74 // punning: holding an object in memory of one type and reading its bits
     75 // back using a different type.
     76 //
     77 // The C++ standard is more subtle and complex than this, but that
     78 // is the basic idea.
     79 //
     80 // Anyways ...
     81 //
     82 // bit_cast<> calls memcpy() which is blessed by the standard,
     83 // especially by the example in section 3.9 .  Also, of course,
     84 // bit_cast<> wraps up the nasty logic in one place.
     85 //
     86 // Fortunately memcpy() is very fast.  In optimized mode, with a
     87 // constant size, gcc 2.95.3, gcc 4.0.1, and msvc 7.1 produce inline
     88 // code with the minimal amount of data movement.  On a 32-bit system,
     89 // memcpy(d,s,4) compiles to one load and one store, and memcpy(d,s,8)
     90 // compiles to two loads and two stores.
     91 //
     92 // I tested this code with gcc 2.95.3, gcc 4.0.1, icc 8.1, and msvc 7.1.
     93 //
     94 // WARNING: if Dest or Source is a non-POD type, the result of the memcpy
     95 // is likely to surprise you.
     96 template <class Dest, class Source>
     97 V8_INLINE Dest bit_cast(Source const& source) {
     98   static_assert(sizeof(Dest) == sizeof(Source),
     99                 "source and dest must be same size");
    100   Dest dest;
    101   memcpy(&dest, &source, sizeof(dest));
    102   return dest;
    103 }
    104 
    105 
    106 // Put this in the private: declarations for a class to be unassignable.
    107 #define DISALLOW_ASSIGN(TypeName) void operator=(const TypeName&)
    108 
    109 
    110 // A macro to disallow the evil copy constructor and operator= functions
    111 // This should be used in the private: declarations for a class
    112 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    113   TypeName(const TypeName&) = delete;      \
    114   void operator=(const TypeName&) = delete
    115 
    116 
    117 // A macro to disallow all the implicit constructors, namely the
    118 // default constructor, copy constructor and operator= functions.
    119 //
    120 // This should be used in the private: declarations for a class
    121 // that wants to prevent anyone from instantiating it. This is
    122 // especially useful for classes containing only static methods.
    123 #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
    124   TypeName() = delete;                           \
    125   DISALLOW_COPY_AND_ASSIGN(TypeName)
    126 
    127 
    128 // Newly written code should use V8_INLINE and V8_NOINLINE directly.
    129 #define INLINE(declarator)    V8_INLINE declarator
    130 #define NO_INLINE(declarator) V8_NOINLINE declarator
    131 
    132 
    133 // Newly written code should use WARN_UNUSED_RESULT.
    134 #define MUST_USE_RESULT WARN_UNUSED_RESULT
    135 
    136 
    137 // Define V8_USE_ADDRESS_SANITIZER macros.
    138 #if defined(__has_feature)
    139 #if __has_feature(address_sanitizer)
    140 #define V8_USE_ADDRESS_SANITIZER 1
    141 #endif
    142 #endif
    143 
    144 // Define DISABLE_ASAN macros.
    145 #ifdef V8_USE_ADDRESS_SANITIZER
    146 #define DISABLE_ASAN __attribute__((no_sanitize_address))
    147 #else
    148 #define DISABLE_ASAN
    149 #endif
    150 
    151 // DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons.
    152 #if !defined(DISABLE_CFI_PERF)
    153 #if defined(__clang__) && defined(__has_attribute)
    154 #if __has_attribute(no_sanitize)
    155 #define DISABLE_CFI_PERF __attribute__((no_sanitize("cfi")))
    156 #endif
    157 #endif
    158 #endif
    159 #if !defined(DISABLE_CFI_PERF)
    160 #define DISABLE_CFI_PERF
    161 #endif
    162 
    163 #if V8_CC_GNU
    164 #define V8_IMMEDIATE_CRASH() __builtin_trap()
    165 #else
    166 #define V8_IMMEDIATE_CRASH() ((void(*)())0)()
    167 #endif
    168 
    169 
    170 // TODO(all) Replace all uses of this macro with static_assert, remove macro.
    171 #define STATIC_ASSERT(test) static_assert(test, #test)
    172 
    173 
    174 // The USE(x) template is used to silence C++ compiler warnings
    175 // issued for (yet) unused variables (typically parameters).
    176 template <typename T>
    177 inline void USE(T) { }
    178 
    179 
    180 #define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
    181 
    182 
    183 // Define our own macros for writing 64-bit constants.  This is less fragile
    184 // than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
    185 // works on compilers that don't have it (like MSVC).
    186 #if V8_CC_MSVC
    187 # define V8_UINT64_C(x)   (x ## UI64)
    188 # define V8_INT64_C(x)    (x ## I64)
    189 # if V8_HOST_ARCH_64_BIT
    190 #  define V8_INTPTR_C(x)  (x ## I64)
    191 #  define V8_PTR_PREFIX   "ll"
    192 # else
    193 #  define V8_INTPTR_C(x)  (x)
    194 #  define V8_PTR_PREFIX   ""
    195 # endif  // V8_HOST_ARCH_64_BIT
    196 #elif V8_CC_MINGW64
    197 # define V8_UINT64_C(x)   (x ## ULL)
    198 # define V8_INT64_C(x)    (x ## LL)
    199 # define V8_INTPTR_C(x)   (x ## LL)
    200 # define V8_PTR_PREFIX    "I64"
    201 #elif V8_HOST_ARCH_64_BIT
    202 # if V8_OS_MACOSX || V8_OS_OPENBSD
    203 #  define V8_UINT64_C(x)   (x ## ULL)
    204 #  define V8_INT64_C(x)    (x ## LL)
    205 # else
    206 #  define V8_UINT64_C(x)   (x ## UL)
    207 #  define V8_INT64_C(x)    (x ## L)
    208 # endif
    209 # define V8_INTPTR_C(x)   (x ## L)
    210 # define V8_PTR_PREFIX    "l"
    211 #else
    212 # define V8_UINT64_C(x)   (x ## ULL)
    213 # define V8_INT64_C(x)    (x ## LL)
    214 # define V8_INTPTR_C(x)   (x)
    215 #if V8_OS_AIX
    216 #define V8_PTR_PREFIX "l"
    217 #else
    218 # define V8_PTR_PREFIX    ""
    219 #endif
    220 #endif
    221 
    222 #define V8PRIxPTR V8_PTR_PREFIX "x"
    223 #define V8PRIdPTR V8_PTR_PREFIX "d"
    224 #define V8PRIuPTR V8_PTR_PREFIX "u"
    225 
    226 // ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
    227 #if V8_CC_MSVC
    228 #define V8PRIxPTRDIFF "Ix"
    229 #define V8PRIdPTRDIFF "Id"
    230 #define V8PRIuPTRDIFF "Iu"
    231 #else
    232 #define V8PRIxPTRDIFF "tx"
    233 #define V8PRIdPTRDIFF "td"
    234 #define V8PRIuPTRDIFF "tu"
    235 #endif
    236 
    237 // Fix for Mac OS X defining uintptr_t as "unsigned long":
    238 #if V8_OS_MACOSX
    239 #undef V8PRIxPTR
    240 #define V8PRIxPTR "lx"
    241 #undef V8PRIdPTR
    242 #define V8PRIdPTR "ld"
    243 #undef V8PRIuPTR
    244 #define V8PRIuPTR "lxu"
    245 #endif
    246 
    247 // The following macro works on both 32 and 64-bit platforms.
    248 // Usage: instead of writing 0x1234567890123456
    249 //      write V8_2PART_UINT64_C(0x12345678,90123456);
    250 #define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
    251 
    252 
    253 // Compute the 0-relative offset of some absolute value x of type T.
    254 // This allows conversion of Addresses and integral types into
    255 // 0-relative int offsets.
    256 template <typename T>
    257 inline intptr_t OffsetFrom(T x) {
    258   return x - static_cast<T>(0);
    259 }
    260 
    261 
    262 // Compute the absolute value of type T for some 0-relative offset x.
    263 // This allows conversion of 0-relative int offsets into Addresses and
    264 // integral types.
    265 template <typename T>
    266 inline T AddressFrom(intptr_t x) {
    267   return static_cast<T>(static_cast<T>(0) + x);
    268 }
    269 
    270 
    271 // Return the largest multiple of m which is <= x.
    272 template <typename T>
    273 inline T RoundDown(T x, intptr_t m) {
    274   DCHECK(IS_POWER_OF_TWO(m));
    275   return AddressFrom<T>(OffsetFrom(x) & -m);
    276 }
    277 
    278 
    279 // Return the smallest multiple of m which is >= x.
    280 template <typename T>
    281 inline T RoundUp(T x, intptr_t m) {
    282   return RoundDown<T>(static_cast<T>(x + m - 1), m);
    283 }
    284 
    285 #endif   // V8_BASE_MACROS_H_
    286