1/* 2* This is where we define macros used across upb. 3* 4* All of these macros are undef'd in port_undef.inc to avoid leaking them to 5* users. 6* 7* The correct usage is: 8* 9* #include "upb/foobar.h" 10* #include "upb/baz.h" 11* 12* // MUST be last included header. 13* #include "upb/port_def.inc" 14* 15* // Code for this file. 16* // <...> 17* 18* // Can be omitted for .c files, required for .h. 19* #include "upb/port_undef.inc" 20* 21* This file is private and must not be included by users! 22*/ 23 24#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ 25 (defined(__cplusplus) && __cplusplus >= 201103L) || \ 26 (defined(_MSC_VER) && _MSC_VER >= 1900)) 27#error upb requires C99 or C++11 or MSVC >= 2015. 28#endif 29 30#include <stdint.h> 31#include <stddef.h> 32 33#if UINTPTR_MAX == 0xffffffff 34#define UPB_SIZE(size32, size64) size32 35#else 36#define UPB_SIZE(size32, size64) size64 37#endif 38 39/* If we always read/write as a consistent type to each address, this shouldn't 40 * violate aliasing. 41 */ 42#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) 43 44#define UPB_READ_ONEOF(msg, fieldtype, offset, case_offset, case_val, default) \ 45 *UPB_PTR_AT(msg, case_offset, int) == case_val \ 46 ? *UPB_PTR_AT(msg, offset, fieldtype) \ 47 : default 48 49#define UPB_WRITE_ONEOF(msg, fieldtype, offset, value, case_offset, case_val) \ 50 *UPB_PTR_AT(msg, case_offset, int) = case_val; \ 51 *UPB_PTR_AT(msg, offset, fieldtype) = value; 52 53#define UPB_MAPTYPE_STRING 0 54 55/* UPB_INLINE: inline if possible, emit standalone code if required. */ 56#ifdef __cplusplus 57#define UPB_INLINE inline 58#elif defined (__GNUC__) || defined(__clang__) 59#define UPB_INLINE static __inline__ 60#else 61#define UPB_INLINE static 62#endif 63 64#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) 65#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) 66#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, 16) 67#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member) 68 69/* Hints to the compiler about likely/unlikely branches. */ 70#if defined (__GNUC__) || defined(__clang__) 71#define UPB_LIKELY(x) __builtin_expect((x),1) 72#define UPB_UNLIKELY(x) __builtin_expect((x),0) 73#else 74#define UPB_LIKELY(x) (x) 75#define UPB_UNLIKELY(x) (x) 76#endif 77 78/* Macros for function attributes on compilers that support them. */ 79#ifdef __GNUC__ 80#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) 81#define UPB_NOINLINE __attribute__((noinline)) 82#define UPB_NORETURN __attribute__((__noreturn__)) 83#elif defined(_MSC_VER) 84#define UPB_NOINLINE 85#define UPB_FORCEINLINE 86#define UPB_NORETURN __declspec(noreturn) 87#else /* !defined(__GNUC__) */ 88#define UPB_FORCEINLINE 89#define UPB_NOINLINE 90#define UPB_NORETURN 91#endif 92 93#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) 94#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) 95 96#define UPB_UNUSED(var) (void)var 97 98/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. 99 */ 100#ifdef NDEBUG 101#ifdef __GNUC__ 102#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable() 103#elif defined _MSC_VER 104#define UPB_ASSUME(expr) if (!(expr)) __assume(0) 105#else 106#define UPB_ASSUME(expr) do {} while (false && (expr)) 107#endif 108#else 109#define UPB_ASSUME(expr) assert(expr) 110#endif 111 112/* UPB_ASSERT(): in release mode, we use the expression without letting it be 113 * evaluated. This prevents "unused variable" warnings. */ 114#ifdef NDEBUG 115#define UPB_ASSERT(expr) do {} while (false && (expr)) 116#else 117#define UPB_ASSERT(expr) assert(expr) 118#endif 119 120#if defined(__GNUC__) || defined(__clang__) 121#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0) 122#else 123#define UPB_UNREACHABLE() do { assert(0); } while(0) 124#endif 125 126/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */ 127#ifdef __APPLE__ 128#define UPB_SETJMP(buf) _setjmp(buf) 129#define UPB_LONGJMP(buf, val) _longjmp(buf, val) 130#else 131#define UPB_SETJMP(buf) setjmp(buf) 132#define UPB_LONGJMP(buf, val) longjmp(buf, val) 133#endif 134 135/* Configure whether fasttable is switched on or not. *************************/ 136 137#if defined(__x86_64__) && defined(__GNUC__) 138#define UPB_FASTTABLE_SUPPORTED 1 139#else 140#define UPB_FASTTABLE_SUPPORTED 0 141#endif 142 143/* define UPB_ENABLE_FASTTABLE to force fast table support. 144 * This is useful when we want to ensure we are really getting fasttable, 145 * for example for testing or benchmarking. */ 146#if defined(UPB_ENABLE_FASTTABLE) 147#if !UPB_FASTTABLE_SUPPORTED 148#error fasttable is x86-64 + Clang/GCC only 149#endif 150#define UPB_FASTTABLE 1 151/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. 152 * This is useful for releasing code that might be used on multiple platforms, 153 * for example the PHP or Ruby C extensions. */ 154#elif defined(UPB_TRY_ENABLE_FASTTABLE) 155#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED 156#else 157#define UPB_FASTTABLE 0 158#endif 159 160/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully 161 * degrade to non-fasttable if we are using UPB_TRY_ENABLE_FASTTABLE. */ 162#if !UPB_FASTTABLE && defined(UPB_TRY_ENABLE_FASTTABLE) 163#define UPB_FASTTABLE_INIT(...) 164#else 165#define UPB_FASTTABLE_INIT(...) __VA_ARGS__ 166#endif 167 168#undef UPB_FASTTABLE_SUPPORTED 169 170/* ASAN poisoning (for arena) *************************************************/ 171 172#if defined(__SANITIZE_ADDRESS__) 173#define UPB_ASAN 1 174#ifdef __cplusplus 175extern "C" { 176#endif 177void __asan_poison_memory_region(void const volatile *addr, size_t size); 178void __asan_unpoison_memory_region(void const volatile *addr, size_t size); 179#ifdef __cplusplus 180} /* extern "C" */ 181#endif 182#define UPB_POISON_MEMORY_REGION(addr, size) \ 183 __asan_poison_memory_region((addr), (size)) 184#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ 185 __asan_unpoison_memory_region((addr), (size)) 186#else 187#define UPB_ASAN 0 188#define UPB_POISON_MEMORY_REGION(addr, size) \ 189 ((void)(addr), (void)(size)) 190#define UPB_UNPOISON_MEMORY_REGION(addr, size) \ 191 ((void)(addr), (void)(size)) 192#endif 193