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