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