// Protocol Buffers - Google's data interchange format // Copyright 2023 Google LLC. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd /* * This is where we define internal portability macros used across upb. * * All of these macros are undef'd in undef.inc to avoid leaking them to users. * * The correct usage is: * * #include "upb/foobar.h" * #include "upb/baz.h" * * // MUST be last included header. * #include "upb/port/def.inc" * * // Code for this file. * // <...> * * // Can be omitted for .c files, required for .h. * #include "upb/port/undef.inc" * * This file is private and must not be included by users! */ #if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ (defined(__cplusplus) && __cplusplus >= 201703L) || \ (defined(_MSC_VER) && _MSC_VER >= 1900)) #error upb requires C99 or C++17 or MSVC >= 2015. #endif // Portable check for GCC minimum version: // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) #define UPB_GNUC_MIN(x, y) \ (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) #else #define UPB_GNUC_MIN(x, y) 0 #endif #if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) #define UPB_CLANG_MIN(x, y) \ (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y)) #else #define UPB_CLANG_MIN(x, y) 0 #endif // Macros for checking for compiler attributes, defined here to avoid the // problem described in // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. #ifdef __has_attribute #define UPB_HAS_ATTRIBUTE(x) __has_attribute(x) #else #define UPB_HAS_ATTRIBUTE(x) 0 #endif #ifdef __has_c_attribute #define UPB_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) #else #define UPB_HAS_C_ATTRIBUTE(x) 0 #endif #if defined(__cplusplus) && defined(__has_cpp_attribute) // NOTE: requiring __cplusplus above should not be necessary, but // works around https://bugs.llvm.org/show_bug.cgi?id=23435. #define UPB_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else #define UPB_HAS_CPP_ATTRIBUTE(x) 0 #endif // Once in a while we want to use this macro in a C++-only portion of an // otherwise C-compatible header, so we copy and paste this from ABSL. #if UPB_HAS_CPP_ATTRIBUTE(deprecated) && UPB_HAS_CPP_ATTRIBUTE(clang::annotate) #define UPB_DEPRECATE_AND_INLINE() [[deprecated, clang::annotate("inline-me")]] #elif UPB_HAS_CPP_ATTRIBUTE(deprecated) #define UPB_DEPRECATE_AND_INLINE() [[deprecated]] #else #define UPB_DEPRECATE_AND_INLINE() #endif #ifdef __has_builtin #define UPB_HAS_BUILTIN(x) __has_builtin(x) #else #define UPB_HAS_BUILTIN(x) 0 #endif #ifdef __has_extension #define UPB_HAS_EXTENSION(x) __has_extension(x) #else #define UPB_HAS_EXTENSION(x) 0 #endif #ifdef __has_feature #define UPB_HAS_FEATURE(x) __has_feature(x) #else #define UPB_HAS_FEATURE(x) 0 #endif #include #include #include #include #include #include #ifndef UINTPTR_MAX Error, UINTPTR_MAX is undefined #endif #if UINTPTR_MAX == 0xffffffff #define UPB_SIZE(size32, size64) size32 #else #define UPB_SIZE(size32, size64) size64 #endif /* If we always read/write as a consistent type to each address, this shouldn't * violate aliasing. */ #define UPB_PTR_AT(msg, ofs, type) ((type*)((char*)(msg) + (ofs))) // A flexible array member may have lower alignment requirements than the struct // overall - in that case, it can overlap with the trailing padding of the rest // of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation // will not take into account that overlap, and allocate more than is required. #define UPB_SIZEOF_FLEX(type, member, count) \ UPB_MAX(sizeof(type), offsetof(type, member[count])) #define UPB_SIZEOF_FLEX_WOULD_OVERFLOW(type, member, count) \ (((SIZE_MAX - offsetof(type, member[0])) / \ (offsetof(type, member[1]) - offsetof(type, member[0]))) < (size_t)count) #define UPB_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) #define UPB_MAPTYPE_STRING 0 // UPB_EXPORT: always generate a public symbol. #if defined(__GNUC__) || defined(__clang__) #define UPB_EXPORT __attribute__((visibility("default"))) __attribute__((used)) #else #define UPB_EXPORT #endif // UPB_INLINE: inline if possible, emit standalone code if required. #ifdef __cplusplus #define UPB_INLINE inline #elif defined(__GNUC__) || defined(__clang__) #define UPB_INLINE static __inline__ #else #define UPB_INLINE static #endif // UPB_INLINE_IF_NOT_GCC: because gcc can be very noisy at times. #if defined(__GNUC__) && !defined(__clang__) #define UPB_INLINE_IF_NOT_GCC static #else #define UPB_INLINE_IF_NOT_GCC UPB_INLINE #endif #ifdef UPB_BUILD_API #define UPB_API UPB_EXPORT #define UPB_API_INLINE UPB_EXPORT #else #define UPB_API #define UPB_API_INLINE UPB_INLINE #endif #ifdef EXPORT_UPBC #define UPBC_API UPB_EXPORT #else #define UPBC_API #endif #if UPB_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) #define UPB_ASAN 1 #else #define UPB_ASAN 0 #endif #if UPB_HAS_FEATURE(hwaddress_sanitizer) #define UPB_HWASAN 1 #define UPB_HWASAN_POISON_TAG 17 #define UPB_MALLOC_ALIGN 16 #else #define UPB_HWASAN 0 #define UPB_MALLOC_ALIGN 8 #endif #if UPB_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__) #define UPB_TSAN 1 #else #define UPB_TSAN 0 #endif #if UPB_HAS_FEATURE(memory_sanitizer) #define UPB_MSAN 1 #else #define UPB_MSAN 0 #endif // An unfortunate concession to C++17 and MSVC, which don't support zero-sized // structs. #if UPB_ASAN || UPB_HWASAN || UPB_TSAN #define UPB_XSAN_MEMBER upb_Xsan xsan; #define UPB_XSAN(st) (&(st)->xsan) #define UPB_XSAN_STRUCT_SIZE 1 #else #define UPB_XSAN_MEMBER #define UPB_XSAN(st) (NULL) #define UPB_XSAN_STRUCT_SIZE 0 #endif #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) #define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN) #if __STDC_VERSION__ >= 202311L || UPB_HAS_EXTENSION(cxx_alignof) || \ defined(__cplusplus) #define UPB_ALIGN_OF(type) alignof(type) #elif __STDC_VERSION__ >= 201112L || UPB_HAS_EXTENSION(c_alignof) #define UPB_ALIGN_OF(type) _Alignof(type) #elif UPB_GNUC_MIN(2, 95) #define UPB_ALIGN_OF(type) __alignof__(type) #elif defined(_MSC_VER) #define UPB_ALIGN_OF(type) __alignof(type) #else #define UPB_ALIGN_OF(type) \ offsetof( \ struct { \ char c; \ type member; \ }, \ member) #endif #ifdef _MSC_VER // Some versions of our Windows compiler don't support the C11 syntax. #define UPB_ALIGN_AS(x) __declspec(align(x)) #elif defined(__GNUC__) #define UPB_ALIGN_AS(x) __attribute__((aligned(x))) #else #define UPB_ALIGN_AS(x) _Alignas(x) #endif #if __STDC_VERSION__ >= 202311L || UPB_HAS_EXTENSION(cxx_static_assert) || \ defined(__cplusplus) #define UPB_STATIC_ASSERT(val, msg) static_assert((val), msg) #elif __STDC_VERSION__ >= 201112L || UPB_HAS_EXTENSION(c_static_assert) || \ UPB_GNUC_MIN(4, 6) #define UPB_STATIC_ASSERT(val, msg) _Static_assert((val), msg) #else // Unfortunately this hack doesn't work inside struct declarations, but it works // everywhere else #define UPB_STATIC_ASSERT_CONCAT_IMPL(s1, s2) s1##s2 #define UPB_STATIC_ASSERT_CONCAT(s1, s2) UPB_STATIC_ASSERT_CONCAT_IMPL(s1, s2) #ifdef __COUNTER__ #define UPB_STATIC_ASSERT(condition, message) \ typedef char UPB_STATIC_ASSERT_CONCAT(static_assertion_failure_, \ __COUNTER__)[(condition) ? 1 : -1] #else #define UPB_STATIC_ASSERT(condition, message) \ typedef char UPB_STATIC_ASSERT_CONCAT(static_assertion_failure_, \ __LINE__)[(condition) ? 1 : -1] #endif #endif // Hints to the compiler about likely/unlikely branches. #if defined(__GNUC__) || defined(__clang__) #define UPB_LIKELY(x) __builtin_expect((bool)(x), 1) #define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0) #else #define UPB_LIKELY(x) (x) #define UPB_UNLIKELY(x) (x) #endif #if UPB_HAS_BUILTIN(__builtin_expect_with_probability) #define UPB_UNPREDICTABLE(x) \ __builtin_expect_with_probability((bool)(x), 1, 0.5) #else #define UPB_UNPREDICTABLE(x) (x) #endif // Macros for function attributes on compilers that support them. #if defined(__GNUC__) || defined(__clang__) #define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) static #define UPB_NOINLINE __attribute__((noinline)) #define UPB_NORETURN __attribute__((__noreturn__)) #define UPB_PRINTF(str, first_vararg) \ __attribute__((format(printf, str, first_vararg))) #elif defined(_MSC_VER) #define UPB_NOINLINE #define UPB_FORCEINLINE static #define UPB_NORETURN __declspec(noreturn) #define UPB_PRINTF(str, first_vararg) #else /* !defined(__GNUC__) */ #define UPB_FORCEINLINE static #define UPB_NOINLINE #define UPB_NORETURN #define UPB_PRINTF(str, first_vararg) #endif #if UPB_HAS_ATTRIBUTE(noderef) #define UPB_NODEREF __attribute__((noderef)) #else #define UPB_NODEREF #endif // Will be defined properly once call sites are updated #if false && UPB_HAS_C_ATTRIBUTE(nodiscard) #define UPB_NODISCARD [[nodiscard]] #elif false && UPB_HAS_ATTRIBUTE(warn_unused_result) #define UPB_NODISCARD __attribute__((warn_unused_result)) #elif false && UPB_HAS_CPP_ATTRIBUTE(nodiscard) #define UPB_NODISCARD [[nodiscard]] #else #define UPB_NODISCARD #endif #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) #define UPB_UNUSED(var) (void)(var) // UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. #ifdef NDEBUG #ifdef __GNUC__ #define UPB_ASSUME(expr) \ if (!(expr)) __builtin_unreachable() #elif defined _MSC_VER #define UPB_ASSUME(expr) \ if (!(expr)) __assume(0) #else #define UPB_ASSUME(expr) \ do { \ } while (false && (expr)) #endif #else #define UPB_ASSUME(expr) assert(expr) #endif #if UPB_HAS_BUILTIN(__builtin_constant_p) && UPB_HAS_ATTRIBUTE(const) #define UPB_MAYBE_ASSUME(pred, x) \ if (__builtin_constant_p(pred) && pred) UPB_ASSUME(x) #define UPB_ATTR_CONST __attribute__((const)) #else #define UPB_MAYBE_ASSUME(pred, x) #define UPB_ATTR_CONST #endif /* UPB_ASSERT(): in release mode, we use the expression without letting it be * evaluated. This prevents "unused variable" warnings. */ #ifdef NDEBUG #define UPB_ASSERT(expr) \ do { \ } while (false && (expr)) #else #define UPB_ASSERT(expr) assert(expr) #endif #if !defined(NDEBUG) && !defined(UPB_TSAN) #define UPB_ENABLE_REF_CYCLE_CHECKS 1 #else #define UPB_ENABLE_REF_CYCLE_CHECKS 0 #endif #if defined(__GNUC__) || defined(__clang__) #define UPB_PRETTY_FUNCTION __PRETTY_FUNCTION__ #else #define UPB_PRETTY_FUNCTION NULL #endif #ifdef __cplusplus extern "C" { #endif UPB_NORETURN void _upb_UnreachableFailure(const char* file, int line, const char* function_name); #if !defined(NDEBUG) #define UPB_UNREACHABLE_FAILURE() \ _upb_UnreachableFailure(__FILE__, __LINE__, UPB_PRETTY_FUNCTION); #else #define UPB_UNREACHABLE_FAILURE() #endif #ifdef __cplusplus } /* extern "C" */ #endif #if defined(__GNUC__) || defined(__clang__) #define UPB_UNREACHABLE() \ do { \ UPB_UNREACHABLE_FAILURE(); \ __builtin_unreachable(); \ } while (0) #elif defined(_MSC_VER) #define UPB_UNREACHABLE() \ do { \ UPB_UNREACHABLE_FAILURE(); \ __assume(0); \ } while (0) #else #define UPB_UNREACHABLE() \ do { \ UPB_UNREACHABLE_FAILURE(); \ } while (0) #endif #ifdef __ANDROID__ #define UPB_DEFAULT_MAX_BLOCK_SIZE 8192 #else #define UPB_DEFAULT_MAX_BLOCK_SIZE 32768 #endif /* UPB_SETJMP() / UPB_LONGJMP() */ // Android uses a custom libc that does not implement all of posix, but it has // had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has // sigsetjmp, but does not define the posix feature test macro. #if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) // avoid setting/restoring signal mask, which involves costly syscalls #define UPB_SETJMP(buf) sigsetjmp(buf, 0) #define UPB_LONGJMP(buf, val) siglongjmp(buf, val) #elif defined(WASM_WAMR) #define UPB_SETJMP(buf) 0 #define UPB_LONGJMP(buf, val) abort() #else #define UPB_SETJMP(buf) setjmp(buf) #define UPB_LONGJMP(buf, val) longjmp(buf, val) #endif #if ((__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)) || \ UPB_HAS_EXTENSION(c_atomic) || \ defined(__GNUC__) // GCC supported atomics as an extension before it // supported __has_extension #define UPB_USE_C11_ATOMICS #elif defined(_MSC_VER) #define UPB_USE_MSC_ATOMICS #endif #if defined(UPB_USE_C11_ATOMICS) #define UPB_ATOMIC(T) _Atomic(T) #elif defined(UPB_USE_MSC_ATOMICS) #define UPB_ATOMIC(T) volatile T #else #define UPB_ATOMIC(T) T #endif /* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */ #define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr)) #define UPB_PRIVATE(x) x##_dont_copy_me__upb_internal_use_only #ifdef UPB_ALLOW_PRIVATE_ACCESS__FOR_BITS_ONLY #define UPB_ONLYBITS(x) x #else #define UPB_ONLYBITS(x) UPB_PRIVATE(x) #endif /* Configure whether fasttable is switched on or not. *************************/ #if UPB_HAS_ATTRIBUTE(musttail) #define UPB_MUSTTAIL __attribute__((musttail)) #else #define UPB_MUSTTAIL #endif #if UPB_HAS_ATTRIBUTE(preserve_most) && !defined(__i386__) #define UPB_PRESERVE_MOST __attribute__((preserve_most)) #else #define UPB_PRESERVE_MOST #endif #if UPB_HAS_ATTRIBUTE(preserve_none) #define UPB_PRESERVE_NONE __attribute__((preserve_none)) #else #define UPB_PRESERVE_NONE #endif #if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__)) #define UPB_ARM64_ASM 1 #else #define UPB_ARM64_ASM 0 #endif /* When compiling with branch protection, we need to ensure that all branch * targets in assembly use the appropriate landing pad instruction. These * instructions are backwards compatible with processors that don't have * FEAT_BTI and are treated as nops. */ #if UPB_ARM64_ASM && defined(__ARM_FEATURE_BTI_DEFAULT) #if __ARM_FEATURE_BTI_DEFAULT == 1 #define UPB_ARM64_BTI_DEFAULT 1 #else #define UPB_ARM64_BTI_DEFAULT 0 #endif #else #define UPB_ARM64_BTI_DEFAULT 0 #endif /* aarch64 supports big and little endian modes; fasttable performs multibyte * tag loads assumes the tag of a varint is in the low bits. */ #if (defined(__x86_64__) || defined(__AARCH64EL__)) && \ UPB_HAS_ATTRIBUTE(preserve_none) && UPB_HAS_ATTRIBUTE(musttail) #define UPB_FASTTABLE_SUPPORTED 1 #else #define UPB_FASTTABLE_SUPPORTED 0 #endif /* define UPB_ENABLE_FASTTABLE to force fast table support. * This is useful when we want to ensure we are really getting fasttable, * for example for testing or benchmarking. */ #if defined(UPB_ENABLE_FASTTABLE) #if !UPB_FASTTABLE_SUPPORTED #error fasttable is x86-64/ARM64le only and requires preserve_none and musttail. #endif #define UPB_FASTTABLE 1 /* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. * This is useful for releasing code that might be used on multiple platforms, * for example the PHP or Ruby C extensions. */ #elif defined(UPB_TRY_ENABLE_FASTTABLE) #define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED #else #define UPB_FASTTABLE 0 #endif /* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully * degrade to non-fasttable if the runtime or platform do not support it. */ #if !UPB_FASTTABLE #define UPB_FASTTABLE_INIT(...) #define UPB_FASTTABLE_MASK(mask) -1 #else #define UPB_FASTTABLE_INIT(...) __VA_ARGS__ #define UPB_FASTTABLE_MASK(mask) mask #endif #undef UPB_FASTTABLE_SUPPORTED #if defined(__cplusplus) #if defined(__clang__) || UPB_GNUC_MIN(6, 0) // https://gcc.gnu.org/gcc-6/changes.html #define UPB_DEPRECATED [[deprecated]] #else #define UPB_DEPRECATED #endif #else #define UPB_DEPRECATED #endif #if defined(UPB_IS_GOOGLE3) && \ (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init #elif defined(UPB_IS_GOOGLE3) && defined(UPB_BOOTSTRAP_STAGE) && \ UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC_MINITABLE(sym) proto2__##sym##_msg_init() #elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() #else #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init #endif #undef UPB_IS_GOOGLE3 #ifdef __clang__ #define UPB_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) #else #define UPB_NO_SANITIZE_ADDRESS #endif #if defined(__GNUC__) && (defined(__clang__) || UPB_GNUC_MIN(11, 0)) #define UPB_RETAIN __attribute__((retain)) #else #define UPB_RETAIN #endif // Linker arrays combine elements from multiple translation units into a single // array that can be iterated over at runtime. // // It is an alternative to pre-main "registration" functions. // // Usage: // // // In N translation units. // UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; // // // At runtime: // UPB_LINKARR_DECLARE(foo_array, int); // // void f() { // const int* start = UPB_LINKARR_START(foo_array); // const int* stop = UPB_LINKARR_STOP(foo_array); // for (const int* p = start; p < stop; p++) { // // Windows can introduce zero padding, so we have to skip zeroes. // if (*p != 0) { // vec.push_back(*p); // } // } // } #if defined(__GNUC__) && !defined(__clang__) // GCC can't handle mismatched retain attributes in the same section: // https://github.com/protocolbuffers/protobuf/issues/26385 // To work around this, we retain all linker array elements, even though this // effectively disables tree-shaking of unused extensions when using GCC. #define UPB_LINKARR_ATTR UPB_RETAIN #else #define UPB_LINKARR_ATTR #endif #define UPB_LINKARR_SENTINEL UPB_RETAIN __attribute__((weak, used)) #if defined(__ELF__) || defined(__wasm__) #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("linkarr_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS #define UPB_LINKARR_DECLARE(name, type) \ UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ "Linker array name too long for Mach-O (16-char limit)"); \ extern type __start_linkarr_##name; \ extern type __stop_linkarr_##name; \ UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) #elif defined(__MACH__) /* As described in: https://stackoverflow.com/a/22366882 */ #define UPB_LINKARR_APPEND(name) \ __attribute__(( \ section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS #define UPB_LINKARR_DECLARE(name, type) \ UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ "Linker array name too long for Mach-O (16-char limit)"); \ extern type __start_linkarr_##name __asm( \ "section$start$__DATA$__la_" #name); \ extern type __stop_linkarr_##name __asm( \ "section$end$__DATA$" \ "__la_" #name); \ UPB_LINKARR_APPEND(name) \ UPB_LINKARR_SENTINEL type UPB_linkarr_internal_empty_##name[1] #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) #elif defined(_MSC_VER) /* See: * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ #define UPB_STRINGIFY_INTERNAL(x) #x #define UPB_STRINGIFY(x) UPB_STRINGIFY_INTERNAL(x) #define UPB_CONCAT(a, b, c) a##b##c #define UPB_LINKARR_NAME(name, index) \ UPB_STRINGIFY(UPB_CONCAT(la_, name, index)) #define UPB_LINKARR_APPEND(name) \ __pragma(section(UPB_LINKARR_NAME(name, $j), read)) \ __declspec(allocate(UPB_LINKARR_NAME(name, $j))) // clang-format off #define UPB_LINKARR_DECLARE(name, type) \ __pragma(message(UPB_LINKARR_NAME(name, $j))) \ __pragma(section(UPB_LINKARR_NAME(name, $a), read)) \ __pragma(section(UPB_LINKARR_NAME(name, $z), read)) \ __declspec(allocate(UPB_LINKARR_NAME(name, $a)), selectany) \ type __start_linkarr_##name; \ __declspec(allocate(UPB_LINKARR_NAME(name, $z)), selectany) \ type __stop_linkarr_##name; \ UPB_LINKARR_APPEND(name) \ __declspec(selectany) type UPB_linkarr_internal_empty_##name[1] = {0} // clang-format on #define UPB_LINKARR_START(name) (&__start_linkarr_##name) #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) #else // Linker arrays are not supported on this platform. Make macros no-ops. #define UPB_LINKARR_APPEND(name) #define UPB_LINKARR_DECLARE(name, type) \ UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \ "Linker array name too long for Mach-O (16-char limit)") #define UPB_LINKARR_START(name) (NULL) #define UPB_LINKARR_STOP(name) (NULL) #endif // Workaround for https://github.com/llvm/llvm-project/issues/167577 until it's // fixed. Some function must exist for the constructor to work properly. // TODO Remove this or gate it on a future version of clang. #if defined(__clang__) && defined(__arm__) #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((used, visibility("hidden"))) void UPB_PRIVATE(unique_name)( \ void) {} #else #define _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) #endif #define _UPB_STRINGIFY2(x) #x #define _UPB_STRINGIFY(x) _UPB_STRINGIFY2(x) #if defined(__ELF__) && (UPB_GNUC_MIN(15, 1) || UPB_CLANG_MIN(21, 1)) /* * Workaround for b/456308964 and b/456317163. Although weak constructors * resolve to a single function body, Clang still emits a pointer into * .init_array for every translation unit, causing the constructor to be * executed multiple times and inflating binary size. We wrap the .init_array * entry in a COMDAT group (using inline assembly) to force the linker to * deduplicate the pointer to exactly one instance. %cc is used in preference to * the more widely available %c because %c may under some circumstances still * output a function name including relocation information, which will then * confuse the linker. This was only a problem on gcc; when %cc was introduced * to clang it was just an alias to %c, and clang's %c had already done the * checks that %cc introduced to gcc. * References: * https://github.com/gcc-mirror/gcc/commit/74d6a676034b3ab20c387f12f19f5597e4f1c9fa * https://github.com/llvm/llvm-project/pull/127719#issuecomment-2686276305 */ #define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, used, visibility("hidden"))) void UPB_PRIVATE(name)( \ void) { \ __asm__ volatile( \ ".pushsection .init_array,\"awG\",%%init_array, %cc0, comdat\n" \ ".dc.a %cc0\n" \ ".popsection\n" \ : \ : "X"(UPB_PRIVATE(name))); \ __VA_ARGS__ \ } #elif defined(__ELF__) || defined(__wasm__) || defined(__MACH__) || \ defined(__MINGW32__) #define UPB_CONSTRUCTOR(name, unique_name, ...) \ _UPB_CONSTRUCTOR_PLACEHOLDER(unique_name) \ __attribute__((weak, visibility("hidden"), constructor)) void UPB_PRIVATE( \ name)(void) { \ __VA_ARGS__ \ } #elif defined(_MSC_VER) /* * See: https://stackoverflow.com/questions/1113409 * * The /include pragma suggested in the link above doesn't work in our case * because it requires globally unique names. We need a different solution * to prevent optimizers from removing the constructor. Our solution is to * create a dummy exported weak symbol that prevent this stripping. */ #pragma section(".CRT$XCT", read) #define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void __cdecl UPB_PRIVATE(name)(void); \ __declspec(allocate(".CRT$XCT"), selectany) void( \ __cdecl * UPB_PRIVATE(name##_))(void) = UPB_PRIVATE(name); \ __declspec(selectany, dllexport) void* UPB_PRIVATE(name##_force_linkage) = \ &UPB_PRIVATE(name##_); \ static void __cdecl UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else // No constructor support, nothing we can do except not break builds. #if defined(__GNUC__) || defined(__clang__) #define UPB_CONSTRUCTOR(name, unique_name, ...) \ static __attribute__((used)) void UPB_PRIVATE(name)(void) { __VA_ARGS__ } #else #define UPB_CONSTRUCTOR(name, unique_name, ...) \ static void UPB_PRIVATE(name)(void) { __VA_ARGS__ } #endif #endif // // Weak alias platform support. Theoretically this should be possible to do with // only C using attributes like __attribute__((weak, alias("foo"))), but // Clang doesn't support this properly on macOS. So we have to use assembly. #if defined(__APPLE__) // TODO: once https://github.com/llvm/llvm-project/issues/167262 is fixed // in the LLVM linker, we should have all weak variables point to a single // "default" empty MiniTable instead of having each leaf define its own, like // we do with ELF below. This will reduce binary size if many messages are tree // shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() #define UPB_WEAK_PLACEHOLDER_MINITABLE(name) \ __attribute__((weak)) const upb_MiniTable name = { \ .UPB_PRIVATE(fields) = NULL, \ .UPB_PRIVATE(size) = sizeof(struct upb_Message), \ .UPB_PRIVATE(field_count) = 0, \ .UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable, \ .UPB_PRIVATE(dense_below) = 0, \ .UPB_PRIVATE(table_mask) = -1, \ .UPB_PRIVATE(required_count) = 0, \ }; #define UPB_WEAK_ALIAS(type, from, to) \ extern type to; \ __asm__(".globl _" #to); \ __asm__(".private_extern _" #to); \ __asm__(".set _" #to ", _" #from); \ __asm__(".weak_definition _" #to); #define UPB_STRONG_ALIAS(type, from, to) \ __asm__(".globl _" #to); \ __asm__(".private_extern _" #to); \ __asm__(".set _" #to ", _" #from); #elif defined(__ELF__) || defined(__wasm__) // On ELF, weak aliases work properly, so we can have all weak MiniTables // point to the same empty singleton MiniTable. This reduces code size if many // MiniTables are tree shaken. #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() \ __attribute__((weak)) \ const upb_MiniTable kUpb_WeakSingletonPlaceholderMiniTable = { \ .UPB_PRIVATE(fields) = NULL, \ .UPB_PRIVATE(size) = sizeof(struct upb_Message), \ .UPB_PRIVATE(field_count) = 0, \ .UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable, \ .UPB_PRIVATE(dense_below) = 0, \ .UPB_PRIVATE(table_mask) = -1, \ .UPB_PRIVATE(required_count) = 0, \ }; #define UPB_WEAK_PLACEHOLDER_MINITABLE(name) #define UPB_WEAK_ALIAS(type, from, to) \ extern type to \ __attribute__((weak, alias("kUpb_WeakSingletonPlaceholderMiniTable"))); #define UPB_STRONG_ALIAS(type, from, to) \ extern type to __attribute__((alias(#from))); #else #define UPB_WEAK_SINGLETON_PLACEHOLDER_MINITABLE() #define UPB_WEAK_PLACEHOLDER_MINITABLE(name) #define UPB_WEAK_ALIAS(type, from, to) weak_alias_not_supported_on_this_platform #define UPB_STRONG_ALIAS(type, from, to) \ strong_alias_not_supported_on_this_platform #endif