1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  */
    
  7. 
    
  8. #ifndef incl_HPHP_PORTABILITY_H_
    
  9. #define incl_HPHP_PORTABILITY_H_
    
  10. 
    
  11. // From folly/Likely.h
    
  12. #if defined(__GNUC__) && __GNUC__ >= 4
    
  13. #define LIKELY(x)   (__builtin_expect((x), 1))
    
  14. #define UNLIKELY(x) (__builtin_expect((x), 0))
    
  15. #else
    
  16. #define LIKELY(x)   (x)
    
  17. #define UNLIKELY(x) (x)
    
  18. #endif
    
  19. 
    
  20. //////////////////////////////////////////////////////////////////////
    
  21. 
    
  22. /*
    
  23.  * Various macros to make certain things conditional on either
    
  24.  * compiler or architecture.
    
  25.  *
    
  26.  * Currently we don't *really* compile on anything other than gcc or
    
  27.  * sometimes clang, and there are some parts of the code using
    
  28.  * __attribute__ stuff directly, but some things go through these
    
  29.  * macros to make it maybe easier to change later.
    
  30.  */
    
  31. 
    
  32. //////////////////////////////////////////////////////////////////////
    
  33. 
    
  34. // TODO: does clang define __GNUC__ ?
    
  35. #ifndef __GNUC__
    
  36. # define __attribute__(x)
    
  37. #endif
    
  38. 
    
  39. //////////////////////////////////////////////////////////////////////
    
  40. 
    
  41. #ifdef ATTRIBUTE_UNUSED
    
  42. # undef ATTRIBUTE_UNUSED
    
  43. #endif
    
  44. #ifdef ATTRIBUTE_NORETURN
    
  45. # undef ATTRIBUTE_NORETURN
    
  46. #endif
    
  47. #ifdef ATTRIBUTE_PRINTF
    
  48. # undef ATTRIBUTE_PRINTF
    
  49. #endif
    
  50. #ifdef ATTRIBUTE_PRINTF_STRING
    
  51. # undef ATTRIBUTE_PRINTF_STRING
    
  52. #endif
    
  53. 
    
  54. #define ATTRIBUTE_PRINTF_STRING FOLLY_PRINTF_FORMAT
    
  55. 
    
  56. #ifdef _MSC_VER
    
  57. #define ATTRIBUTE_NORETURN __declspec(noreturn)
    
  58. #define ATTRIBUTE_PRINTF(a1, a2)
    
  59. #ifndef __thread
    
  60. # define __thread __declspec(thread)
    
  61. #endif
    
  62. #define ATTRIBUTE_UNUSED
    
  63. 
    
  64. #define ALWAYS_INLINE __forceinline
    
  65. #define EXTERNALLY_VISIBLE
    
  66. #define FLATTEN
    
  67. #define NEVER_INLINE __declspec(noinline)
    
  68. #define UNUSED
    
  69. #else
    
  70. #define ATTRIBUTE_NORETURN __attribute__((__noreturn__))
    
  71. #define ATTRIBUTE_PRINTF(a1, a2) \
    
  72.   __attribute__((__format__ (__printf__, a1, a2)))
    
  73. #define ATTRIBUTE_UNUSED   __attribute__((__unused__))
    
  74. 
    
  75. #define ALWAYS_INLINE      inline __attribute__((__always_inline__))
    
  76. #define EXTERNALLY_VISIBLE __attribute__((__externally_visible__))
    
  77. #define FLATTEN            __attribute__((__flatten__))
    
  78. #define NEVER_INLINE       __attribute__((__noinline__))
    
  79. #define UNUSED             __attribute__((__unused__))
    
  80. #endif
    
  81. 
    
  82. #ifdef DEBUG
    
  83. # define DEBUG_ONLY /* nop */
    
  84. #else
    
  85. # define DEBUG_ONLY UNUSED
    
  86. #endif
    
  87. 
    
  88. /*
    
  89.  * We need to keep some unreferenced functions from being removed by
    
  90.  * the linker. There is no compile time mechanism for doing this, but
    
  91.  * by putting them in the same section as some other, referenced function
    
  92.  * in the same file, we can keep them around.
    
  93.  *
    
  94.  * So this macro should be used to mark at least one function that is
    
  95.  * referenced, and other functions that are not referenced in the same
    
  96.  * file.
    
  97.  *
    
  98.  * Note: this may not work properly with LTO. We'll revisit when/if we
    
  99.  * move to it.
    
  100.  */
    
  101. #ifndef __APPLE__
    
  102. # define KEEP_SECTION \
    
  103.     __attribute__((__section__(".text.keep")))
    
  104. #else
    
  105. # define KEEP_SECTION \
    
  106.     __attribute__((__section__(".text,.text.keep")))
    
  107. #endif
    
  108. 
    
  109. #if defined(__APPLE__)
    
  110. // OS X has a macro "isset" defined in this header. Force the include so we can
    
  111. // make sure the macro gets undef'd. (I think this also applies to BSD, but we
    
  112. // can cross that road when we come to it.)
    
  113. # include <sys/param.h>
    
  114. # ifdef isset
    
  115. #  undef isset
    
  116. # endif
    
  117. #endif
    
  118. 
    
  119. //////////////////////////////////////////////////////////////////////
    
  120. 
    
  121. #if defined(__x86_64__)
    
  122. 
    
  123. # if defined(__clang__)
    
  124. #  define DECLARE_FRAME_POINTER(fp)               \
    
  125.     ActRec* fp;                                   \
    
  126.     asm volatile("mov %%rbp, %0" : "=r" (fp) ::)
    
  127. # else
    
  128. #  define DECLARE_FRAME_POINTER(fp) register ActRec* fp asm("rbp");
    
  129. # endif
    
  130. 
    
  131. #elif defined(_M_X64)
    
  132. 
    
  133. // TODO: FIXME! Without this implemented properly, the JIT
    
  134. // will fail "pretty spectacularly".
    
  135. # define DECLARE_FRAME_POINTER(fp) \
    
  136.   always_assert(false);            \
    
  137.   register ActRec* fp = nullptr;
    
  138. 
    
  139. #elif defined(__AARCH64EL__)
    
  140. 
    
  141. # if defined(__clang__)
    
  142. #  error Clang implementation not done for ARM
    
  143. # endif
    
  144. # define DECLARE_FRAME_POINTER(fp) register ActRec* fp asm("x29");
    
  145. 
    
  146. #elif defined(__powerpc64__)
    
  147. 
    
  148. # if defined(__clang__)
    
  149. #  error Clang implementation not done for PPC64
    
  150. # endif
    
  151. # define DECLARE_FRAME_POINTER(fp) register ActRec* fp = (ActRec*) __builtin_frame_address(0);
    
  152. 
    
  153. #else
    
  154. 
    
  155. # error What are the stack and frame pointers called on your architecture?
    
  156. 
    
  157. #endif
    
  158. 
    
  159. //////////////////////////////////////////////////////////////////////
    
  160. 
    
  161. // We reserve the exit status 127 to signal a failure in the
    
  162. // interpreter. 127 is a valid exit code on all reasonable
    
  163. // architectures: POSIX requires at least 8 unsigned bits and
    
  164. // Windows 32 signed bits.
    
  165. #define HPHP_EXIT_FAILURE 127
    
  166. 
    
  167. //////////////////////////////////////////////////////////////////////
    
  168. 
    
  169. #if FACEBOOK
    
  170. // Linking in libbfd is a gigantic PITA. If you want this yourself in a non-FB
    
  171. // build, feel free to define HAVE_LIBBFD and specify the right options to link
    
  172. // in libbfd.a in the extra C++ options.
    
  173. #define HAVE_LIBBFD 1
    
  174. #endif
    
  175. 
    
  176. #ifndef PACKAGE
    
  177. // The value doesn't matter, but it must be defined before you include
    
  178. // bfd.h
    
  179. #define PACKAGE "hhvm"
    
  180. #endif
    
  181. 
    
  182. //////////////////////////////////////////////////////////////////////
    
  183. 
    
  184. #endif