portability_macros.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright (c) Meta Platforms, Inc. and affiliates.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. * You may select, at your option, one of the above-listed licenses.
  9. */
  10. #ifndef ZSTD_PORTABILITY_MACROS_H
  11. #define ZSTD_PORTABILITY_MACROS_H
  12. /**
  13. * This header file contains macro definitions to support portability.
  14. * This header is shared between C and ASM code, so it MUST only
  15. * contain macro definitions. It MUST not contain any C code.
  16. *
  17. * This header ONLY defines macros to detect platforms/feature support.
  18. *
  19. */
  20. /* compat. with non-clang compilers */
  21. #ifndef __has_attribute
  22. #define __has_attribute(x) 0
  23. #endif
  24. /* compat. with non-clang compilers */
  25. #ifndef __has_builtin
  26. # define __has_builtin(x) 0
  27. #endif
  28. /* compat. with non-clang compilers */
  29. #ifndef __has_feature
  30. # define __has_feature(x) 0
  31. #endif
  32. /* detects whether we are being compiled under msan */
  33. #ifndef ZSTD_MEMORY_SANITIZER
  34. # if __has_feature(memory_sanitizer)
  35. # define ZSTD_MEMORY_SANITIZER 1
  36. # else
  37. # define ZSTD_MEMORY_SANITIZER 0
  38. # endif
  39. #endif
  40. /* detects whether we are being compiled under asan */
  41. #ifndef ZSTD_ADDRESS_SANITIZER
  42. # if __has_feature(address_sanitizer)
  43. # define ZSTD_ADDRESS_SANITIZER 1
  44. # elif defined(__SANITIZE_ADDRESS__)
  45. # define ZSTD_ADDRESS_SANITIZER 1
  46. # else
  47. # define ZSTD_ADDRESS_SANITIZER 0
  48. # endif
  49. #endif
  50. /* detects whether we are being compiled under dfsan */
  51. #ifndef ZSTD_DATAFLOW_SANITIZER
  52. # if __has_feature(dataflow_sanitizer)
  53. # define ZSTD_DATAFLOW_SANITIZER 1
  54. # else
  55. # define ZSTD_DATAFLOW_SANITIZER 0
  56. # endif
  57. #endif
  58. /* Mark the internal assembly functions as hidden */
  59. #ifdef __ELF__
  60. # define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func
  61. #elif defined(__APPLE__)
  62. # define ZSTD_HIDE_ASM_FUNCTION(func) .private_extern func
  63. #else
  64. # define ZSTD_HIDE_ASM_FUNCTION(func)
  65. #endif
  66. /* Compile time determination of BMI2 support */
  67. #ifndef STATIC_BMI2
  68. # if defined(__BMI2__)
  69. # define STATIC_BMI2 1
  70. # elif defined(_MSC_VER) && defined(__AVX2__)
  71. # define STATIC_BMI2 1 /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */
  72. # endif
  73. #endif
  74. #ifndef STATIC_BMI2
  75. # define STATIC_BMI2 0
  76. #endif
  77. /* Enable runtime BMI2 dispatch based on the CPU.
  78. * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
  79. */
  80. #ifndef DYNAMIC_BMI2
  81. # if ((defined(__clang__) && __has_attribute(__target__)) \
  82. || (defined(__GNUC__) \
  83. && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
  84. && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)) \
  85. && !defined(__BMI2__)
  86. # define DYNAMIC_BMI2 1
  87. # else
  88. # define DYNAMIC_BMI2 0
  89. # endif
  90. #endif
  91. /**
  92. * Only enable assembly for GNU C compatible compilers,
  93. * because other platforms may not support GAS assembly syntax.
  94. *
  95. * Only enable assembly for Linux / MacOS / Win32, other platforms may
  96. * work, but they haven't been tested. This could likely be
  97. * extended to BSD systems.
  98. *
  99. * Disable assembly when MSAN is enabled, because MSAN requires
  100. * 100% of code to be instrumented to work.
  101. */
  102. #if defined(__GNUC__)
  103. # if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32)
  104. # if ZSTD_MEMORY_SANITIZER
  105. # define ZSTD_ASM_SUPPORTED 0
  106. # elif ZSTD_DATAFLOW_SANITIZER
  107. # define ZSTD_ASM_SUPPORTED 0
  108. # else
  109. # define ZSTD_ASM_SUPPORTED 1
  110. # endif
  111. # else
  112. # define ZSTD_ASM_SUPPORTED 0
  113. # endif
  114. #else
  115. # define ZSTD_ASM_SUPPORTED 0
  116. #endif
  117. /**
  118. * Determines whether we should enable assembly for x86-64
  119. * with BMI2.
  120. *
  121. * Enable if all of the following conditions hold:
  122. * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
  123. * - Assembly is supported
  124. * - We are compiling for x86-64 and either:
  125. * - DYNAMIC_BMI2 is enabled
  126. * - BMI2 is supported at compile time
  127. */
  128. #if !defined(ZSTD_DISABLE_ASM) && \
  129. ZSTD_ASM_SUPPORTED && \
  130. defined(__x86_64__) && \
  131. (DYNAMIC_BMI2 || defined(__BMI2__))
  132. # define ZSTD_ENABLE_ASM_X86_64_BMI2 1
  133. #else
  134. # define ZSTD_ENABLE_ASM_X86_64_BMI2 0
  135. #endif
  136. /*
  137. * For x86 ELF targets, add .note.gnu.property section for Intel CET in
  138. * assembly sources when CET is enabled.
  139. *
  140. * Additionally, any function that may be called indirectly must begin
  141. * with ZSTD_CET_ENDBRANCH.
  142. */
  143. #if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \
  144. && defined(__has_include)
  145. # if __has_include(<cet.h>)
  146. # include <cet.h>
  147. # define ZSTD_CET_ENDBRANCH _CET_ENDBR
  148. # endif
  149. #endif
  150. #ifndef ZSTD_CET_ENDBRANCH
  151. # define ZSTD_CET_ENDBRANCH
  152. #endif
  153. #endif /* ZSTD_PORTABILITY_MACROS_H */