xref: /aosp_15_r20/external/emboss/runtime/cpp/emboss_defines.h (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1 // Copyright 2019 Google LLC
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 //     https://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 // This header contains #defines that are used to control Emboss's generated
16 // code.
17 //
18 // These #defines are global, and *must* be defined the same way in every
19 // translation unit.  In particular, if you use `-D` (or your compiler's
20 // equivalent) to define some of them on the command line, you *must* pass the
21 // *exact* same definition when compiling *every* file that #includes any
22 // Emboss-generated or Emboss-related file, directly or indirectly.  Failure to
23 // do so will lead to ODR violations and strange behavior.
24 //
25 // Rather than using the command line, the Emboss authors recommend that you
26 // insert an #include of a custom site_defines.h between the two markers below.
27 //
28 // If you are using [Copybara][1] to import Emboss into your environment, you
29 // can use a transform like:
30 //
31 //     core.replace(
32 //         before = '${start_of_line}// #include "MY_SITE_DEFINES.h"',
33 //         after = '${start_of_line}#include "MY_SITE_DEFINES.h"',
34 //         paths = ['public/emboss_defines.h'],
35 //         regex_groups = {
36 //             'start_of_line': '^',
37 //         },
38 //     ),
39 //
40 // [1]: https://github.com/google/copybara
41 //
42 // If you are using [Bazel][2], be sure to add a dependency from the
43 // //public:cpp_utils target to a target exporting your custom header:
44 //
45 //     core.replace(
46 //         before = '${leading_whitespace}# "//MY_SITE_DEFINES:TARGET",',
47 //         after = '${leading_whitespace}"//MY_SITE_DEFINES:TARGET",',
48 //         paths = ['public/BUILD'],
49 //         regex_groups = {
50 //             'leading_whitespace': '^ *',
51 //         },
52 //     ),
53 //
54 // [2]: https://bazel.build
55 #ifndef EMBOSS_RUNTIME_CPP_EMBOSS_DEFINES_H_
56 #define EMBOSS_RUNTIME_CPP_EMBOSS_DEFINES_H_
57 
58 #include <cassert>
59 
60 // START INSERT_INCLUDE_SITE_DEFINES_HERE
61 // #include "MY_SITE_DEFINES.h"
62 // END INSERT_INCLUDE_SITE_DEFINES_HERE
63 
64 // EMBOSS_CHECK should abort the program if the given expression evaluates to
65 // false.
66 //
67 // By default, checks are only enabled on non-NDEBUG builds.  (Note that all
68 // translation units MUST be built with the same value of NDEBUG!)
69 #if !defined(EMBOSS_CHECK)
70 #define EMBOSS_CHECK(x) assert((x))
71 #define EMBOSS_CHECK_ABORTS (!(NDEBUG))
72 #endif  // !defined(EMBOSS_CHECK)
73 
74 #if !defined(EMBOSS_CHECK_ABORTS)
75 #error "Custom EMBOSS_CHECK without EMBOSS_CHECK_ABORTS."
76 #endif  // !defined(EMBOSS_CHECK_ABORTS)
77 
78 #if !defined(EMBOSS_CHECK_LE)
79 #define EMBOSS_CHECK_LE(x, y) EMBOSS_CHECK((x) <= (y))
80 #endif  // !defined(EMBOSS_CHECK_LE)
81 
82 #if !defined(EMBOSS_CHECK_LT)
83 #define EMBOSS_CHECK_LT(x, y) EMBOSS_CHECK((x) < (y))
84 #endif  // !defined(EMBOSS_CHECK_LT)
85 
86 #if !defined(EMBOSS_CHECK_GE)
87 #define EMBOSS_CHECK_GE(x, y) EMBOSS_CHECK((x) >= (y))
88 #endif  // !defined(EMBOSS_CHECK_GE)
89 
90 #if !defined(EMBOSS_CHECK_GT)
91 #define EMBOSS_CHECK_GT(x, y) EMBOSS_CHECK((x) > (y))
92 #endif  // !defined(EMBOSS_CHECK_GT)
93 
94 #if !defined(EMBOSS_CHECK_EQ)
95 #define EMBOSS_CHECK_EQ(x, y) EMBOSS_CHECK((x) == (y))
96 #endif  // !defined(EMBOSS_CHECK_EQ)
97 
98 #if !defined(EMBOSS_CHECK_NE)
99 #define EMBOSS_CHECK_NE(x, y) EMBOSS_CHECK((x) == (y))
100 #endif  // !defined(EMBOSS_CHECK_NE)
101 
102 // The EMBOSS_DCHECK macros, by default, work the same way as EMBOSS_CHECK;
103 // EMBOSS_DCHECK is used as an assert() for logic embedded in Emboss, where
104 // EMBOSS_CHECK is used to check preconditions on application logic.  Depending
105 // on how much you trust the correctness of Emboss itself, you may wish to
106 // disable EMBOSS_DCHECK in situations where you do not disable EMBOSS_CHECK.
107 #if !defined(EMBOSS_DCHECK)
108 #define EMBOSS_DCHECK(x) assert((x))
109 #define EMBOSS_DCHECK_ABORTS (!(NDEBUG))
110 #endif  // !defined(EMBOSS_DCHECK)
111 
112 #if !defined(EMBOSS_DCHECK_ABORTS)
113 #error "Custom EMBOSS_DCHECK without EMBOSS_DCHECK_ABORTS."
114 #endif  // !defined(EMBOSS_DCHECK_ABORTS)
115 
116 #if !defined(EMBOSS_DCHECK_LE)
117 #define EMBOSS_DCHECK_LE(x, y) EMBOSS_DCHECK((x) <= (y))
118 #endif  // !defined(EMBOSS_DCHECK_LE)
119 
120 #if !defined(EMBOSS_DCHECK_LT)
121 #define EMBOSS_DCHECK_LT(x, y) EMBOSS_DCHECK((x) < (y))
122 #endif  // !defined(EMBOSS_DCHECK_LT)
123 
124 #if !defined(EMBOSS_DCHECK_GE)
125 #define EMBOSS_DCHECK_GE(x, y) EMBOSS_DCHECK((x) >= (y))
126 #endif  // !defined(EMBOSS_DCHECK_GE)
127 
128 #if !defined(EMBOSS_DCHECK_GT)
129 #define EMBOSS_DCHECK_GT(x, y) EMBOSS_DCHECK((x) > (y))
130 #endif  // !defined(EMBOSS_DCHECK_GT)
131 
132 #if !defined(EMBOSS_DCHECK_EQ)
133 #define EMBOSS_DCHECK_EQ(x, y) EMBOSS_DCHECK((x) == (y))
134 #endif  // !defined(EMBOSS_DCHECK_EQ)
135 
136 #if !defined(EMBOSS_DCHECK_NE)
137 #define EMBOSS_DCHECK_NE(x, y) EMBOSS_DCHECK((x) == (y))
138 #endif  // !defined(EMBOSS_DCHECK_NE)
139 
140 // Technically, the mapping from pointers to integers is implementation-defined,
141 // but the standard states "[ Note: It is intended to be unsurprising to those
142 // who know the addressing structure of the underlying machine. - end note ],"
143 // so this should be a reasonably safe way to check that a pointer is aligned.
144 #if !defined(EMBOSS_DCHECK_POINTER_ALIGNMENT)
145 #define EMBOSS_DCHECK_POINTER_ALIGNMENT(p, align, offset)                  \
146   EMBOSS_DCHECK_EQ(reinterpret_cast</**/ ::std::uintptr_t>((p)) % (align), \
147                    (static_cast</**/ ::std::uintptr_t>((offset))))
148 #endif  // !defined(EMBOSS_DCHECK_POINTER_ALIGNMENT)
149 
150 #if !defined(EMBOSS_CHECK_POINTER_ALIGNMENT)
151 #define EMBOSS_CHECK_POINTER_ALIGNMENT(p, align, offset)                  \
152   EMBOSS_CHECK_EQ(reinterpret_cast</**/ ::std::uintptr_t>((p)) % (align), \
153                   static_cast</**/ ::std::uintptr_t>((offset)))
154 #endif  // !defined(EMBOSS_CHECK_POINTER_ALIGNMENT)
155 
156 // EMBOSS_NO_OPTIMIZATIONS is used to turn off all system-specific
157 // optimizations.  This is mostly intended for testing, but could be used if
158 // optimizations are causing problems.
159 #if !defined(EMBOSS_NO_OPTIMIZATIONS)
160 #if defined(__GNUC__)  // GCC and "compatible" compilers, such as Clang.
161 
162 // GCC, Clang, and ICC only support two's-complement systems, so it is safe to
163 // assume two's-complement for those systems.  In particular, this means that
164 // static_cast<int>() will treat its argument as a two's-complement bit pattern,
165 // which means that it is reasonable to static_cast<int>(some_unsigned_value).
166 //
167 // TODO(bolms): Are there actually any non-archaic systems that use any integer
168 // types other than 2's-complement?
169 #if !defined(EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT)
170 #define EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT 1
171 #endif  // !defined(EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT)
172 
173 #if !defined(__INTEL_COMPILER)
174 // On systems with known host byte order, Emboss can always use memcpy to safely
175 // and relatively efficiently read and write values from and to memory.
176 // However, memcpy cannot assume that its pointers are aligned.  On common
177 // platforms, particularly x86, this almost never matters; however, on some
178 // systems this can add considerable overhead, as memcpy must either perform
179 // byte-by-byte copies or perform tests to determine pointer alignment and then
180 // dispatch to alignment-specific code.
181 //
182 // Platforms with no alignment restrictions:
183 //
184 // * x86 (except for a few SSE instructions like movdqa: see
185 //   http://pzemtsov.github.io/2016/11/06/bug-story-alignment-on-x86.html)
186 // * ARM systems with ARMv6 and later ISAs
187 // * High-end POWER-based systems
188 // * POWER-based systems with an alignment exception handler installed (but note
189 //   that emulated unaligned reads are *very* slow)
190 //
191 // Platforms with alignment restrictions:
192 //
193 // * MicroBlaze
194 // * Emscripten
195 // * Low-end bare-metal POWER-based systems
196 // * ARM systems with ARMv5 and earlier ISAs
197 // * x86 with the AC bit of EEFLAGS enabled (but note that this is never enabled
198 //   on any normal system, and, e.g., you will get crashes in glibc if you try
199 //   to enable it)
200 //
201 // The naive solution is to reinterpret_cast to a type like uint32_t, then read
202 // or write through that pointer; however, this can easily run afoul of C++'s
203 // type aliasing rules and result in undefined behavior.
204 //
205 // On GCC, there is a solution to this: use the "__may_alias__" type attribute,
206 // which essentially forces the type to have the same aliasing rules as char;
207 // i.e., it is safe to read and write through a pointer derived from
208 // reinterpret_cast<T __attribute__((__may_alias__)) *>, just as it is safe to
209 // read and write through a pointer derived from reinterpret_cast<char *>.
210 //
211 // Note that even though ICC pretends to be compatible with GCC by defining
212 // __GNUC__, it does *not* appear to support the __may_alias__ attribute.
213 // (TODO(bolms): verify this if/when Emboss explicitly supports ICC.)
214 //
215 // Note the lack of parentheses around 't' in the expansion: unfortunately,
216 // GCC's attribute syntax disallows parentheses in that particular position.
217 #if !defined(EMBOSS_ALIAS_SAFE_POINTER_CAST)
218 #define EMBOSS_ALIAS_SAFE_POINTER_CAST(t, x) \
219   reinterpret_cast<t __attribute__((__may_alias__)) *>((x))
220 #endif  // !defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE)
221 #endif  // !defined(__INTEL_COMPILER)
222 
223 // GCC supports __BYTE_ORDER__ of __ORDER_LITTLE_ENDIAN__, __ORDER_BIG_ENDIAN__,
224 // and __ORDER_PDP_ENDIAN__.  Since all available test systems are
225 // __ORDER_LITTLE_ENDIAN__, only little-endian hosts get optimized code paths;
226 // however, big-endian support ought to be trivial to add.
227 //
228 // There are no plans to support PDP-endian systems.
229 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
230 // EMBOSS_LITTLE_ENDIAN_TO_NATIVE and EMBOSS_BIG_ENDIAN_TO_NATIVE can be used to
231 // fix up integers after a little- or big-endian value has been memcpy'ed into
232 // them.
233 //
234 // On little-endian systems, no fixup is needed for little-endian sources, but
235 // big-endian sources require a byte swap.
236 #if !defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE)
237 #define EMBOSS_LITTLE_ENDIAN_TO_NATIVE(x) (x)
238 #endif  // !defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE)
239 
240 #if !defined(EMBOSS_NATIVE_TO_LITTLE_ENDIAN)
241 #define EMBOSS_NATIVE_TO_LITTLE_ENDIAN(x) (x)
242 #endif  // !defined(EMBOSS_NATIVE_TO_LITTLE_ENDIAN)
243 
244 #if !defined(EMBOSS_BIG_ENDIAN_TO_NATIVE)
245 #define EMBOSS_BIG_ENDIAN_TO_NATIVE(x) (::emboss::support::ByteSwap((x)))
246 #endif  // !defined(EMBOSS_BIG_ENDIAN_TO_NATIVE)
247 
248 #if !defined(EMBOSS_NATIVE_TO_BIG_ENDIAN)
249 #define EMBOSS_NATIVE_TO_BIG_ENDIAN(x) (::emboss::support::ByteSwap((x)))
250 #endif  // !defined(EMBOSS_NATIVE_TO_BIG_ENDIAN)
251 
252 // TODO(bolms): Find a way to test on a big-endian architecture, and add support
253 // for __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
254 #endif  // __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
255 
256 // Prior to version 4.8, __builtin_bswap16 was not available on all platforms.
257 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624
258 //
259 // Clang pretends to be an earlier GCC, but does support __builtin_bswap16.
260 // Clang recommends using __has_builtin(__builtin_bswap16), but unfortunately
261 // that fails to compile on GCC, even with defined(__has_builtin) &&
262 // __has_builtin(__builtin_bswap16), so instead Emboss just checks for
263 // defined(__clang__).
264 #if !defined(EMBOSS_BYTESWAP16)
265 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || defined(__clang__)
266 #define EMBOSS_BYTESWAP16(x) __builtin_bswap16((x))
267 #endif  // __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
268 #endif  // !defined(EMBOSS_BYTESWAP16)
269 
270 #if !defined(EMBOSS_BYTESWAP32)
271 #define EMBOSS_BYTESWAP32(x) __builtin_bswap32((x))
272 #endif  // !defined(EMBOSS_BYTESWAP32)
273 
274 #if !defined(EMBOSS_BYTESWAP64)
275 #define EMBOSS_BYTESWAP64(x) __builtin_bswap64((x))
276 #endif  // !defined(EMBOSS_BYTESWAP64)
277 
278 #endif  // defined(__GNUC__)
279 #endif  // !defined(EMBOSS_NO_OPTIMIZATIONS)
280 
281 #if !defined(EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT)
282 #define EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT 0
283 #endif  // !defined(EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT)
284 
285 #endif  // EMBOSS_RUNTIME_CPP_EMBOSS_DEFINES_H_
286