1*3117ece4Schristos /* 2*3117ece4Schristos * Copyright (c) Meta Platforms, Inc. and affiliates. 3*3117ece4Schristos * All rights reserved. 4*3117ece4Schristos * 5*3117ece4Schristos * This source code is licensed under both the BSD-style license (found in the 6*3117ece4Schristos * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7*3117ece4Schristos * in the COPYING file in the root directory of this source tree). 8*3117ece4Schristos * You may select, at your option, one of the above-listed licenses. 9*3117ece4Schristos */ 10*3117ece4Schristos 11*3117ece4Schristos #ifndef ZSTD_COMPILER_H 12*3117ece4Schristos #define ZSTD_COMPILER_H 13*3117ece4Schristos 14*3117ece4Schristos #include <stddef.h> 15*3117ece4Schristos 16*3117ece4Schristos #include "portability_macros.h" 17*3117ece4Schristos 18*3117ece4Schristos /*-******************************************************* 19*3117ece4Schristos * Compiler specifics 20*3117ece4Schristos *********************************************************/ 21*3117ece4Schristos /* force inlining */ 22*3117ece4Schristos 23*3117ece4Schristos #if !defined(ZSTD_NO_INLINE) 24*3117ece4Schristos #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ 25*3117ece4Schristos # define INLINE_KEYWORD inline 26*3117ece4Schristos #else 27*3117ece4Schristos # define INLINE_KEYWORD 28*3117ece4Schristos #endif 29*3117ece4Schristos 30*3117ece4Schristos #if defined(__GNUC__) || defined(__ICCARM__) 31*3117ece4Schristos # define FORCE_INLINE_ATTR __attribute__((always_inline)) 32*3117ece4Schristos #elif defined(_MSC_VER) 33*3117ece4Schristos # define FORCE_INLINE_ATTR __forceinline 34*3117ece4Schristos #else 35*3117ece4Schristos # define FORCE_INLINE_ATTR 36*3117ece4Schristos #endif 37*3117ece4Schristos 38*3117ece4Schristos #else 39*3117ece4Schristos 40*3117ece4Schristos #define INLINE_KEYWORD 41*3117ece4Schristos #define FORCE_INLINE_ATTR 42*3117ece4Schristos 43*3117ece4Schristos #endif 44*3117ece4Schristos 45*3117ece4Schristos /** 46*3117ece4Schristos On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). 47*3117ece4Schristos This explicitly marks such functions as __cdecl so that the code will still compile 48*3117ece4Schristos if a CC other than __cdecl has been made the default. 49*3117ece4Schristos */ 50*3117ece4Schristos #if defined(_MSC_VER) 51*3117ece4Schristos # define WIN_CDECL __cdecl 52*3117ece4Schristos #else 53*3117ece4Schristos # define WIN_CDECL 54*3117ece4Schristos #endif 55*3117ece4Schristos 56*3117ece4Schristos /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */ 57*3117ece4Schristos #if defined(__GNUC__) 58*3117ece4Schristos # define UNUSED_ATTR __attribute__((unused)) 59*3117ece4Schristos #else 60*3117ece4Schristos # define UNUSED_ATTR 61*3117ece4Schristos #endif 62*3117ece4Schristos 63*3117ece4Schristos /** 64*3117ece4Schristos * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant 65*3117ece4Schristos * parameters. They must be inlined for the compiler to eliminate the constant 66*3117ece4Schristos * branches. 67*3117ece4Schristos */ 68*3117ece4Schristos #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR 69*3117ece4Schristos /** 70*3117ece4Schristos * HINT_INLINE is used to help the compiler generate better code. It is *not* 71*3117ece4Schristos * used for "templates", so it can be tweaked based on the compilers 72*3117ece4Schristos * performance. 73*3117ece4Schristos * 74*3117ece4Schristos * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the 75*3117ece4Schristos * always_inline attribute. 76*3117ece4Schristos * 77*3117ece4Schristos * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline 78*3117ece4Schristos * attribute. 79*3117ece4Schristos */ 80*3117ece4Schristos #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5 81*3117ece4Schristos # define HINT_INLINE static INLINE_KEYWORD 82*3117ece4Schristos #else 83*3117ece4Schristos # define HINT_INLINE FORCE_INLINE_TEMPLATE 84*3117ece4Schristos #endif 85*3117ece4Schristos 86*3117ece4Schristos /* "soft" inline : 87*3117ece4Schristos * The compiler is free to select if it's a good idea to inline or not. 88*3117ece4Schristos * The main objective is to silence compiler warnings 89*3117ece4Schristos * when a defined function in included but not used. 90*3117ece4Schristos * 91*3117ece4Schristos * Note : this macro is prefixed `MEM_` because it used to be provided by `mem.h` unit. 92*3117ece4Schristos * Updating the prefix is probably preferable, but requires a fairly large codemod, 93*3117ece4Schristos * since this name is used everywhere. 94*3117ece4Schristos */ 95*3117ece4Schristos #ifndef MEM_STATIC /* already defined in Linux Kernel mem.h */ 96*3117ece4Schristos #if defined(__GNUC__) 97*3117ece4Schristos # define MEM_STATIC static __inline UNUSED_ATTR 98*3117ece4Schristos #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) 99*3117ece4Schristos # define MEM_STATIC static inline 100*3117ece4Schristos #elif defined(_MSC_VER) 101*3117ece4Schristos # define MEM_STATIC static __inline 102*3117ece4Schristos #else 103*3117ece4Schristos # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ 104*3117ece4Schristos #endif 105*3117ece4Schristos #endif 106*3117ece4Schristos 107*3117ece4Schristos /* force no inlining */ 108*3117ece4Schristos #ifdef _MSC_VER 109*3117ece4Schristos # define FORCE_NOINLINE static __declspec(noinline) 110*3117ece4Schristos #else 111*3117ece4Schristos # if defined(__GNUC__) || defined(__ICCARM__) 112*3117ece4Schristos # define FORCE_NOINLINE static __attribute__((__noinline__)) 113*3117ece4Schristos # else 114*3117ece4Schristos # define FORCE_NOINLINE static 115*3117ece4Schristos # endif 116*3117ece4Schristos #endif 117*3117ece4Schristos 118*3117ece4Schristos 119*3117ece4Schristos /* target attribute */ 120*3117ece4Schristos #if defined(__GNUC__) || defined(__ICCARM__) 121*3117ece4Schristos # define TARGET_ATTRIBUTE(target) __attribute__((__target__(target))) 122*3117ece4Schristos #else 123*3117ece4Schristos # define TARGET_ATTRIBUTE(target) 124*3117ece4Schristos #endif 125*3117ece4Schristos 126*3117ece4Schristos /* Target attribute for BMI2 dynamic dispatch. 127*3117ece4Schristos * Enable lzcnt, bmi, and bmi2. 128*3117ece4Schristos * We test for bmi1 & bmi2. lzcnt is included in bmi1. 129*3117ece4Schristos */ 130*3117ece4Schristos #define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2") 131*3117ece4Schristos 132*3117ece4Schristos /* prefetch 133*3117ece4Schristos * can be disabled, by declaring NO_PREFETCH build macro */ 134*3117ece4Schristos #if defined(NO_PREFETCH) 135*3117ece4Schristos # define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */ 136*3117ece4Schristos # define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */ 137*3117ece4Schristos #else 138*3117ece4Schristos # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC) /* _mm_prefetch() is not defined outside of x86/x64 */ 139*3117ece4Schristos # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ 140*3117ece4Schristos # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) 141*3117ece4Schristos # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) 142*3117ece4Schristos # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) 143*3117ece4Schristos # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) 144*3117ece4Schristos # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) 145*3117ece4Schristos # elif defined(__aarch64__) 146*3117ece4Schristos # define PREFETCH_L1(ptr) do { __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))); } while (0) 147*3117ece4Schristos # define PREFETCH_L2(ptr) do { __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))); } while (0) 148*3117ece4Schristos # else 149*3117ece4Schristos # define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */ 150*3117ece4Schristos # define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */ 151*3117ece4Schristos # endif 152*3117ece4Schristos #endif /* NO_PREFETCH */ 153*3117ece4Schristos 154*3117ece4Schristos #define CACHELINE_SIZE 64 155*3117ece4Schristos 156*3117ece4Schristos #define PREFETCH_AREA(p, s) \ 157*3117ece4Schristos do { \ 158*3117ece4Schristos const char* const _ptr = (const char*)(p); \ 159*3117ece4Schristos size_t const _size = (size_t)(s); \ 160*3117ece4Schristos size_t _pos; \ 161*3117ece4Schristos for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \ 162*3117ece4Schristos PREFETCH_L2(_ptr + _pos); \ 163*3117ece4Schristos } \ 164*3117ece4Schristos } while (0) 165*3117ece4Schristos 166*3117ece4Schristos /* vectorization 167*3117ece4Schristos * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax, 168*3117ece4Schristos * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */ 169*3117ece4Schristos #if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__) 170*3117ece4Schristos # if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5) 171*3117ece4Schristos # define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize"))) 172*3117ece4Schristos # else 173*3117ece4Schristos # define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")") 174*3117ece4Schristos # endif 175*3117ece4Schristos #else 176*3117ece4Schristos # define DONT_VECTORIZE 177*3117ece4Schristos #endif 178*3117ece4Schristos 179*3117ece4Schristos /* Tell the compiler that a branch is likely or unlikely. 180*3117ece4Schristos * Only use these macros if it causes the compiler to generate better code. 181*3117ece4Schristos * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc 182*3117ece4Schristos * and clang, please do. 183*3117ece4Schristos */ 184*3117ece4Schristos #if defined(__GNUC__) 185*3117ece4Schristos #define LIKELY(x) (__builtin_expect((x), 1)) 186*3117ece4Schristos #define UNLIKELY(x) (__builtin_expect((x), 0)) 187*3117ece4Schristos #else 188*3117ece4Schristos #define LIKELY(x) (x) 189*3117ece4Schristos #define UNLIKELY(x) (x) 190*3117ece4Schristos #endif 191*3117ece4Schristos 192*3117ece4Schristos #if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))) 193*3117ece4Schristos # define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0) 194*3117ece4Schristos #else 195*3117ece4Schristos # define ZSTD_UNREACHABLE do { assert(0); } while (0) 196*3117ece4Schristos #endif 197*3117ece4Schristos 198*3117ece4Schristos /* disable warnings */ 199*3117ece4Schristos #ifdef _MSC_VER /* Visual Studio */ 200*3117ece4Schristos # include <intrin.h> /* For Visual 2005 */ 201*3117ece4Schristos # pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */ 202*3117ece4Schristos # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 203*3117ece4Schristos # pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ 204*3117ece4Schristos # pragma warning(disable : 4214) /* disable: C4214: non-int bitfields */ 205*3117ece4Schristos # pragma warning(disable : 4324) /* disable: C4324: padded structure */ 206*3117ece4Schristos #endif 207*3117ece4Schristos 208*3117ece4Schristos /*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ 209*3117ece4Schristos #ifndef STATIC_BMI2 210*3117ece4Schristos # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) 211*3117ece4Schristos # ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 212*3117ece4Schristos # define STATIC_BMI2 1 213*3117ece4Schristos # endif 214*3117ece4Schristos # elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__) 215*3117ece4Schristos # define STATIC_BMI2 1 216*3117ece4Schristos # endif 217*3117ece4Schristos #endif 218*3117ece4Schristos 219*3117ece4Schristos #ifndef STATIC_BMI2 220*3117ece4Schristos #define STATIC_BMI2 0 221*3117ece4Schristos #endif 222*3117ece4Schristos 223*3117ece4Schristos /* compile time determination of SIMD support */ 224*3117ece4Schristos #if !defined(ZSTD_NO_INTRINSICS) 225*3117ece4Schristos # if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2)) 226*3117ece4Schristos # define ZSTD_ARCH_X86_SSE2 227*3117ece4Schristos # endif 228*3117ece4Schristos # if defined(__ARM_NEON) || defined(_M_ARM64) 229*3117ece4Schristos # define ZSTD_ARCH_ARM_NEON 230*3117ece4Schristos # endif 231*3117ece4Schristos # 232*3117ece4Schristos # if defined(ZSTD_ARCH_X86_SSE2) 233*3117ece4Schristos # include <emmintrin.h> 234*3117ece4Schristos # elif defined(ZSTD_ARCH_ARM_NEON) 235*3117ece4Schristos # include <arm_neon.h> 236*3117ece4Schristos # endif 237*3117ece4Schristos #endif 238*3117ece4Schristos 239*3117ece4Schristos /* C-language Attributes are added in C23. */ 240*3117ece4Schristos #if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute) 241*3117ece4Schristos # define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x) 242*3117ece4Schristos #else 243*3117ece4Schristos # define ZSTD_HAS_C_ATTRIBUTE(x) 0 244*3117ece4Schristos #endif 245*3117ece4Schristos 246*3117ece4Schristos /* Only use C++ attributes in C++. Some compilers report support for C++ 247*3117ece4Schristos * attributes when compiling with C. 248*3117ece4Schristos */ 249*3117ece4Schristos #if defined(__cplusplus) && defined(__has_cpp_attribute) 250*3117ece4Schristos # define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) 251*3117ece4Schristos #else 252*3117ece4Schristos # define ZSTD_HAS_CPP_ATTRIBUTE(x) 0 253*3117ece4Schristos #endif 254*3117ece4Schristos 255*3117ece4Schristos /* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute. 256*3117ece4Schristos * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough 257*3117ece4Schristos * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough 258*3117ece4Schristos * - Else: __attribute__((__fallthrough__)) 259*3117ece4Schristos */ 260*3117ece4Schristos #ifndef ZSTD_FALLTHROUGH 261*3117ece4Schristos # if ZSTD_HAS_C_ATTRIBUTE(fallthrough) 262*3117ece4Schristos # define ZSTD_FALLTHROUGH [[fallthrough]] 263*3117ece4Schristos # elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough) 264*3117ece4Schristos # define ZSTD_FALLTHROUGH [[fallthrough]] 265*3117ece4Schristos # elif __has_attribute(__fallthrough__) 266*3117ece4Schristos /* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon 267*3117ece4Schristos * gcc complains about: a label can only be part of a statement and a declaration is not a statement. 268*3117ece4Schristos */ 269*3117ece4Schristos # define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__)) 270*3117ece4Schristos # else 271*3117ece4Schristos # define ZSTD_FALLTHROUGH 272*3117ece4Schristos # endif 273*3117ece4Schristos #endif 274*3117ece4Schristos 275*3117ece4Schristos /*-************************************************************** 276*3117ece4Schristos * Alignment check 277*3117ece4Schristos *****************************************************************/ 278*3117ece4Schristos 279*3117ece4Schristos /* this test was initially positioned in mem.h, 280*3117ece4Schristos * but this file is removed (or replaced) for linux kernel 281*3117ece4Schristos * so it's now hosted in compiler.h, 282*3117ece4Schristos * which remains valid for both user & kernel spaces. 283*3117ece4Schristos */ 284*3117ece4Schristos 285*3117ece4Schristos #ifndef ZSTD_ALIGNOF 286*3117ece4Schristos # if defined(__GNUC__) || defined(_MSC_VER) 287*3117ece4Schristos /* covers gcc, clang & MSVC */ 288*3117ece4Schristos /* note : this section must come first, before C11, 289*3117ece4Schristos * due to a limitation in the kernel source generator */ 290*3117ece4Schristos # define ZSTD_ALIGNOF(T) __alignof(T) 291*3117ece4Schristos 292*3117ece4Schristos # elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) 293*3117ece4Schristos /* C11 support */ 294*3117ece4Schristos # include <stdalign.h> 295*3117ece4Schristos # define ZSTD_ALIGNOF(T) alignof(T) 296*3117ece4Schristos 297*3117ece4Schristos # else 298*3117ece4Schristos /* No known support for alignof() - imperfect backup */ 299*3117ece4Schristos # define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T)) 300*3117ece4Schristos 301*3117ece4Schristos # endif 302*3117ece4Schristos #endif /* ZSTD_ALIGNOF */ 303*3117ece4Schristos 304*3117ece4Schristos /*-************************************************************** 305*3117ece4Schristos * Sanitizer 306*3117ece4Schristos *****************************************************************/ 307*3117ece4Schristos 308*3117ece4Schristos /** 309*3117ece4Schristos * Zstd relies on pointer overflow in its decompressor. 310*3117ece4Schristos * We add this attribute to functions that rely on pointer overflow. 311*3117ece4Schristos */ 312*3117ece4Schristos #ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR 313*3117ece4Schristos # if __has_attribute(no_sanitize) 314*3117ece4Schristos # if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8 315*3117ece4Schristos /* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */ 316*3117ece4Schristos # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("signed-integer-overflow"))) 317*3117ece4Schristos # else 318*3117ece4Schristos /* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */ 319*3117ece4Schristos # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("pointer-overflow"))) 320*3117ece4Schristos # endif 321*3117ece4Schristos # else 322*3117ece4Schristos # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR 323*3117ece4Schristos # endif 324*3117ece4Schristos #endif 325*3117ece4Schristos 326*3117ece4Schristos /** 327*3117ece4Schristos * Helper function to perform a wrapped pointer difference without trigging 328*3117ece4Schristos * UBSAN. 329*3117ece4Schristos * 330*3117ece4Schristos * @returns lhs - rhs with wrapping 331*3117ece4Schristos */ 332*3117ece4Schristos MEM_STATIC 333*3117ece4Schristos ZSTD_ALLOW_POINTER_OVERFLOW_ATTR 334*3117ece4Schristos ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs) 335*3117ece4Schristos { 336*3117ece4Schristos return lhs - rhs; 337*3117ece4Schristos } 338*3117ece4Schristos 339*3117ece4Schristos /** 340*3117ece4Schristos * Helper function to perform a wrapped pointer add without triggering UBSAN. 341*3117ece4Schristos * 342*3117ece4Schristos * @return ptr + add with wrapping 343*3117ece4Schristos */ 344*3117ece4Schristos MEM_STATIC 345*3117ece4Schristos ZSTD_ALLOW_POINTER_OVERFLOW_ATTR 346*3117ece4Schristos unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add) 347*3117ece4Schristos { 348*3117ece4Schristos return ptr + add; 349*3117ece4Schristos } 350*3117ece4Schristos 351*3117ece4Schristos /** 352*3117ece4Schristos * Helper function to perform a wrapped pointer subtraction without triggering 353*3117ece4Schristos * UBSAN. 354*3117ece4Schristos * 355*3117ece4Schristos * @return ptr - sub with wrapping 356*3117ece4Schristos */ 357*3117ece4Schristos MEM_STATIC 358*3117ece4Schristos ZSTD_ALLOW_POINTER_OVERFLOW_ATTR 359*3117ece4Schristos unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub) 360*3117ece4Schristos { 361*3117ece4Schristos return ptr - sub; 362*3117ece4Schristos } 363*3117ece4Schristos 364*3117ece4Schristos /** 365*3117ece4Schristos * Helper function to add to a pointer that works around C's undefined behavior 366*3117ece4Schristos * of adding 0 to NULL. 367*3117ece4Schristos * 368*3117ece4Schristos * @returns `ptr + add` except it defines `NULL + 0 == NULL`. 369*3117ece4Schristos */ 370*3117ece4Schristos MEM_STATIC 371*3117ece4Schristos unsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add) 372*3117ece4Schristos { 373*3117ece4Schristos return add > 0 ? ptr + add : ptr; 374*3117ece4Schristos } 375*3117ece4Schristos 376*3117ece4Schristos /* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an 377*3117ece4Schristos * abundance of caution, disable our custom poisoning on mingw. */ 378*3117ece4Schristos #ifdef __MINGW32__ 379*3117ece4Schristos #ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE 380*3117ece4Schristos #define ZSTD_ASAN_DONT_POISON_WORKSPACE 1 381*3117ece4Schristos #endif 382*3117ece4Schristos #ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE 383*3117ece4Schristos #define ZSTD_MSAN_DONT_POISON_WORKSPACE 1 384*3117ece4Schristos #endif 385*3117ece4Schristos #endif 386*3117ece4Schristos 387*3117ece4Schristos #if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE) 388*3117ece4Schristos /* Not all platforms that support msan provide sanitizers/msan_interface.h. 389*3117ece4Schristos * We therefore declare the functions we need ourselves, rather than trying to 390*3117ece4Schristos * include the header file... */ 391*3117ece4Schristos #include <stddef.h> /* size_t */ 392*3117ece4Schristos #define ZSTD_DEPS_NEED_STDINT 393*3117ece4Schristos #include "zstd_deps.h" /* intptr_t */ 394*3117ece4Schristos 395*3117ece4Schristos /* Make memory region fully initialized (without changing its contents). */ 396*3117ece4Schristos void __msan_unpoison(const volatile void *a, size_t size); 397*3117ece4Schristos 398*3117ece4Schristos /* Make memory region fully uninitialized (without changing its contents). 399*3117ece4Schristos This is a legacy interface that does not update origin information. Use 400*3117ece4Schristos __msan_allocated_memory() instead. */ 401*3117ece4Schristos void __msan_poison(const volatile void *a, size_t size); 402*3117ece4Schristos 403*3117ece4Schristos /* Returns the offset of the first (at least partially) poisoned byte in the 404*3117ece4Schristos memory range, or -1 if the whole range is good. */ 405*3117ece4Schristos intptr_t __msan_test_shadow(const volatile void *x, size_t size); 406*3117ece4Schristos 407*3117ece4Schristos /* Print shadow and origin for the memory range to stderr in a human-readable 408*3117ece4Schristos format. */ 409*3117ece4Schristos void __msan_print_shadow(const volatile void *x, size_t size); 410*3117ece4Schristos #endif 411*3117ece4Schristos 412*3117ece4Schristos #if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE) 413*3117ece4Schristos /* Not all platforms that support asan provide sanitizers/asan_interface.h. 414*3117ece4Schristos * We therefore declare the functions we need ourselves, rather than trying to 415*3117ece4Schristos * include the header file... */ 416*3117ece4Schristos #include <stddef.h> /* size_t */ 417*3117ece4Schristos 418*3117ece4Schristos /** 419*3117ece4Schristos * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. 420*3117ece4Schristos * 421*3117ece4Schristos * This memory must be previously allocated by your program. Instrumented 422*3117ece4Schristos * code is forbidden from accessing addresses in this region until it is 423*3117ece4Schristos * unpoisoned. This function is not guaranteed to poison the entire region - 424*3117ece4Schristos * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan 425*3117ece4Schristos * alignment restrictions. 426*3117ece4Schristos * 427*3117ece4Schristos * \note This function is not thread-safe because no two threads can poison or 428*3117ece4Schristos * unpoison memory in the same memory region simultaneously. 429*3117ece4Schristos * 430*3117ece4Schristos * \param addr Start of memory region. 431*3117ece4Schristos * \param size Size of memory region. */ 432*3117ece4Schristos void __asan_poison_memory_region(void const volatile *addr, size_t size); 433*3117ece4Schristos 434*3117ece4Schristos /** 435*3117ece4Schristos * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. 436*3117ece4Schristos * 437*3117ece4Schristos * This memory must be previously allocated by your program. Accessing 438*3117ece4Schristos * addresses in this region is allowed until this region is poisoned again. 439*3117ece4Schristos * This function could unpoison a super-region of <c>[addr, addr+size)</c> due 440*3117ece4Schristos * to ASan alignment restrictions. 441*3117ece4Schristos * 442*3117ece4Schristos * \note This function is not thread-safe because no two threads can 443*3117ece4Schristos * poison or unpoison memory in the same memory region simultaneously. 444*3117ece4Schristos * 445*3117ece4Schristos * \param addr Start of memory region. 446*3117ece4Schristos * \param size Size of memory region. */ 447*3117ece4Schristos void __asan_unpoison_memory_region(void const volatile *addr, size_t size); 448*3117ece4Schristos #endif 449*3117ece4Schristos 450*3117ece4Schristos #endif /* ZSTD_COMPILER_H */ 451