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