1212 * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
1313 * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
1414 * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
15- * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
16- read and overlapping memcpy; this reduces decompression speed by 5%
1715 * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
16+ * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read
17+ optimizations (mainly for testing purposes)
1818 * BROTLI_DEBUG dumps file name and line number when decoder detects stream
1919 or memory error
2020 * BROTLI_ENABLE_LOG enables asserts and dumps various state information
21+ * BROTLI_ENABLE_DUMP overrides default "dump" behaviour
2122*/
2223
2324#ifndef BROTLI_COMMON_PLATFORM_H_
4041#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN
4142#endif
4243
43- #if BROTLI_MSVC_VERSION_CHECK(12 , 0, 0)
44+ #if BROTLI_MSVC_VERSION_CHECK(18 , 0, 0)
4445#include < intrin.h>
4546#endif
4647
@@ -156,24 +157,6 @@ To apply compiler hint, enclose the branching condition into macros, like this:
156157#define BROTLI_NOINLINE
157158#endif
158159
159- /* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */
160- #if !defined(BROTLI_INTERNAL)
161- #if defined(_WIN32) || defined(__CYGWIN__)
162- #define BROTLI_INTERNAL
163- #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
164- BROTLI_TI_VERSION_CHECK (8 , 0 , 0 ) || \
165- BROTLI_INTEL_VERSION_CHECK(16 , 0 , 0 ) || \
166- BROTLI_ARM_VERSION_CHECK(4 , 1 , 0 ) || \
167- BROTLI_IBM_VERSION_CHECK(13 , 1 , 0 ) || \
168- BROTLI_SUNPRO_VERSION_CHECK(5 , 11 , 0 ) || \
169- (BROTLI_TI_VERSION_CHECK(7 , 3 , 0 ) && \
170- defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))
171- #define BROTLI_INTERNAL __attribute__ ((visibility (" hidden" )))
172- #else
173- #define BROTLI_INTERNAL
174- #endif
175- #endif
176-
177160/* <<< <<< <<< end of hedley macros. */
178161
179162#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \
@@ -226,15 +209,24 @@ To apply compiler hint, enclose the branching condition into macros, like this:
226209#define BROTLI_TARGET_RISCV64
227210#endif
228211
212+ #if defined(__loongarch_lp64)
213+ #define BROTLI_TARGET_LOONGARCH64
214+ #endif
215+
216+ #if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
217+ defined (BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \
218+ defined(BROTLI_TARGET_LOONGARCH64)
219+ #define BROTLI_TARGET_64_BITS 1
220+ #else
221+ #define BROTLI_TARGET_64_BITS 0
222+ #endif
223+
229224#if defined(BROTLI_BUILD_64_BIT)
230225#define BROTLI_64_BITS 1
231226#elif defined(BROTLI_BUILD_32_BIT)
232227#define BROTLI_64_BITS 0
233- #elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
234- defined (BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
235- #define BROTLI_64_BITS 1
236228#else
237- #define BROTLI_64_BITS 0
229+ #define BROTLI_64_BITS BROTLI_TARGET_64_BITS
238230#endif
239231
240232#if (BROTLI_64_BITS)
@@ -278,18 +270,19 @@ To apply compiler hint, enclose the branching condition into macros, like this:
278270#undef BROTLI_X_BIG_ENDIAN
279271#endif
280272
281- #if defined(BROTLI_BUILD_PORTABLE )
282- #define BROTLI_ALIGNED_READ (!!1 )
283- #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
273+ #if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST )
274+ #define BROTLI_UNALIGNED_READ_FAST (!!0 )
275+ #elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
284276 defined (BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
285- defined(BROTLI_TARGET_RISCV64)
286- /* Allow unaligned read only for white-listed CPUs. */
287- #define BROTLI_ALIGNED_READ (!!0 )
277+ defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64)
278+ /* These targets are known to generate efficient code for unaligned reads
279+ * (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd
280+ * together). */
281+ #define BROTLI_UNALIGNED_READ_FAST (!!1 )
288282#else
289- #define BROTLI_ALIGNED_READ (!!1 )
283+ #define BROTLI_UNALIGNED_READ_FAST (!!0 )
290284#endif
291285
292- #if BROTLI_ALIGNED_READ
293286/* Portable unaligned memory access: read / write values via memcpy. */
294287static BROTLI_INLINE uint16_t BrotliUnalignedRead16 (const void * p) {
295288 uint16_t t;
@@ -309,75 +302,6 @@ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
309302static BROTLI_INLINE void BrotliUnalignedWrite64 (void * p, uint64_t v) {
310303 memcpy (p, &v, sizeof v);
311304}
312- #else /* BROTLI_ALIGNED_READ */
313- /* Unaligned memory access is allowed: just cast pointer to requested type. */
314- #if BROTLI_SANITIZED
315- /* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
316- AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
317- will miss a bug if 08 is the first unaddressable byte.
318- ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
319- miss a race between this access and some other accesses to 08.
320- MemorySanitizer will correctly propagate the shadow on unaligned stores
321- and correctly report bugs on unaligned loads, but it may not properly
322- update and report the origin of the uninitialized memory.
323- For all three tools, replacing an unaligned access with a tool-specific
324- callback solves the problem. */
325- #if defined(__cplusplus)
326- extern " C" {
327- #endif /* __cplusplus */
328- uint16_t __sanitizer_unaligned_load16 (const void * p);
329- uint32_t __sanitizer_unaligned_load32 (const void * p);
330- uint64_t __sanitizer_unaligned_load64 (const void * p);
331- void __sanitizer_unaligned_store64 (void * p, uint64_t v);
332- #if defined(__cplusplus)
333- } /* extern "C" */
334- #endif /* __cplusplus */
335- #define BrotliUnalignedRead16 __sanitizer_unaligned_load16
336- #define BrotliUnalignedRead32 __sanitizer_unaligned_load32
337- #define BrotliUnalignedRead64 __sanitizer_unaligned_load64
338- #define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
339- #else /* BROTLI_SANITIZED */
340- static BROTLI_INLINE uint16_t BrotliUnalignedRead16 (const void * p) {
341- return *(const uint16_t *)p;
342- }
343- static BROTLI_INLINE uint32_t BrotliUnalignedRead32 (const void * p) {
344- return *(const uint32_t *)p;
345- }
346- #if (BROTLI_64_BITS)
347- static BROTLI_INLINE uint64_t BrotliUnalignedRead64 (const void * p) {
348- return *(const uint64_t *)p;
349- }
350- static BROTLI_INLINE void BrotliUnalignedWrite64 (void * p, uint64_t v) {
351- *(uint64_t *)p = v;
352- }
353- #else /* BROTLI_64_BITS */
354- /* Avoid emitting LDRD / STRD, which require properly aligned address. */
355- /* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
356-
357- #if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
358- typedef BROTLI_ALIGNED (1 ) uint64_t brotli_unaligned_uint64_t;
359-
360- static BROTLI_INLINE uint64_t BrotliUnalignedRead64 (const void * p) {
361- return (uint64_t ) ((const brotli_unaligned_uint64_t *) p)[0 ];
362- }
363- static BROTLI_INLINE void BrotliUnalignedWrite64 (void * p, uint64_t v) {
364- brotli_unaligned_uint64_t * dwords = (brotli_unaligned_uint64_t *) p;
365- dwords[0 ] = (brotli_unaligned_uint64_t ) v;
366- }
367- #else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
368- static BROTLI_INLINE uint64_t BrotliUnalignedRead64 (const void * p) {
369- uint64_t v;
370- memcpy (&v, p, sizeof (uint64_t ));
371- return v;
372- }
373-
374- static BROTLI_INLINE void BrotliUnalignedWrite64 (void * p, uint64_t v) {
375- memcpy (p, &v, sizeof (uint64_t ));
376- }
377- #endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
378- #endif /* BROTLI_64_BITS */
379- #endif /* BROTLI_SANITIZED */
380- #endif /* BROTLI_ALIGNED_READ */
381305
382306#if BROTLI_LITTLE_ENDIAN
383307/* Straight endianness. Just read / write values. */
@@ -453,6 +377,16 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
453377}
454378#endif /* BROTLI_LITTLE_ENDIAN */
455379
380+ static BROTLI_INLINE void * BROTLI_UNALIGNED_LOAD_PTR (const void * p) {
381+ void * v;
382+ memcpy (&v, p, sizeof (void *));
383+ return v;
384+ }
385+
386+ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR (void * p, const void * v) {
387+ memcpy (p, &v, sizeof (void *));
388+ }
389+
456390/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */
457391#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \
458392 BROTLI_INTEL_VERSION_CHECK (16 , 0 , 0 )
@@ -474,22 +408,34 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
474408#endif
475409
476410#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
411+ #define BROTLI_ENABLE_DUMP_DEFAULT 1
477412#define BROTLI_DCHECK (x ) assert (x)
413+ #else
414+ #define BROTLI_ENABLE_DUMP_DEFAULT 0
415+ #define BROTLI_DCHECK (x )
416+ #endif
417+
418+ #if !defined(BROTLI_ENABLE_DUMP)
419+ #define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT
420+ #endif
421+
422+ #if BROTLI_ENABLE_DUMP
478423static BROTLI_INLINE void BrotliDump (const char * f, int l, const char * fn) {
479424 fprintf (stderr, " %s:%d (%s)\n " , f, l, fn);
480425 fflush (stderr);
481426}
482427#define BROTLI_DUMP () BrotliDump(__FILE__, __LINE__, __FUNCTION__)
483428#else
484- #define BROTLI_DCHECK (x )
485429#define BROTLI_DUMP () (void )(0 )
486430#endif
487431
488- /* TODO: add appropriate icc/sunpro/arm/ibm/ti checks. */
432+ /* BrotliRBit assumes brotli_reg_t fits native CPU register type. */
433+ #if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)
434+ /* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */
489435#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
490436 !defined (BROTLI_BUILD_NO_RBIT)
491437#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
492- /* TODO: detect ARMv6T2 and enable this code for it. */
438+ /* TODO(eustas) : detect ARMv6T2 and enable this code for it. */
493439static BROTLI_INLINE brotli_reg_t BrotliRBit (brotli_reg_t input) {
494440 brotli_reg_t output;
495441 __asm__ (" rbit %0, %1\n " : " =r" (output) : " r" (input));
@@ -498,15 +444,14 @@ static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
498444#define BROTLI_RBIT (x ) BrotliRBit(x)
499445#endif /* armv7 / armv8 */
500446#endif /* gcc || clang */
447+ #endif /* brotli_reg_t is native */
501448#if !defined(BROTLI_RBIT)
502449static BROTLI_INLINE void BrotliRBit (void ) { /* Should break build if used. */ }
503450#endif /* BROTLI_RBIT */
504451
505- #define BROTLI_REPEAT (N, X ) { \
506- if ((N & 1 ) != 0 ) {X;} \
507- if ((N & 2 ) != 0 ) {X; X;} \
508- if ((N & 4 ) != 0 ) {X; X; X; X;} \
509- }
452+ #define BROTLI_REPEAT_4 (X ) {X; X; X; X;}
453+ #define BROTLI_REPEAT_5 (X ) {X; X; X; X; X;}
454+ #define BROTLI_REPEAT_6 (X ) {X; X; X; X; X; X;}
510455
511456#define BROTLI_UNUSED (X ) (void )(X)
512457
@@ -529,7 +474,7 @@ BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)
529474#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \
530475 BROTLI_INTEL_VERSION_CHECK (16 , 0 , 0 )
531476#define BROTLI_TZCNT64 __builtin_ctzll
532- #elif BROTLI_MSVC_VERSION_CHECK(12 , 0, 0)
477+ #elif BROTLI_MSVC_VERSION_CHECK(18 , 0, 0)
533478#if defined(BROTLI_TARGET_X64)
534479#define BROTLI_TZCNT64 _tzcnt_u64
535480#else /* BROTLI_TARGET_X64 */
@@ -546,7 +491,7 @@ static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {
546491#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \
547492 BROTLI_INTEL_VERSION_CHECK (16 , 0 , 0 )
548493#define BROTLI_BSR32 (x ) (31u ^ (uint32_t )__builtin_clz(x))
549- #elif BROTLI_MSVC_VERSION_CHECK(12 , 0, 0)
494+ #elif BROTLI_MSVC_VERSION_CHECK(18 , 0, 0)
550495static BROTLI_INLINE uint32_t BrotliBsr32Msvc (uint32_t x) {
551496 unsigned long msb;
552497 _BitScanReverse (&msb, x);
@@ -571,6 +516,8 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
571516 BROTLI_UNUSED (&BROTLI_UNALIGNED_LOAD32LE);
572517 BROTLI_UNUSED (&BROTLI_UNALIGNED_LOAD64LE);
573518 BROTLI_UNUSED (&BROTLI_UNALIGNED_STORE64LE);
519+ BROTLI_UNUSED (&BROTLI_UNALIGNED_LOAD_PTR);
520+ BROTLI_UNUSED (&BROTLI_UNALIGNED_STORE_PTR);
574521 BROTLI_UNUSED (&BrotliRBit);
575522 BROTLI_UNUSED (&brotli_min_double);
576523 BROTLI_UNUSED (&brotli_max_double);
@@ -586,7 +533,7 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
586533 BROTLI_UNUSED (&brotli_max_uint8_t );
587534 BROTLI_UNUSED (&BrotliDefaultAllocFunc);
588535 BROTLI_UNUSED (&BrotliDefaultFreeFunc);
589- #if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
536+ #if BROTLI_ENABLE_DUMP
590537 BROTLI_UNUSED (&BrotliDump);
591538#endif
592539}
0 commit comments