
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) NGINX, Inc.
 */

#ifndef _NXT_CLANG_H_INCLUDED_
#define _NXT_CLANG_H_INCLUDED_


#define nxt_inline     static inline __attribute__((always_inline))
#define nxt_noinline   __attribute__((noinline))
#define nxt_cdecl


#if (NXT_CLANG)

/* Any __asm__ directive disables loop vectorization in GCC and Clang. */
#define                                                                       \
nxt_pragma_loop_disable_vectorization                                         \
    __asm__("")

#else

#define                                                                       \
nxt_pragma_loop_disable_vectorization

#endif


#if (NXT_HAVE_BUILTIN_EXPECT)

#define                                                                       \
nxt_expect(c, x)                                                              \
    __builtin_expect((long) (x), (c))

#define                                                                       \
nxt_fast_path(x)                                                              \
    nxt_expect(1, x)

#define                                                                       \
nxt_slow_path(x)                                                              \
    nxt_expect(0, x)


#else

#define                                                                       \
nxt_expect(c, x)                                                              \
    (x)

#define                                                                       \
nxt_fast_path(x)                                                              \
    (x)

#define                                                                       \
nxt_slow_path(x)                                                              \
    (x)

#endif


#if (NXT_HAVE_BUILTIN_UNREACHABLE)

#define                                                                       \
nxt_unreachable()                                                             \
    __builtin_unreachable()

#else

#define                                                                       \
nxt_unreachable()

#endif


#if (NXT_HAVE_BUILTIN_PREFETCH)

#define                                                                       \
nxt_prefetch(a)                                                               \
    __builtin_prefetch(a)

#else

#define                                                                       \
nxt_prefetch(a)

#endif


#if (NXT_HAVE_GCC_ATTRIBUTE_VISIBILITY)

#define NXT_EXPORT         __attribute__((visibility("default")))

#else

#define NXT_EXPORT

#endif


#if (NXT_HAVE_GCC_ATTRIBUTE_MALLOC)

#define NXT_MALLOC_LIKE    __attribute__((__malloc__))

#else

#define NXT_MALLOC_LIKE

#endif


#if (NXT_HAVE_GCC_ATTRIBUTE_ALIGNED)

#define nxt_aligned(x)     __attribute__((aligned(x)))

#else

#define nxt_aligned(x)

#endif


#if (NXT_HAVE_GCC_ATTRIBUTE_PACKED)

#define nxt_packed         __attribute__((__packed__))

#else

#define nxt_packed

#endif


#if (NXT_HAVE_BUILTIN_POPCOUNT)

#define nxt_popcount       __builtin_popcount

#else

nxt_inline int
nxt_popcount(unsigned int x)
{
    int  count;

    for (count = 0; x != 0; count++) {
        x &= x - 1;
    }

    return count;
}

#endif


#ifndef NXT_ALIGNMENT

#if (NXT_SOLARIS)
#define NXT_ALIGNMENT      _POINTER_ALIGNMENT     /* x86_64: 8,   i386: 4    */
                                                  /* sparcv9: 8,  sparcv8: 4 */
#elif (__i386__ || __i386)
#define NXT_ALIGNMENT      4

#elif (__arm__)
#define NXT_ALIGNMENT      8         /* 32-bit ARM may use 64-bit load/store */

#elif (__ia64__)
#define NXT_ALIGNMENT      8         /* long long */

#else
#define NXT_ALIGNMENT      NXT_PTR_SIZE
#endif

#endif


#ifndef NXT_MAX_ALIGNMENT

#if (NXT_SOLARIS)
#define NXT_MAX_ALIGNMENT  _MAX_ALIGNMENT        /* x86_64: 16,   i386: 4    */
                                                 /* sparcv9: 16,  sparcv8: 8 */
#elif (__i386__ || __i386)
#define NXT_MAX_ALIGNMENT  4

#elif (__arm__)
#define NXT_MAX_ALIGNMENT  16

#elif (__ia64__)
#define NXT_MAX_ALIGNMENT  16

#else
#define NXT_MAX_ALIGNMENT  16
#endif

#endif


#define                                                                       \
nxt_alloca(size)                                                              \
    alloca(size)


#define                                                                       \
nxt_container_of(p, type, field)                                              \
    (type *) ((u_char *) (p) - offsetof(type, field))


#define nxt_pointer_to(p, offset)                                             \
    ((void *) ((char *) (p) + (offset)))


#define nxt_value_at(type, p, offset)                                         \
    *(type *) ((u_char *) p + offset)


#define                                                                       \
nxt_nitems(x)                                                                 \
    (sizeof(x) / sizeof((x)[0]))


/* GCC and Clang use __builtin_abs() instead of libc abs(). */

#define                                                                       \
nxt_abs(val)                                                                  \
    abs(val)


#define                                                                       \
nxt_max(val1, val2)                                                           \
    ((val1 < val2) ? (val2) : (val1))


#define                                                                       \
nxt_min(val1, val2)                                                           \
    ((val1 > val2) ? (val2) : (val1))


#define                                                                       \
nxt_bswap32(val)                                                              \
    (   ((val)               >> 24)                                           \
     | (((val) & 0x00FF0000) >>  8)                                           \
     | (((val) & 0x0000FF00) <<  8)                                           \
     |  ((val)               << 24))


#define nxt_is_power_of_two(value)                                            \
    ((((value) - 1) & (value)) == 0)


#define                                                                       \
nxt_align_size(d, a)                                                          \
    (((d) + ((size_t) (a) - 1)) & ~((size_t) (a) - 1))


#define                                                                       \
nxt_align_ptr(p, a)                                                           \
    (u_char *) (((uintptr_t) (p) + ((uintptr_t) (a) - 1))                     \
                  & ~((uintptr_t) (a) - 1))

#define                                                                       \
nxt_trunc_ptr(p, a)                                                           \
    (u_char *) ((uintptr_t) (p) & ~((uintptr_t) (a) - 1))


#define nxt_length(s)                                                         \
    (sizeof(s) - 1)


#endif /* _NXT_CLANG_H_INCLUDED_ */
