/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #ifndef incl_HPHP_PORTABILITY_H_ #define incl_HPHP_PORTABILITY_H_ // From folly/Likely.h #if defined(__GNUC__) && __GNUC__ >= 4 #define LIKELY(x) (__builtin_expect((x), 1)) #define UNLIKELY(x) (__builtin_expect((x), 0)) #else #define LIKELY(x) (x) #define UNLIKELY(x) (x) #endif ////////////////////////////////////////////////////////////////////// /* * Various macros to make certain things conditional on either * compiler or architecture. * * Currently we don't *really* compile on anything other than gcc or * sometimes clang, and there are some parts of the code using * __attribute__ stuff directly, but some things go through these * macros to make it maybe easier to change later. */ ////////////////////////////////////////////////////////////////////// // TODO: does clang define __GNUC__ ? #ifndef __GNUC__ # define __attribute__(x) #endif ////////////////////////////////////////////////////////////////////// #ifdef ATTRIBUTE_UNUSED # undef ATTRIBUTE_UNUSED #endif #ifdef ATTRIBUTE_NORETURN # undef ATTRIBUTE_NORETURN #endif #ifdef ATTRIBUTE_PRINTF # undef ATTRIBUTE_PRINTF #endif #ifdef ATTRIBUTE_PRINTF_STRING # undef ATTRIBUTE_PRINTF_STRING #endif #define ATTRIBUTE_PRINTF_STRING FOLLY_PRINTF_FORMAT #ifdef _MSC_VER #define ATTRIBUTE_NORETURN __declspec(noreturn) #define ATTRIBUTE_PRINTF(a1, a2) #ifndef __thread # define __thread __declspec(thread) #endif #define ATTRIBUTE_UNUSED #define ALWAYS_INLINE __forceinline #define EXTERNALLY_VISIBLE #define FLATTEN #define NEVER_INLINE __declspec(noinline) #define UNUSED #else #define ATTRIBUTE_NORETURN __attribute__((__noreturn__)) #define ATTRIBUTE_PRINTF(a1, a2) \ __attribute__((__format__ (__printf__, a1, a2))) #define ATTRIBUTE_UNUSED __attribute__((__unused__)) #define ALWAYS_INLINE inline __attribute__((__always_inline__)) #define EXTERNALLY_VISIBLE __attribute__((__externally_visible__)) #define FLATTEN __attribute__((__flatten__)) #define NEVER_INLINE __attribute__((__noinline__)) #define UNUSED __attribute__((__unused__)) #endif #ifdef DEBUG # define DEBUG_ONLY /* nop */ #else # define DEBUG_ONLY UNUSED #endif /* * We need to keep some unreferenced functions from being removed by * the linker. There is no compile time mechanism for doing this, but * by putting them in the same section as some other, referenced function * in the same file, we can keep them around. * * So this macro should be used to mark at least one function that is * referenced, and other functions that are not referenced in the same * file. * * Note: this may not work properly with LTO. We'll revisit when/if we * move to it. */ #ifndef __APPLE__ # define KEEP_SECTION \ __attribute__((__section__(".text.keep"))) #else # define KEEP_SECTION \ __attribute__((__section__(".text,.text.keep"))) #endif #if defined(__APPLE__) // OS X has a macro "isset" defined in this header. Force the include so we can // make sure the macro gets undef'd. (I think this also applies to BSD, but we // can cross that road when we come to it.) # include # ifdef isset # undef isset # endif #endif ////////////////////////////////////////////////////////////////////// #if defined(__x86_64__) # if defined(__clang__) # define DECLARE_FRAME_POINTER(fp) \ ActRec* fp; \ asm volatile("mov %%rbp, %0" : "=r" (fp) ::) # else # define DECLARE_FRAME_POINTER(fp) register ActRec* fp asm("rbp"); # endif #elif defined(_M_X64) // TODO: FIXME! Without this implemented properly, the JIT // will fail "pretty spectacularly". # define DECLARE_FRAME_POINTER(fp) \ always_assert(false); \ register ActRec* fp = nullptr; #elif defined(__AARCH64EL__) # if defined(__clang__) # error Clang implementation not done for ARM # endif # define DECLARE_FRAME_POINTER(fp) register ActRec* fp asm("x29"); #elif defined(__powerpc64__) # if defined(__clang__) # error Clang implementation not done for PPC64 # endif # define DECLARE_FRAME_POINTER(fp) register ActRec* fp = (ActRec*) __builtin_frame_address(0); #else # error What are the stack and frame pointers called on your architecture? #endif ////////////////////////////////////////////////////////////////////// // We reserve the exit status 127 to signal a failure in the // interpreter. 127 is a valid exit code on all reasonable // architectures: POSIX requires at least 8 unsigned bits and // Windows 32 signed bits. #define HPHP_EXIT_FAILURE 127 ////////////////////////////////////////////////////////////////////// #if FACEBOOK // Linking in libbfd is a gigantic PITA. If you want this yourself in a non-FB // build, feel free to define HAVE_LIBBFD and specify the right options to link // in libbfd.a in the extra C++ options. #define HAVE_LIBBFD 1 #endif #ifndef PACKAGE // The value doesn't matter, but it must be defined before you include // bfd.h #define PACKAGE "hhvm" #endif ////////////////////////////////////////////////////////////////////// #endif