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