11#ifndef ZSTD_COMPILER_H
12#define ZSTD_COMPILER_H
23#if !defined(ZSTD_NO_INLINE)
24#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
25# define INLINE_KEYWORD inline
27# define INLINE_KEYWORD
30#if defined(__GNUC__) || defined(__ICCARM__)
31# define FORCE_INLINE_ATTR __attribute__((always_inline))
32#elif defined(_MSC_VER)
33# define FORCE_INLINE_ATTR __forceinline
35# define FORCE_INLINE_ATTR
41#define FORCE_INLINE_ATTR
51# define WIN_CDECL __cdecl
58# define UNUSED_ATTR __attribute__((unused))
68#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR
80#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
81# define HINT_INLINE static INLINE_KEYWORD
83# define HINT_INLINE FORCE_INLINE_TEMPLATE
97# define MEM_STATIC static __inline UNUSED_ATTR
98#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) )
99# define MEM_STATIC static inline
100#elif defined(_MSC_VER)
101# define MEM_STATIC static __inline
103# define MEM_STATIC static
109# define FORCE_NOINLINE static __declspec(noinline)
111# if defined(__GNUC__) || defined(__ICCARM__)
112# define FORCE_NOINLINE static __attribute__((__noinline__))
114# define FORCE_NOINLINE static
120#if defined(__GNUC__) || defined(__ICCARM__)
121# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
123# define TARGET_ATTRIBUTE(target)
130#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
134#if defined(NO_PREFETCH)
135# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0)
136# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0)
138# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC)
139# include <mmintrin.h>
140# define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
141# define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
142# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
143# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 , 3 )
144# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 , 2 )
145# elif defined(__aarch64__)
146# define PREFETCH_L1(ptr) do { __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))); } while (0)
147# define PREFETCH_L2(ptr) do { __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))); } while (0)
149# define PREFETCH_L1(ptr) do { (void)(ptr); } while (0)
150# define PREFETCH_L2(ptr) do { (void)(ptr); } while (0)
154#define CACHELINE_SIZE 64
156#define PREFETCH_AREA(p, s) \
158 const char* const _ptr = (const char*)(p); \
159 size_t const _size = (size_t)(s); \
161 for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
162 PREFETCH_L2(_ptr + _pos); \
169#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)
170# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
171# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
173# define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")")
176# define DONT_VECTORIZE
185#define LIKELY(x) (__builtin_expect((x), 1))
186#define UNLIKELY(x) (__builtin_expect((x), 0))
189#define UNLIKELY(x) (x)
192#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
193# define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0)
195# define ZSTD_UNREACHABLE do { assert(0); } while (0)
201# pragma warning(disable : 4100)
202# pragma warning(disable : 4127)
203# pragma warning(disable : 4204)
204# pragma warning(disable : 4214)
205# pragma warning(disable : 4324)
210# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86))
212# define STATIC_BMI2 1
214# elif defined(__BMI2__) && defined(__x86_64__) && defined(__GNUC__)
215# define STATIC_BMI2 1
220 #define STATIC_BMI2 0
224#if !defined(ZSTD_NO_INTRINSICS)
225# if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))
226# define ZSTD_ARCH_X86_SSE2
228# if defined(__ARM_NEON) || defined(_M_ARM64)
229# define ZSTD_ARCH_ARM_NEON
232# if defined(ZSTD_ARCH_X86_SSE2)
233# include <emmintrin.h>
234# elif defined(ZSTD_ARCH_ARM_NEON)
235# include <arm_neon.h>
240#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
241# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
243# define ZSTD_HAS_C_ATTRIBUTE(x) 0
249#if defined(__cplusplus) && defined(__has_cpp_attribute)
250# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
252# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
260#ifndef ZSTD_FALLTHROUGH
261# if ZSTD_HAS_C_ATTRIBUTE(fallthrough)
262# define ZSTD_FALLTHROUGH [[fallthrough]]
263# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)
264# define ZSTD_FALLTHROUGH [[fallthrough]]
265# elif __has_attribute(__fallthrough__)
269# define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))
271# define ZSTD_FALLTHROUGH
286# if defined(__GNUC__) || defined(_MSC_VER)
290# define ZSTD_ALIGNOF(T) __alignof(T)
292# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
294# include <stdalign.h>
295# define ZSTD_ALIGNOF(T) alignof(T)
299# define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))
312#ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
313# if __has_attribute(no_sanitize)
314# if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
316# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("signed-integer-overflow")))
319# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("pointer-overflow")))
322# define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
373 return add > 0 ? ptr + add : ptr;
379#ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE
380#define ZSTD_ASAN_DONT_POISON_WORKSPACE 1
382#ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE
383#define ZSTD_MSAN_DONT_POISON_WORKSPACE 1
387#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)
392#define ZSTD_DEPS_NEED_STDINT
396void __msan_unpoison(
const volatile void *a,
size_t size);
401void __msan_poison(
const volatile void *a,
size_t size);
405intptr_t __msan_test_shadow(
const volatile void *x,
size_t size);
409void __msan_print_shadow(
const volatile void *x,
size_t size);
412#if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE)
432void __asan_poison_memory_region(
void const volatile *addr,
size_t size);
447void __asan_unpoison_memory_region(
void const volatile *addr,
size_t size);
MEM_STATIC ZSTD_ALLOW_POINTER_OVERFLOW_ATTR unsigned char const * ZSTD_wrappedPtrSub(unsigned char const *ptr, ptrdiff_t sub)
MEM_STATIC ZSTD_ALLOW_POINTER_OVERFLOW_ATTR ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const *lhs, unsigned char const *rhs)
MEM_STATIC unsigned char * ZSTD_maybeNullPtrAdd(unsigned char *ptr, ptrdiff_t add)
MEM_STATIC ZSTD_ALLOW_POINTER_OVERFLOW_ATTR unsigned char const * ZSTD_wrappedPtrAdd(unsigned char const *ptr, ptrdiff_t add)
#define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR