#ifndef COMPILER_H
#define COMPILER_H

#ifndef __ASSEMBLY__

#include <stddef.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>

#ifdef __cplusplus
# define extern_c extern "C"
# define EXTERN_C(...) extern "C" { __VA_ARGS__ }
#else
# define extern_c extern
# define EXTERN_C(...) __VA_ARGS__
#endif

#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))

#undef  likely
#define likely(x)	__builtin_expect(!!(x), 1)
#undef  unlikely
#define unlikely(x)	__builtin_expect(!!(x), 0)

/* Handy composite pointer types */
typedef union xptr {
    uint32_t *l;
    uint16_t *w;
    uint8_t  *b;
    void     *v;
    size_t    a;
} xptr_t;
typedef union xcptr {
    const uint32_t *l;
    const uint16_t *w;
    const uint8_t  *b;
    const void     *v;
    size_t          a;
} xcptr_t;

/* Subword types */
typedef union {
    uint8_t  b[8];
    uint16_t h[4];
    uint32_t l[2];
    uint64_t q;
} qword_t;
typedef union {
    uint8_t  b[4];
    uint16_t h[2];
    uint32_t l;
} lword_t;
typedef union {
    uint8_t  b[2];
    uint16_t h;
} hword_t;

/* The container_of construct: if p is a pointer to member m of
   container class c, then return a pointer to the container of which
   *p is a member. */
#ifndef container_of
# define container_of(p, c, m) ((c *)((char *)(p) - offsetof(c,m)))
#endif

#define offset_diff(c, m1, m2) ((ptrdiff_t)offsetof(c,m2) - \
				(ptrdiff_t)offsetof(c,m1))

/* Type-safeish comparison macros */
#define Min(a,b) ({				\
      __typeof__((a)*(b)) __a = (a);		\
      __typeof__((a)*(b)) __b = (b);		\
      (__a < __b) ? __a : __b;			\
})
#define Max(a,b) ({				\
  __typeof__((a)*(b)) __a = (a);		\
  __typeof__((a)*(b)) __b = (b);		\
  (__a > __b) ? __a : __b;			\
})

#if SIZE_MAX == UINT16_MAX
# define SIZE_BITS 16
typedef uint32_t size2_t;
#elif SIZE_MAX == UINT32_MAX
# define SIZE_BITS 32
typedef uint64_t size2_t;
#elif SIZE_MAX == UINT64_MAX
# define SIZE_BITS 64
typedef unsigned __int128 size2_t;
#else
# error "Unknown size_t"
#endif

#define alignof(a) __alignof__(a)

#define no_return void __attribute__((noreturn))

#define ___section(s,a,...) __attribute__((__section__(s)))

#define __hot			__attribute__((__hot__))
#define __cold			__attribute__((__cold__))
#define __aligned(x)		__attribute__((__aligned__(x)))
#define __unused		__attribute__((__unused__))
#define __must_inline		__attribute__((__always_inline__))
#define __noinline		__attribute__ ((__noinline__))
#define __constfunc		__attribute__((__const__))
#define __purefunc		__attribute__((__pure__))
#undef  __alloc_size
#define __alloc_size(...)	__attribute__((__alloc_size__(__VA_ARGS__)))
#define __malloc_func		__attribute__((__malloc__))
#define __fmt_printf(fstr,farg)	__attribute__((__format__(__printf__,fstr,farg)))
#define __nonnull_arg(...)	__attribute__((__nonnull__(__VA_ARGS__)))
#define __no_return		void __attribute__((__noreturn__))
#define __nonnull_ret		__attribute__((__returns_nonnull__))
#define __packed		__attribute__((__packed__))

#define __safe_alloc(...)	__nonnull_ret __alloc_size(__VA_ARGS__)

#define __is_constant(expr)	__builtin_constant_p(expr)

#ifndef __cplusplus
# define atomic(x)		(*(volatile __typeof__(x) *)&(x))
#endif

#else /* __ASSEMBLY__ */

#define ___section(s,a,...)	.pushsection s, a, ## __VA_ARGS__

#endif /* __ASSEMBLY__ */

#endif /* COMPILER_H */
