port.h revision db71549ac5008174ed4ada46476f0a74144bf2fc
1/* Copyright 2015 Google Inc. All Rights Reserved.
2
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6
7   http://www.apache.org/licenses/LICENSE-2.0
8
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14*/
15
16/* Macros for branch prediction. */
17
18#ifndef BROTLI_DEC_PORT_H_
19#define BROTLI_DEC_PORT_H_
20
21#include<assert.h>
22
23/* Compatibility with non-clang compilers. */
24#ifndef __has_builtin
25#define __has_builtin(x) 0
26#endif
27
28#ifndef __has_attribute
29#define __has_attribute(x) 0
30#endif
31
32#ifndef __has_feature
33#define __has_feature(x) 0
34#endif
35
36#define BROTLI_ASAN_BUILD __has_feature(address_sanitizer)
37
38/* Define "PREDICT_TRUE" and "PREDICT_FALSE" macros for capable compilers.
39
40To apply compiler hint, enclose the branching condition into macros, like this:
41
42  if (PREDICT_TRUE(zero == 0)) {
43    // main execution path
44  } else {
45    // compiler should place this code outside of main execution path
46  }
47
48OR:
49
50  if (PREDICT_FALSE(something_rare_or_unexpected_happens)) {
51    // compiler should place this code outside of main execution path
52  }
53
54*/
55#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \
56    (defined(__llvm__) && __has_builtin(__builtin_expect))
57#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
58#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
59#else
60#define PREDICT_FALSE(x) (x)
61#define PREDICT_TRUE(x) (x)
62#endif
63
64/* IS_CONSTANT macros returns true for compile-time constant expressions. */
65#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \
66    (defined(__llvm__) && __has_builtin(__builtin_constant_p))
67#define IS_CONSTANT(x) __builtin_constant_p(x)
68#else
69#define IS_CONSTANT(x) 0
70#endif
71
72#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \
73    (defined(__llvm__) && __has_attribute(always_inline))
74#define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline))
75#else
76#define ATTRIBUTE_ALWAYS_INLINE
77#endif
78
79#ifndef _MSC_VER
80#if defined(__cplusplus) || !defined(__STRICT_ANSI__) \
81    || __STDC_VERSION__ >= 199901L
82#define BROTLI_INLINE inline ATTRIBUTE_ALWAYS_INLINE
83#else
84#define BROTLI_INLINE
85#endif
86#else  /* _MSC_VER */
87#define BROTLI_INLINE __forceinline
88#endif  /* _MSC_VER */
89
90#ifdef BROTLI_DECODE_DEBUG
91#define BROTLI_DCHECK(x) assert(x)
92#else
93#define BROTLI_DCHECK(x)
94#endif
95
96#if (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || \
97     defined(__PPC64__))
98#define BROTLI_64_BITS 1
99#define BROTLI_PRELOAD_SYMBOLS 1
100#else
101#define BROTLI_64_BITS 0
102#define BROTLI_PRELOAD_SYMBOLS 0
103#endif
104
105#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
106#define BROTLI_LITTLE_ENDIAN 1
107#elif defined(_WIN32)
108/* Win32 can currently always be assumed to be little endian */
109#define BROTLI_LITTLE_ENDIAN 1
110#else
111#define BROTLI_LITTLE_ENDIAN 0
112#endif
113
114#if (BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN)
115#define BROTLI_64_BITS_LITTLE_ENDIAN 1
116#else
117#define BROTLI_64_BITS_LITTLE_ENDIAN 0
118#endif
119
120#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || \
121    (defined(__llvm__) && __has_attribute(noinline))
122#define BROTLI_NOINLINE __attribute__ ((noinline))
123#else
124#define BROTLI_NOINLINE
125#endif
126
127#if BROTLI_ASAN_BUILD
128#define BROTLI_NO_ASAN __attribute__((no_sanitize("address"))) BROTLI_NOINLINE
129#else
130#define BROTLI_NO_ASAN
131#endif
132
133#define BROTLI_REPEAT(N, X) { \
134  if ((N & 1) != 0) {X;} \
135  if ((N & 2) != 0) {X; X;} \
136  if ((N & 4) != 0) {X; X; X; X;} \
137}
138
139#if (__GNUC__ > 2) || defined(__llvm__)
140#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7))
141static BROTLI_INLINE unsigned BrotliRBit(unsigned input) {
142  unsigned output;
143  __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
144  return output;
145}
146#define BROTLI_RBIT(x) BrotliRBit(x)
147#endif  /* armv7 */
148#endif  /* gcc || clang */
149
150#endif  /* BROTLI_DEC_PORT_H_ */
151