• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC.  All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8/*
9 * This is where we define internal portability macros used across upb.
10 *
11 * All of these macros are undef'd in undef.inc to avoid leaking them to users.
12 *
13 * The correct usage is:
14 *
15 *   #include "upb/foobar.h"
16 *   #include "upb/baz.h"
17 *
18 *   // MUST be last included header.
19 *   #include "upb/port/def.inc"
20 *
21 *   // Code for this file.
22 *   // <...>
23 *
24 *   // Can be omitted for .c files, required for .h.
25 *   #include "upb/port/undef.inc"
26 *
27 * This file is private and must not be included by users!
28 */
29
30#if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
31      (defined(__cplusplus) && __cplusplus >= 201402L) ||           \
32      (defined(_MSC_VER) && _MSC_VER >= 1900))
33#error upb requires C99 or C++14 or MSVC >= 2015.
34#endif
35
36// Portable check for GCC minimum version:
37// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
38#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
39#define UPB_GNUC_MIN(x, y) \
40  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
41#else
42#define UPB_GNUC_MIN(x, y) 0
43#endif
44
45#include <assert.h>
46#include <setjmp.h>
47#include <stdbool.h>
48#include <stdint.h>
49#include <stdio.h>
50#include <stdlib.h>
51
52#ifndef UINTPTR_MAX
53Error, UINTPTR_MAX is undefined
54#endif
55
56#if UINTPTR_MAX == 0xffffffff
57#define UPB_SIZE(size32, size64) size32
58#else
59#define UPB_SIZE(size32, size64) size64
60#endif
61
62/* If we always read/write as a consistent type to each address, this shouldn't
63 * violate aliasing.
64 */
65#define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs)))
66
67#define UPB_MAPTYPE_STRING 0
68
69// UPB_EXPORT: always generate a public symbol.
70#if defined(__GNUC__) || defined(__clang__)
71#define UPB_EXPORT __attribute__((visibility("default"))) __attribute__((used))
72#else
73#define UPB_EXPORT
74#endif
75
76// UPB_INLINE: inline if possible, emit standalone code if required.
77#ifdef __cplusplus
78#define UPB_INLINE inline
79#elif defined (__GNUC__) || defined(__clang__)
80#define UPB_INLINE static __inline__
81#else
82#define UPB_INLINE static
83#endif
84
85#ifdef UPB_BUILD_API
86#define UPB_API UPB_EXPORT
87#define UPB_API_INLINE UPB_EXPORT
88#else
89#define UPB_API
90#define UPB_API_INLINE UPB_INLINE
91#endif
92
93#ifdef EXPORT_UPBC
94#define UPBC_API UPB_EXPORT
95#else
96#define UPBC_API
97#endif
98
99#define UPB_MALLOC_ALIGN 8
100#define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align))
101#define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align))
102#define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
103#ifdef __clang__
104#define UPB_ALIGN_OF(type) _Alignof(type)
105#else
106#define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
107#endif
108
109#ifdef _MSC_VER
110// Some versions of our Windows compiler don't support the C11 syntax.
111#define UPB_ALIGN_AS(x) __declspec(align(x))
112#else
113#define UPB_ALIGN_AS(x) _Alignas(x)
114#endif
115
116// Hints to the compiler about likely/unlikely branches.
117#if defined (__GNUC__) || defined(__clang__)
118#define UPB_LIKELY(x) __builtin_expect((bool)(x), 1)
119#define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0)
120#else
121#define UPB_LIKELY(x) (x)
122#define UPB_UNLIKELY(x) (x)
123#endif
124
125// Macros for function attributes on compilers that support them.
126#ifdef __GNUC__
127#define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) static
128#define UPB_NOINLINE __attribute__((noinline))
129#define UPB_NORETURN __attribute__((__noreturn__))
130#define UPB_PRINTF(str, first_vararg) __attribute__((format (printf, str, first_vararg)))
131#elif defined(_MSC_VER)
132#define UPB_NOINLINE
133#define UPB_FORCEINLINE static
134#define UPB_NORETURN __declspec(noreturn)
135#define UPB_PRINTF(str, first_vararg)
136#else  /* !defined(__GNUC__) */
137#define UPB_FORCEINLINE static
138#define UPB_NOINLINE
139#define UPB_NORETURN
140#define UPB_PRINTF(str, first_vararg)
141#endif
142
143#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
144#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
145
146#define UPB_UNUSED(var) (void)var
147
148// UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
149#ifdef NDEBUG
150#ifdef __GNUC__
151#define UPB_ASSUME(expr) if (!(expr)) __builtin_unreachable()
152#elif defined _MSC_VER
153#define UPB_ASSUME(expr) if (!(expr)) __assume(0)
154#else
155#define UPB_ASSUME(expr) do {} while (false && (expr))
156#endif
157#else
158#define UPB_ASSUME(expr) assert(expr)
159#endif
160
161/* UPB_ASSERT(): in release mode, we use the expression without letting it be
162 * evaluated.  This prevents "unused variable" warnings. */
163#ifdef NDEBUG
164#define UPB_ASSERT(expr) do {} while (false && (expr))
165#else
166#define UPB_ASSERT(expr) assert(expr)
167#endif
168
169#if defined(__GNUC__) || defined(__clang__)
170#define UPB_UNREACHABLE() do { assert(0); __builtin_unreachable(); } while(0)
171#elif defined(_MSC_VER)
172#define UPB_UNREACHABLE() \
173  do {                    \
174    assert(0);            \
175    __assume(0);          \
176  } while (0)
177#else
178#define UPB_UNREACHABLE() do { assert(0); } while(0)
179#endif
180
181/* UPB_SETJMP() / UPB_LONGJMP(): avoid setting/restoring signal mask. */
182#ifdef __APPLE__
183#define UPB_SETJMP(buf) _setjmp(buf)
184#define UPB_LONGJMP(buf, val) _longjmp(buf, val)
185#elif defined(WASM_WAMR)
186#define UPB_SETJMP(buf) 0
187#define UPB_LONGJMP(buf, val) abort()
188#else
189#define UPB_SETJMP(buf) setjmp(buf)
190#define UPB_LONGJMP(buf, val) longjmp(buf, val)
191#endif
192
193#ifdef __GNUC__
194#define UPB_USE_C11_ATOMICS
195#define UPB_ATOMIC(T) _Atomic(T)
196#else
197#define UPB_ATOMIC(T) T
198#endif
199
200/* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
201#define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
202
203#define UPB_PRIVATE(x) x##_dont_copy_me__upb_internal_use_only
204
205#ifdef UPB_ALLOW_PRIVATE_ACCESS__FOR_BITS_ONLY
206#define UPB_ONLYBITS(x) x
207#else
208#define UPB_ONLYBITS(x) UPB_PRIVATE(x)
209#endif
210
211/* Configure whether fasttable is switched on or not. *************************/
212
213#ifdef __has_attribute
214#define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
215#else
216#define UPB_HAS_ATTRIBUTE(x) 0
217#endif
218
219#if UPB_HAS_ATTRIBUTE(musttail)
220#define UPB_MUSTTAIL __attribute__((musttail))
221#else
222#define UPB_MUSTTAIL
223#endif
224
225#undef UPB_HAS_ATTRIBUTE
226
227/* This check is not fully robust: it does not require that we have "musttail"
228 * support available. We need tail calls to avoid consuming arbitrary amounts
229 * of stack space.
230 *
231 * GCC/Clang can mostly be trusted to generate tail calls as long as
232 * optimization is enabled, but, debug builds will not generate tail calls
233 * unless "musttail" is available.
234 *
235 * We should probably either:
236 *   1. require that the compiler supports musttail.
237 *   2. add some fallback code for when musttail isn't available (ie. return
238 *      instead of tail calling). This is safe and portable, but this comes at
239 *      a CPU cost.
240 */
241#if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
242#define UPB_FASTTABLE_SUPPORTED 1
243#else
244#define UPB_FASTTABLE_SUPPORTED 0
245#endif
246
247/* define UPB_ENABLE_FASTTABLE to force fast table support.
248 * This is useful when we want to ensure we are really getting fasttable,
249 * for example for testing or benchmarking. */
250#if defined(UPB_ENABLE_FASTTABLE)
251#if !UPB_FASTTABLE_SUPPORTED
252#error fasttable is x86-64/ARM64 only and requires GCC or Clang.
253#endif
254#define UPB_FASTTABLE 1
255/* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
256 * This is useful for releasing code that might be used on multiple platforms,
257 * for example the PHP or Ruby C extensions. */
258#elif defined(UPB_TRY_ENABLE_FASTTABLE)
259#define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
260#else
261#define UPB_FASTTABLE 0
262#endif
263
264/* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully
265 * degrade to non-fasttable if the runtime or platform do not support it. */
266#if !UPB_FASTTABLE
267#define UPB_FASTTABLE_INIT(...)
268#define UPB_FASTTABLE_MASK(mask) -1
269#else
270#define UPB_FASTTABLE_INIT(...) __VA_ARGS__
271#define UPB_FASTTABLE_MASK(mask) mask
272#endif
273
274#undef UPB_FASTTABLE_SUPPORTED
275
276/* ASAN poisoning (for arena).
277 * If using UPB from an interpreted language like Ruby, a build of the
278 * interpreter compiled with ASAN enabled must be used in order to get sane and
279 * expected behavior.
280 */
281
282/* Due to preprocessor limitations, the conditional logic for setting
283 * UPN_CLANG_ASAN below cannot be consolidated into a portable one-liner.
284 * See https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html.
285 */
286#if defined(__has_feature)
287#if __has_feature(address_sanitizer)
288#define UPB_CLANG_ASAN 1
289#else
290#define UPB_CLANG_ASAN 0
291#endif
292#else
293#define UPB_CLANG_ASAN 0
294#endif
295
296#if defined(__SANITIZE_ADDRESS__) || UPB_CLANG_ASAN
297#define UPB_ASAN 1
298#define UPB_ASAN_GUARD_SIZE 32
299#ifdef __cplusplus
300    extern "C" {
301#endif
302void __asan_poison_memory_region(void const volatile *addr, size_t size);
303void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
304#ifdef __cplusplus
305}  /* extern "C" */
306#endif
307#define UPB_POISON_MEMORY_REGION(addr, size) \
308  __asan_poison_memory_region((addr), (size))
309#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
310  __asan_unpoison_memory_region((addr), (size))
311#else
312#define UPB_ASAN 0
313#define UPB_ASAN_GUARD_SIZE 0
314#define UPB_POISON_MEMORY_REGION(addr, size) \
315  ((void)(addr), (void)(size))
316#define UPB_UNPOISON_MEMORY_REGION(addr, size) \
317  ((void)(addr), (void)(size))
318#endif
319
320/* Disable proto2 arena behavior (TEMPORARY) **********************************/
321
322#ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING
323#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1
324#else
325#define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0
326#endif
327
328#if defined(__cplusplus)
329#if defined(__clang__) || UPB_GNUC_MIN(6, 0)
330// https://gcc.gnu.org/gcc-6/changes.html
331#if __cplusplus >= 201402L
332#define UPB_DEPRECATED [[deprecated]]
333#else
334#define UPB_DEPRECATED __attribute__((deprecated))
335#endif
336#else
337#define UPB_DEPRECATED
338#endif
339#else
340#define UPB_DEPRECATED
341#endif
342
343#if defined(UPB_IS_GOOGLE3) && \
344    (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0)
345#define UPB_DESC(sym) proto2_##sym
346#define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init
347#elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0
348#define UPB_DESC(sym) google_protobuf_##sym
349#define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init()
350#else
351#define UPB_DESC(sym) google_protobuf_##sym
352#define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init
353#endif
354
355#undef UPB_IS_GOOGLE3
356
357// Linker arrays combine elements from multiple translation units into a single
358// array that can be iterated over at runtime.
359//
360// It is an alternative to pre-main "registration" functions.
361//
362// Usage:
363//
364//   // In N translation units.
365//   UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3};
366//
367//   // At runtime:
368//   UPB_LINKARR_DECLARE(foo_array, int);
369//
370//   void f() {
371//     const int* start = UPB_LINKARR_START(foo_array);
372//     const int* stop = UPB_LINKARR_STOP(foo_array);
373//     for (const int* p = start; p < stop; p++) {
374//       // Windows can introduce zero padding, so we have to skip zeroes.
375//       if (*p != 0) {
376//         vec.push_back(*p);
377//       }
378//     }
379//   }
380
381#if defined(__ELF__) || defined(__wasm__)
382
383#define UPB_LINKARR_APPEND(name) \
384  __attribute__((retain, used, section("linkarr_" #name)))
385#define UPB_LINKARR_DECLARE(name, type)     \
386  extern type const __start_linkarr_##name; \
387  extern type const __stop_linkarr_##name;  \
388  UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1]
389#define UPB_LINKARR_START(name) (&__start_linkarr_##name)
390#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name)
391
392#elif defined(__MACH__)
393
394/* As described in: https://stackoverflow.com/a/22366882 */
395#define UPB_LINKARR_APPEND(name) \
396  __attribute__((retain, used, section("__DATA,__la_" #name)))
397#define UPB_LINKARR_DECLARE(name, type)           \
398  extern type const __start_linkarr_##name __asm( \
399      "section$start$__DATA$__la_" #name);        \
400  extern type const __stop_linkarr_##name __asm(  \
401      "section$end$__DATA$"                       \
402      "__la_" #name);                             \
403  UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1]
404#define UPB_LINKARR_START(name) (&__start_linkarr_##name)
405#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name)
406
407#elif defined(_MSC_VER) && defined(__clang__)
408
409/* See:
410 *   https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155
411 *   https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165
412 *   https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */
413
414// Usage of __attribute__ here probably means this is Clang-specific, and would
415// not work on MSVC.
416#define UPB_LINKARR_APPEND(name) \
417  __declspec(allocate("la_" #name "$j")) __attribute__((retain, used))
418#define UPB_LINKARR_DECLARE(name, type)                               \
419  __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \
420  __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name;  \
421  UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0}
422#define UPB_LINKARR_START(name) (&__start_linkarr_##name)
423#define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name)
424
425#else
426
427// Linker arrays are not supported on this platform.  Make appends a no-op but
428// don't define the other macros.
429#define UPB_LINKARR_APPEND(name)
430
431#endif
432
433// Future versions of upb will include breaking changes to some APIs.
434// This macro can be set to enable these API changes ahead of time, so that
435// user code can be updated before upgrading versions of protobuf.
436#ifdef UPB_FUTURE_BREAKING_CHANGES
437
438// Properly enforce closed enums in python.
439// Owner: mkruskal@
440#define UPB_FUTURE_PYTHON_CLOSED_ENUM_ENFORCEMENT 1
441
442#endif
443