• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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