]>
Commit | Line | Data |
---|---|---|
f9995f31 MG |
1 | /* Copyright 2015 Google Inc. All Rights Reserved. |
2 | ||
3 | Distributed under MIT license. | |
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | |
5 | */ | |
6 | ||
7 | /* Macros for compiler / platform specific features and build options. | |
8 | ||
9 | Build options are: | |
10 | * BROTLI_BUILD_32_BIT disables 64-bit optimizations | |
11 | * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations | |
12 | * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations | |
13 | * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations | |
14 | * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations | |
15 | * BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins, | |
16 | features and attributes | |
17 | * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned | |
18 | read and overlapping memcpy; this reduces decompression speed by 5% | |
19 | * BROTLI_DEBUG dumps file name and line number when decoder detects stream | |
20 | or memory error | |
21 | * BROTLI_DECODE_DEBUG enables asserts and dumps various state information | |
22 | */ | |
23 | ||
24 | #ifndef BROTLI_DEC_PORT_H_ | |
25 | #define BROTLI_DEC_PORT_H_ | |
26 | ||
27 | #include<assert.h> | |
28 | ||
29 | /* Compatibility with non-clang compilers. */ | |
30 | #ifndef __has_builtin | |
31 | #define __has_builtin(x) 0 | |
32 | #endif | |
33 | ||
34 | #ifndef __has_attribute | |
35 | #define __has_attribute(x) 0 | |
36 | #endif | |
37 | ||
38 | #ifndef __has_feature | |
39 | #define __has_feature(x) 0 | |
40 | #endif | |
41 | ||
42 | #if defined(__sparc) | |
43 | #define BROTLI_TARGET_SPARC | |
44 | #endif | |
45 | ||
46 | #if defined(__arm__) || defined(__thumb__) || \ | |
47 | defined(_M_ARM) || defined(_M_ARMT) | |
48 | #define BROTLI_TARGET_ARM | |
49 | #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) || \ | |
50 | (defined(M_ARM) && (M_ARM >= 7)) | |
51 | #define BROTLI_TARGET_ARMV7 | |
52 | #endif /* ARMv7 */ | |
53 | #if defined(__aarch64__) | |
54 | #define BROTLI_TARGET_ARMV8 | |
55 | #endif /* ARMv8 */ | |
56 | #endif /* ARM */ | |
57 | ||
58 | #if defined(__x86_64__) || defined(_M_X64) | |
59 | #define BROTLI_TARGET_X64 | |
60 | #endif | |
61 | ||
62 | #if defined(__PPC64__) | |
63 | #define BROTLI_TARGET_POWERPC64 | |
64 | #endif | |
65 | ||
66 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) | |
67 | #define BROTLI_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) | |
68 | #else | |
69 | #define BROTLI_GCC_VERSION 0 | |
70 | #endif | |
71 | ||
72 | #if defined(__ICC) | |
73 | #define BROTLI_ICC_VERSION __ICC | |
74 | #else | |
75 | #define BROTLI_ICC_VERSION 0 | |
76 | #endif | |
77 | ||
78 | #if defined(BROTLI_BUILD_MODERN_COMPILER) | |
79 | #define BROTLI_MODERN_COMPILER 1 | |
80 | #elif (BROTLI_GCC_VERSION > 300) || (BROTLI_ICC_VERSION >= 1600) | |
81 | #define BROTLI_MODERN_COMPILER 1 | |
82 | #else | |
83 | #define BROTLI_MODERN_COMPILER 0 | |
84 | #endif | |
85 | ||
86 | /* SPARC and ARMv6 don't support unaligned read. | |
87 | Choose portable build for them. */ | |
88 | #if !defined(BROTLI_BUILD_PORTABLE) | |
89 | #if defined(BROTLI_TARGET_SPARC) || \ | |
90 | (defined(BROTLI_TARGET_ARM) && !defined(BROTLI_TARGET_ARMV7)) | |
91 | #define BROTLI_BUILD_PORTABLE | |
92 | #endif /* SPARK or ARMv6 */ | |
93 | #endif /* portable build */ | |
94 | ||
95 | #ifdef BROTLI_BUILD_PORTABLE | |
96 | #define BROTLI_ALIGNED_READ 1 | |
97 | #define BROTLI_SAFE_MEMMOVE 1 | |
98 | #else | |
99 | #define BROTLI_ALIGNED_READ 0 | |
100 | #define BROTLI_SAFE_MEMMOVE 0 | |
101 | #endif | |
102 | ||
103 | #define BROTLI_ASAN_BUILD __has_feature(address_sanitizer) | |
104 | ||
105 | /* Define "PREDICT_TRUE" and "PREDICT_FALSE" macros for capable compilers. | |
106 | ||
107 | To apply compiler hint, enclose the branching condition into macros, like this: | |
108 | ||
109 | if (PREDICT_TRUE(zero == 0)) { | |
110 | // main execution path | |
111 | } else { | |
112 | // compiler should place this code outside of main execution path | |
113 | } | |
114 | ||
115 | OR: | |
116 | ||
117 | if (PREDICT_FALSE(something_rare_or_unexpected_happens)) { | |
118 | // compiler should place this code outside of main execution path | |
119 | } | |
120 | ||
121 | */ | |
122 | #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_expect) | |
123 | #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) | |
124 | #define PREDICT_FALSE(x) (__builtin_expect(x, 0)) | |
125 | #else | |
126 | #define PREDICT_FALSE(x) (x) | |
127 | #define PREDICT_TRUE(x) (x) | |
128 | #endif | |
129 | ||
130 | /* IS_CONSTANT macros returns true for compile-time constant expressions. */ | |
131 | #if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p) | |
132 | #define IS_CONSTANT(x) __builtin_constant_p(x) | |
133 | #else | |
134 | #define IS_CONSTANT(x) 0 | |
135 | #endif | |
136 | ||
137 | #if BROTLI_MODERN_COMPILER || __has_attribute(always_inline) | |
138 | #define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) | |
139 | #else | |
140 | #define ATTRIBUTE_ALWAYS_INLINE | |
141 | #endif | |
142 | ||
143 | #ifndef _MSC_VER | |
144 | #if defined(__cplusplus) || !defined(__STRICT_ANSI__) \ | |
145 | || __STDC_VERSION__ >= 199901L | |
146 | #define BROTLI_INLINE inline ATTRIBUTE_ALWAYS_INLINE | |
147 | #else | |
148 | #define BROTLI_INLINE | |
149 | #endif | |
150 | #else /* _MSC_VER */ | |
151 | #define BROTLI_INLINE __forceinline | |
152 | #endif /* _MSC_VER */ | |
153 | ||
154 | #ifdef BROTLI_DECODE_DEBUG | |
155 | #define BROTLI_DCHECK(x) assert(x) | |
156 | #else | |
157 | #define BROTLI_DCHECK(x) | |
158 | #endif | |
159 | ||
160 | #if defined(BROTLI_BUILD_64_BIT) | |
161 | #define BROTLI_64_BITS 1 | |
162 | #elif defined(BROTLI_BUILD_32_BIT) | |
163 | #define BROTLI_64_BITS 0 | |
164 | #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \ | |
165 | defined(BROTLI_TARGET_POWERPC64) | |
166 | #define BROTLI_64_BITS 1 | |
167 | #else | |
168 | #define BROTLI_64_BITS 0 | |
169 | #endif | |
170 | ||
171 | #if defined(BROTLI_BUILD_BIG_ENDIAN) | |
172 | #define BROTLI_LITTLE_ENDIAN 0 | |
173 | #define BROTLI_BIG_ENDIAN 1 | |
174 | #elif defined(BROTLI_BUILD_LITTLE_ENDIAN) | |
175 | #define BROTLI_LITTLE_ENDIAN 1 | |
176 | #define BROTLI_BIG_ENDIAN 0 | |
177 | #elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL) | |
178 | #define BROTLI_LITTLE_ENDIAN 0 | |
179 | #define BROTLI_BIG_ENDIAN 0 | |
180 | #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) | |
181 | #define BROTLI_LITTLE_ENDIAN 1 | |
182 | #define BROTLI_BIG_ENDIAN 0 | |
183 | #elif defined(_WIN32) | |
184 | /* Win32 can currently always be assumed to be little endian */ | |
185 | #define BROTLI_LITTLE_ENDIAN 1 | |
186 | #define BROTLI_BIG_ENDIAN 0 | |
187 | #else | |
188 | #if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) | |
189 | #define BROTLI_BIG_ENDIAN 1 | |
190 | #else | |
191 | #define BROTLI_BIG_ENDIAN 0 | |
192 | #endif | |
193 | #define BROTLI_LITTLE_ENDIAN 0 | |
194 | #endif | |
195 | ||
196 | #if BROTLI_MODERN_COMPILER || __has_attribute(noinline) | |
197 | #define BROTLI_NOINLINE __attribute__ ((noinline)) | |
198 | #else | |
199 | #define BROTLI_NOINLINE | |
200 | #endif | |
201 | ||
202 | #if BROTLI_ASAN_BUILD && !defined(BROTLI_BUILD_PORTABLE) | |
203 | #define BROTLI_NO_ASAN __attribute__((no_sanitize("address"))) BROTLI_NOINLINE | |
204 | #else | |
205 | #define BROTLI_NO_ASAN | |
206 | #endif | |
207 | ||
208 | #define BROTLI_REPEAT(N, X) { \ | |
209 | if ((N & 1) != 0) {X;} \ | |
210 | if ((N & 2) != 0) {X; X;} \ | |
211 | if ((N & 4) != 0) {X; X; X; X;} \ | |
212 | } | |
213 | ||
214 | #if BROTLI_MODERN_COMPILER || defined(__llvm__) | |
215 | #if defined(BROTLI_TARGET_ARMV7) | |
216 | static BROTLI_INLINE unsigned BrotliRBit(unsigned input) { | |
217 | unsigned output; | |
218 | __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input)); | |
219 | return output; | |
220 | } | |
221 | #define BROTLI_RBIT(x) BrotliRBit(x) | |
222 | #endif /* armv7 */ | |
223 | #endif /* gcc || clang */ | |
224 | ||
225 | #if defined(BROTLI_TARGET_ARM) | |
226 | #define BROTLI_HAS_UBFX 1 | |
227 | #else | |
228 | #define BROTLI_HAS_UBFX 0 | |
229 | #endif | |
230 | ||
231 | #define BROTLI_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L) | |
232 | ||
233 | #define BROTLI_FREE(S, X) { \ | |
234 | S->free_func(S->memory_manager_opaque, X); \ | |
235 | X = NULL; \ | |
236 | } | |
237 | ||
238 | #define BROTLI_UNUSED(X) (void)(X) | |
239 | ||
240 | #endif /* BROTLI_DEC_PORT_H_ */ |