github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/compress/libdeflate/common_defs.h (about)

     1  /*
     2   * common_defs.h
     3   *
     4   * Copyright 2016 Eric Biggers
     5   *
     6   * Permission is hereby granted, free of charge, to any person
     7   * obtaining a copy of this software and associated documentation
     8   * files (the "Software"), to deal in the Software without
     9   * restriction, including without limitation the rights to use,
    10   * copy, modify, merge, publish, distribute, sublicense, and/or sell
    11   * copies of the Software, and to permit persons to whom the
    12   * Software is furnished to do so, subject to the following
    13   * conditions:
    14   *
    15   * The above copyright notice and this permission notice shall be
    16   * included in all copies or substantial portions of the Software.
    17   *
    18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    19   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
    20   * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    21   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    22   * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    23   * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    24   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    25   * OTHER DEALINGS IN THE SOFTWARE.
    26   */
    27  
    28  #ifndef COMMON_COMMON_DEFS_H
    29  #define COMMON_COMMON_DEFS_H
    30  
    31  #ifdef __GNUC__
    32  #  include "compiler_gcc.h"
    33  #elif defined(_MSC_VER)
    34  #  include "compiler_msc.h"
    35  #else
    36  #  pragma message("Unrecognized compiler.  Please add a header file for your compiler.  Compilation will proceed, but performance may suffer!")
    37  #endif
    38  
    39  /* ========================================================================== */
    40  /*                              Type definitions                              */
    41  /* ========================================================================== */
    42  
    43  #include <stddef.h> /* size_t */
    44  
    45  #ifndef __bool_true_false_are_defined
    46  #  include <stdbool.h> /* bool */
    47  #endif
    48  
    49  /* Fixed-width integer types */
    50  #ifndef PRIu32
    51  #  include <inttypes.h>
    52  #endif
    53  typedef uint8_t u8;
    54  typedef uint16_t u16;
    55  typedef uint32_t u32;
    56  typedef uint64_t u64;
    57  typedef int8_t s8;
    58  typedef int16_t s16;
    59  typedef int32_t s32;
    60  typedef int64_t s64;
    61  
    62  /*
    63   * Word type of the target architecture.  Use 'size_t' instead of 'unsigned
    64   * long' to account for platforms such as Windows that use 32-bit 'unsigned
    65   * long' on 64-bit architectures.
    66   */
    67  typedef size_t machine_word_t;
    68  
    69  /* Number of bytes in a word */
    70  #define WORDBYTES	((int)sizeof(machine_word_t))
    71  
    72  /* Number of bits in a word */
    73  #define WORDBITS	(8 * WORDBYTES)
    74  
    75  /* ========================================================================== */
    76  /*                         Optional compiler features                         */
    77  /* ========================================================================== */
    78  
    79  /* LIBEXPORT - export a function from a shared library */
    80  #ifndef LIBEXPORT
    81  #  define LIBEXPORT
    82  #endif
    83  
    84  /* inline - suggest that a function be inlined */
    85  #ifndef inline
    86  #  define inline
    87  #endif
    88  
    89  /* forceinline - force a function to be inlined, if possible */
    90  #ifndef forceinline
    91  #  define forceinline inline
    92  #endif
    93  
    94  /* restrict - annotate a non-aliased pointer */
    95  #ifndef restrict
    96  #  define restrict
    97  #endif
    98  
    99  /* likely(expr) - hint that an expression is usually true */
   100  #ifndef likely
   101  #  define likely(expr)		(expr)
   102  #endif
   103  
   104  /* unlikely(expr) - hint that an expression is usually false */
   105  #ifndef unlikely
   106  #  define unlikely(expr)	(expr)
   107  #endif
   108  
   109  /* prefetchr(addr) - prefetch into L1 cache for read */
   110  #ifndef prefetchr
   111  #  define prefetchr(addr)
   112  #endif
   113  
   114  /* prefetchw(addr) - prefetch into L1 cache for write */
   115  #ifndef prefetchw
   116  #  define prefetchw(addr)
   117  #endif
   118  
   119  /* Does the compiler support the 'target' function attribute? */
   120  #ifndef COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE
   121  #  define COMPILER_SUPPORTS_TARGET_FUNCTION_ATTRIBUTE 0
   122  #endif
   123  
   124  /* Which targets are supported with the 'target' function attribute? */
   125  #ifndef COMPILER_SUPPORTS_BMI2_TARGET
   126  #  define COMPILER_SUPPORTS_BMI2_TARGET 0
   127  #endif
   128  #ifndef COMPILER_SUPPORTS_AVX_TARGET
   129  #  define COMPILER_SUPPORTS_AVX_TARGET 0
   130  #endif
   131  
   132  /*
   133   * Which targets are supported with the 'target' function attribute and have
   134   * intrinsics that work within 'target'-ed functions?
   135   */
   136  #ifndef COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS
   137  #  define COMPILER_SUPPORTS_SSE2_TARGET_INTRINSICS 0
   138  #endif
   139  #ifndef COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS
   140  #  define COMPILER_SUPPORTS_PCLMUL_TARGET_INTRINSICS 0
   141  #endif
   142  #ifndef COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS
   143  #  define COMPILER_SUPPORTS_AVX2_TARGET_INTRINSICS 0
   144  #endif
   145  #ifndef COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS
   146  #  define COMPILER_SUPPORTS_NEON_TARGET_INTRINSICS 0
   147  #endif
   148  #ifndef COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS
   149  #  define COMPILER_SUPPORTS_PMULL_TARGET_INTRINSICS 0
   150  #endif
   151  
   152  /* _aligned_attribute(n) - declare that the annotated variable, or variables of
   153   * the annotated type, are to be aligned on n-byte boundaries */
   154  #ifndef _aligned_attribute
   155  #endif
   156  
   157  /* ========================================================================== */
   158  /*                          Miscellaneous macros                              */
   159  /* ========================================================================== */
   160  
   161  #define ARRAY_LEN(A)		(sizeof(A) / sizeof((A)[0]))
   162  #define MIN(a, b)		((a) <= (b) ? (a) : (b))
   163  #define MAX(a, b)		((a) >= (b) ? (a) : (b))
   164  #define DIV_ROUND_UP(n, d)	(((n) + (d) - 1) / (d))
   165  #define STATIC_ASSERT(expr)	((void)sizeof(char[1 - 2 * !(expr)]))
   166  #define ALIGN(n, a)		(((n) + (a) - 1) & ~((a) - 1))
   167  
   168  /* ========================================================================== */
   169  /*                           Endianness handling                              */
   170  /* ========================================================================== */
   171  
   172  /*
   173   * CPU_IS_LITTLE_ENDIAN() - a macro which evaluates to 1 if the CPU is little
   174   * endian or 0 if it is big endian.  The macro should be defined in a way such
   175   * that the compiler can evaluate it at compilation time.  If not defined, a
   176   * fallback is used.
   177   */
   178  #ifndef CPU_IS_LITTLE_ENDIAN
   179  static forceinline int CPU_IS_LITTLE_ENDIAN(void)
   180  {
   181  	union {
   182  		unsigned int v;
   183  		unsigned char b;
   184  	} u;
   185  	u.v = 1;
   186  	return u.b;
   187  }
   188  #endif
   189  
   190  /* bswap16(n) - swap the bytes of a 16-bit integer */
   191  #ifndef bswap16
   192  static forceinline u16 bswap16(u16 n)
   193  {
   194  	return (n << 8) | (n >> 8);
   195  }
   196  #endif
   197  
   198  /* bswap32(n) - swap the bytes of a 32-bit integer */
   199  #ifndef bswap32
   200  static forceinline u32 bswap32(u32 n)
   201  {
   202  	return ((n & 0x000000FF) << 24) |
   203  	       ((n & 0x0000FF00) << 8) |
   204  	       ((n & 0x00FF0000) >> 8) |
   205  	       ((n & 0xFF000000) >> 24);
   206  }
   207  #endif
   208  
   209  /* bswap64(n) - swap the bytes of a 64-bit integer */
   210  #ifndef bswap64
   211  static forceinline u64 bswap64(u64 n)
   212  {
   213  	return ((n & 0x00000000000000FF) << 56) |
   214  	       ((n & 0x000000000000FF00) << 40) |
   215  	       ((n & 0x0000000000FF0000) << 24) |
   216  	       ((n & 0x00000000FF000000) << 8) |
   217  	       ((n & 0x000000FF00000000) >> 8) |
   218  	       ((n & 0x0000FF0000000000) >> 24) |
   219  	       ((n & 0x00FF000000000000) >> 40) |
   220  	       ((n & 0xFF00000000000000) >> 56);
   221  }
   222  #endif
   223  
   224  #define le16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap16(n))
   225  #define le32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap32(n))
   226  #define le64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? (n) : bswap64(n))
   227  #define be16_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap16(n) : (n))
   228  #define be32_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap32(n) : (n))
   229  #define be64_bswap(n) (CPU_IS_LITTLE_ENDIAN() ? bswap64(n) : (n))
   230  
   231  /* ========================================================================== */
   232  /*                          Unaligned memory accesses                         */
   233  /* ========================================================================== */
   234  
   235  /*
   236   * UNALIGNED_ACCESS_IS_FAST should be defined to 1 if unaligned memory accesses
   237   * can be performed efficiently on the target platform.
   238   */
   239  #ifndef UNALIGNED_ACCESS_IS_FAST
   240  #  define UNALIGNED_ACCESS_IS_FAST 0
   241  #endif
   242  
   243  /*
   244   * DEFINE_UNALIGNED_TYPE(type) - a macro that, given an integer type 'type',
   245   * defines load_type_unaligned(addr) and store_type_unaligned(v, addr) functions
   246   * which load and store variables of type 'type' from/to unaligned memory
   247   * addresses.  If not defined, a fallback is used.
   248   */
   249  #ifndef DEFINE_UNALIGNED_TYPE
   250  
   251  /*
   252   * Although memcpy() may seem inefficient, it *usually* gets optimized
   253   * appropriately by modern compilers.  It's portable and may be the best we can
   254   * do for a fallback...
   255   */
   256  #include <string.h>
   257  
   258  #define DEFINE_UNALIGNED_TYPE(type)				\
   259  								\
   260  static forceinline type						\
   261  load_##type##_unaligned(const void *p)				\
   262  {								\
   263  	type v;							\
   264  	memcpy(&v, p, sizeof(v));				\
   265  	return v;						\
   266  }								\
   267  								\
   268  static forceinline void						\
   269  store_##type##_unaligned(type v, void *p)			\
   270  {								\
   271  	memcpy(p, &v, sizeof(v));				\
   272  }
   273  
   274  #endif /* !DEFINE_UNALIGNED_TYPE */
   275  
   276  /* ========================================================================== */
   277  /*                             Bit scan functions                             */
   278  /* ========================================================================== */
   279  
   280  /*
   281   * Bit Scan Reverse (BSR) - find the 0-based index (relative to the least
   282   * significant end) of the *most* significant 1 bit in the input value.  The
   283   * input value must be nonzero!
   284   */
   285  
   286  #ifndef bsr32
   287  static forceinline unsigned
   288  bsr32(u32 n)
   289  {
   290  	unsigned i = 0;
   291  	while ((n >>= 1) != 0)
   292  		i++;
   293  	return i;
   294  }
   295  #endif
   296  
   297  #ifndef bsr64
   298  static forceinline unsigned
   299  bsr64(u64 n)
   300  {
   301  	unsigned i = 0;
   302  	while ((n >>= 1) != 0)
   303  		i++;
   304  	return i;
   305  }
   306  #endif
   307  
   308  static forceinline unsigned
   309  bsrw(machine_word_t n)
   310  {
   311  	STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
   312  	if (WORDBITS == 32)
   313  		return bsr32(n);
   314  	else
   315  		return bsr64(n);
   316  }
   317  
   318  /*
   319   * Bit Scan Forward (BSF) - find the 0-based index (relative to the least
   320   * significant end) of the *least* significant 1 bit in the input value.  The
   321   * input value must be nonzero!
   322   */
   323  
   324  #ifndef bsf32
   325  static forceinline unsigned
   326  bsf32(u32 n)
   327  {
   328  	unsigned i = 0;
   329  	while ((n & 1) == 0) {
   330  		i++;
   331  		n >>= 1;
   332  	}
   333  	return i;
   334  }
   335  #endif
   336  
   337  #ifndef bsf64
   338  static forceinline unsigned
   339  bsf64(u64 n)
   340  {
   341  	unsigned i = 0;
   342  	while ((n & 1) == 0) {
   343  		i++;
   344  		n >>= 1;
   345  	}
   346  	return i;
   347  }
   348  #endif
   349  
   350  static forceinline unsigned
   351  bsfw(machine_word_t n)
   352  {
   353  	STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64);
   354  	if (WORDBITS == 32)
   355  		return bsf32(n);
   356  	else
   357  		return bsf64(n);
   358  }
   359  
   360  #endif /* COMMON_COMMON_DEFS_H */