zstd-ruby 1.5.5.0 → 1.5.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +2 -2
  4. data/ext/zstdruby/extconf.rb +2 -0
  5. data/ext/zstdruby/libzstd/common/allocations.h +1 -1
  6. data/ext/zstdruby/libzstd/common/bitstream.h +49 -29
  7. data/ext/zstdruby/libzstd/common/compiler.h +114 -22
  8. data/ext/zstdruby/libzstd/common/cpu.h +36 -0
  9. data/ext/zstdruby/libzstd/common/debug.c +6 -0
  10. data/ext/zstdruby/libzstd/common/debug.h +20 -11
  11. data/ext/zstdruby/libzstd/common/error_private.h +45 -36
  12. data/ext/zstdruby/libzstd/common/fse.h +3 -2
  13. data/ext/zstdruby/libzstd/common/fse_decompress.c +19 -17
  14. data/ext/zstdruby/libzstd/common/huf.h +14 -1
  15. data/ext/zstdruby/libzstd/common/mem.h +0 -9
  16. data/ext/zstdruby/libzstd/common/pool.c +1 -1
  17. data/ext/zstdruby/libzstd/common/pool.h +1 -1
  18. data/ext/zstdruby/libzstd/common/portability_macros.h +2 -0
  19. data/ext/zstdruby/libzstd/common/threading.c +8 -2
  20. data/ext/zstdruby/libzstd/common/xxhash.c +5 -11
  21. data/ext/zstdruby/libzstd/common/xxhash.h +2341 -1007
  22. data/ext/zstdruby/libzstd/common/zstd_internal.h +5 -5
  23. data/ext/zstdruby/libzstd/compress/fse_compress.c +8 -7
  24. data/ext/zstdruby/libzstd/compress/huf_compress.c +54 -25
  25. data/ext/zstdruby/libzstd/compress/zstd_compress.c +282 -161
  26. data/ext/zstdruby/libzstd/compress/zstd_compress_internal.h +29 -27
  27. data/ext/zstdruby/libzstd/compress/zstd_compress_superblock.c +224 -113
  28. data/ext/zstdruby/libzstd/compress/zstd_cwksp.h +19 -13
  29. data/ext/zstdruby/libzstd/compress/zstd_double_fast.c +17 -5
  30. data/ext/zstdruby/libzstd/compress/zstd_double_fast.h +11 -0
  31. data/ext/zstdruby/libzstd/compress/zstd_fast.c +14 -6
  32. data/ext/zstdruby/libzstd/compress/zstd_lazy.c +129 -87
  33. data/ext/zstdruby/libzstd/compress/zstd_lazy.h +103 -28
  34. data/ext/zstdruby/libzstd/compress/zstd_ldm.c +8 -2
  35. data/ext/zstdruby/libzstd/compress/zstd_opt.c +216 -112
  36. data/ext/zstdruby/libzstd/compress/zstd_opt.h +31 -7
  37. data/ext/zstdruby/libzstd/compress/zstdmt_compress.c +94 -79
  38. data/ext/zstdruby/libzstd/decompress/huf_decompress.c +188 -126
  39. data/ext/zstdruby/libzstd/decompress/huf_decompress_amd64.S +38 -19
  40. data/ext/zstdruby/libzstd/decompress/zstd_decompress.c +84 -32
  41. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.c +231 -208
  42. data/ext/zstdruby/libzstd/decompress/zstd_decompress_block.h +1 -1
  43. data/ext/zstdruby/libzstd/decompress/zstd_decompress_internal.h +2 -0
  44. data/ext/zstdruby/libzstd/dictBuilder/cover.c +16 -12
  45. data/ext/zstdruby/libzstd/dictBuilder/cover.h +2 -8
  46. data/ext/zstdruby/libzstd/dictBuilder/fastcover.c +2 -2
  47. data/ext/zstdruby/libzstd/dictBuilder/zdict.c +12 -6
  48. data/ext/zstdruby/libzstd/zstd.h +129 -60
  49. data/ext/zstdruby/streaming_compress.c +23 -3
  50. data/ext/zstdruby/streaming_decompress.c +23 -3
  51. data/lib/zstd-ruby/version.rb +1 -1
  52. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76dbffc6a0a13fccd92ea93abd90e33c4a26ab2ac2972877b7928a515e37033e
4
- data.tar.gz: 21e3eba574ac94d9f34ac0d33732435ed3fd2373e9db921702a74d2a2c9d606a
3
+ metadata.gz: 3f071ec996e63976c8391a34fe8b3b66e2551b3ad6cac027e81bffe9c65ee3f7
4
+ data.tar.gz: 1e71eb86fc8378c8d1e9932717fa1a79d2ba5e40de9f0defdc331b6d3de280a0
5
5
  SHA512:
6
- metadata.gz: 4f8c40ad6eaa9b014467fc57651f857713767f7930b2e7e2060c50ff58d05262416d0e9cb1427f440298af577eeef5247daec1866a55003ca6d9b2e2ea6212de
7
- data.tar.gz: 5836f8061f7588081df400bf0705fcc74003029ec9ef9225e43f5ba5a0b19ec747af71cf0e34f150212a5efd90b9e1ea5ebe49a7231297e3f2ab8080bbf8247d
6
+ metadata.gz: 4ef3fdf69acc7a09bddc9bade06555f16fab4a77a2849411007fcb38ded652c02eb12f3470f9231cefc5537bd486235772662777e6aec45b0f8e3b6d7da3d911
7
+ data.tar.gz: 1e79f3d09cd17cf76795a0ea76c64eb279c34fda421e74b10db2f02eff0bde1cbc8c8396fc276acb549422201257b9b18f3199c7fd245b5ee0fd818a3045fc03
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ vendor/
19
19
  .rspec_status
20
20
 
21
21
  .ruby-version
22
+
23
+ .vscode
data/README.md CHANGED
@@ -10,7 +10,7 @@ See https://github.com/facebook/zstd
10
10
  Fork from https://github.com/jarredholman/ruby-zstd.
11
11
 
12
12
  ## Zstd version
13
- v1.5.5 (https://github.com/facebook/zstd/tree/v1.5.5)
13
+ v1.5.5 (https://github.com/facebook/zstd/tree/v1.5.6)
14
14
 
15
15
  ## Installation
16
16
 
@@ -87,7 +87,7 @@ result << stream.decompress(cstr[0, 10])
87
87
  result << stream.decompress(cstr[10..-1])
88
88
  ```
89
89
 
90
- ### Skippable flame
90
+ ### Skippable frame
91
91
 
92
92
  ```ruby
93
93
  compressed_data_with_skippable_frame = Zstd.write_skippable_frame(compressed_data, "sample data")
@@ -1,5 +1,7 @@
1
1
  require "mkmf"
2
2
 
3
+ have_func('rb_gc_mark_movable')
4
+
3
5
  $CFLAGS = '-I. -O3 -std=c99 -DZSTD_STATIC_LINKING_ONLY'
4
6
  $CPPFLAGS += " -fdeclspec" if CONFIG['CXX'] =~ /clang/
5
7
 
@@ -14,7 +14,7 @@
14
14
  #define ZSTD_DEPS_NEED_MALLOC
15
15
  #include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
16
16
 
17
- #include "mem.h" /* MEM_STATIC */
17
+ #include "compiler.h" /* MEM_STATIC */
18
18
  #define ZSTD_STATIC_LINKING_ONLY
19
19
  #include "../zstd.h" /* ZSTD_customMem */
20
20
 
@@ -90,19 +90,20 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
90
90
  /*-********************************************
91
91
  * bitStream decoding API (read backward)
92
92
  **********************************************/
93
+ typedef size_t BitContainerType;
93
94
  typedef struct {
94
- size_t bitContainer;
95
+ BitContainerType bitContainer;
95
96
  unsigned bitsConsumed;
96
97
  const char* ptr;
97
98
  const char* start;
98
99
  const char* limitPtr;
99
100
  } BIT_DStream_t;
100
101
 
101
- typedef enum { BIT_DStream_unfinished = 0,
102
- BIT_DStream_endOfBuffer = 1,
103
- BIT_DStream_completed = 2,
104
- BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
105
- /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
102
+ typedef enum { BIT_DStream_unfinished = 0, /* fully refilled */
103
+ BIT_DStream_endOfBuffer = 1, /* still some bits left in bitstream */
104
+ BIT_DStream_completed = 2, /* bitstream entirely consumed, bit-exact */
105
+ BIT_DStream_overflow = 3 /* user requested more bits than present in bitstream */
106
+ } BIT_DStream_status; /* result of BIT_reloadDStream() */
106
107
 
107
108
  MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
108
109
  MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
@@ -112,7 +113,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
112
113
 
113
114
  /* Start by invoking BIT_initDStream().
114
115
  * A chunk of the bitStream is then stored into a local register.
115
- * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
116
+ * Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType).
116
117
  * You can then retrieve bitFields stored into the local register, **in reverse order**.
117
118
  * Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
118
119
  * A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
@@ -162,7 +163,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
162
163
  return 0;
163
164
  }
164
165
 
165
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
166
+ FORCE_INLINE_TEMPLATE size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
166
167
  {
167
168
  #if defined(STATIC_BMI2) && STATIC_BMI2 == 1 && !defined(ZSTD_NO_INTRINSICS)
168
169
  return _bzhi_u64(bitContainer, nbBits);
@@ -267,22 +268,22 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
267
268
  bitD->bitContainer = *(const BYTE*)(bitD->start);
268
269
  switch(srcSize)
269
270
  {
270
- case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
271
+ case 7: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
271
272
  ZSTD_FALLTHROUGH;
272
273
 
273
- case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
274
+ case 6: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
274
275
  ZSTD_FALLTHROUGH;
275
276
 
276
- case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
277
+ case 5: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
277
278
  ZSTD_FALLTHROUGH;
278
279
 
279
- case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
280
+ case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24;
280
281
  ZSTD_FALLTHROUGH;
281
282
 
282
- case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
283
+ case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16;
283
284
  ZSTD_FALLTHROUGH;
284
285
 
285
- case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
286
+ case 2: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[1]) << 8;
286
287
  ZSTD_FALLTHROUGH;
287
288
 
288
289
  default: break;
@@ -297,12 +298,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
297
298
  return srcSize;
298
299
  }
299
300
 
300
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
301
+ FORCE_INLINE_TEMPLATE size_t BIT_getUpperBits(BitContainerType bitContainer, U32 const start)
301
302
  {
302
303
  return bitContainer >> start;
303
304
  }
304
305
 
305
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
306
+ FORCE_INLINE_TEMPLATE size_t BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits)
306
307
  {
307
308
  U32 const regMask = sizeof(bitContainer)*8 - 1;
308
309
  /* if start > regMask, bitstream is corrupted, and result is undefined */
@@ -325,7 +326,7 @@ MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 c
325
326
  * On 32-bits, maxNbBits==24.
326
327
  * On 64-bits, maxNbBits==56.
327
328
  * @return : value extracted */
328
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
329
+ FORCE_INLINE_TEMPLATE size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
329
330
  {
330
331
  /* arbitrate between double-shift and shift+mask */
331
332
  #if 1
@@ -348,7 +349,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
348
349
  return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
349
350
  }
350
351
 
351
- MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
352
+ FORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
352
353
  {
353
354
  bitD->bitsConsumed += nbBits;
354
355
  }
@@ -357,7 +358,7 @@ MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
357
358
  * Read (consume) next n bits from local register and update.
358
359
  * Pay attention to not read more than nbBits contained into local register.
359
360
  * @return : extracted value. */
360
- MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
361
+ FORCE_INLINE_TEMPLATE size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
361
362
  {
362
363
  size_t const value = BIT_lookBits(bitD, nbBits);
363
364
  BIT_skipBits(bitD, nbBits);
@@ -374,6 +375,21 @@ MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
374
375
  return value;
375
376
  }
376
377
 
378
+ /*! BIT_reloadDStream_internal() :
379
+ * Simple variant of BIT_reloadDStream(), with two conditions:
380
+ * 1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8
381
+ * 2. look window is valid after shifted down : bitD->ptr >= bitD->start
382
+ */
383
+ MEM_STATIC BIT_DStream_status BIT_reloadDStream_internal(BIT_DStream_t* bitD)
384
+ {
385
+ assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
386
+ bitD->ptr -= bitD->bitsConsumed >> 3;
387
+ assert(bitD->ptr >= bitD->start);
388
+ bitD->bitsConsumed &= 7;
389
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
390
+ return BIT_DStream_unfinished;
391
+ }
392
+
377
393
  /*! BIT_reloadDStreamFast() :
378
394
  * Similar to BIT_reloadDStream(), but with two differences:
379
395
  * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
@@ -384,31 +400,35 @@ MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
384
400
  {
385
401
  if (UNLIKELY(bitD->ptr < bitD->limitPtr))
386
402
  return BIT_DStream_overflow;
387
- assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
388
- bitD->ptr -= bitD->bitsConsumed >> 3;
389
- bitD->bitsConsumed &= 7;
390
- bitD->bitContainer = MEM_readLEST(bitD->ptr);
391
- return BIT_DStream_unfinished;
403
+ return BIT_reloadDStream_internal(bitD);
392
404
  }
393
405
 
394
406
  /*! BIT_reloadDStream() :
395
407
  * Refill `bitD` from buffer previously set in BIT_initDStream() .
396
- * This function is safe, it guarantees it will not read beyond src buffer.
408
+ * This function is safe, it guarantees it will not never beyond src buffer.
397
409
  * @return : status of `BIT_DStream_t` internal register.
398
410
  * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
399
- MEM_STATIC FORCE_INLINE_ATTR BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
411
+ FORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
400
412
  {
401
- if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
413
+ /* note : once in overflow mode, a bitstream remains in this mode until it's reset */
414
+ if (UNLIKELY(bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))) {
415
+ static const BitContainerType zeroFilled = 0;
416
+ bitD->ptr = (const char*)&zeroFilled; /* aliasing is allowed for char */
417
+ /* overflow detected, erroneous scenario or end of stream: no update */
402
418
  return BIT_DStream_overflow;
419
+ }
420
+
421
+ assert(bitD->ptr >= bitD->start);
403
422
 
404
423
  if (bitD->ptr >= bitD->limitPtr) {
405
- return BIT_reloadDStreamFast(bitD);
424
+ return BIT_reloadDStream_internal(bitD);
406
425
  }
407
426
  if (bitD->ptr == bitD->start) {
427
+ /* reached end of bitStream => no update */
408
428
  if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
409
429
  return BIT_DStream_completed;
410
430
  }
411
- /* start < ptr < limitPtr */
431
+ /* start < ptr < limitPtr => cautious update */
412
432
  { U32 nbBytes = bitD->bitsConsumed >> 3;
413
433
  BIT_DStream_status result = BIT_DStream_unfinished;
414
434
  if (bitD->ptr - nbBytes < bitD->start) {
@@ -11,6 +11,8 @@
11
11
  #ifndef ZSTD_COMPILER_H
12
12
  #define ZSTD_COMPILER_H
13
13
 
14
+ #include <stddef.h>
15
+
14
16
  #include "portability_macros.h"
15
17
 
16
18
  /*-*******************************************************
@@ -51,12 +53,19 @@
51
53
  # define WIN_CDECL
52
54
  #endif
53
55
 
56
+ /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
57
+ #if defined(__GNUC__)
58
+ # define UNUSED_ATTR __attribute__((unused))
59
+ #else
60
+ # define UNUSED_ATTR
61
+ #endif
62
+
54
63
  /**
55
64
  * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
56
65
  * parameters. They must be inlined for the compiler to eliminate the constant
57
66
  * branches.
58
67
  */
59
- #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
68
+ #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR
60
69
  /**
61
70
  * HINT_INLINE is used to help the compiler generate better code. It is *not*
62
71
  * used for "templates", so it can be tweaked based on the compilers
@@ -71,14 +80,28 @@
71
80
  #if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
72
81
  # define HINT_INLINE static INLINE_KEYWORD
73
82
  #else
74
- # define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
83
+ # define HINT_INLINE FORCE_INLINE_TEMPLATE
75
84
  #endif
76
85
 
77
- /* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
86
+ /* "soft" inline :
87
+ * The compiler is free to select if it's a good idea to inline or not.
88
+ * The main objective is to silence compiler warnings
89
+ * when a defined function in included but not used.
90
+ *
91
+ * Note : this macro is prefixed `MEM_` because it used to be provided by `mem.h` unit.
92
+ * Updating the prefix is probably preferable, but requires a fairly large codemod,
93
+ * since this name is used everywhere.
94
+ */
95
+ #ifndef MEM_STATIC /* already defined in Linux Kernel mem.h */
78
96
  #if defined(__GNUC__)
79
- # define UNUSED_ATTR __attribute__((unused))
97
+ # define MEM_STATIC static __inline UNUSED_ATTR
98
+ #elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
99
+ # define MEM_STATIC static inline
100
+ #elif defined(_MSC_VER)
101
+ # define MEM_STATIC static __inline
80
102
  #else
81
- # define UNUSED_ATTR
103
+ # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */
104
+ #endif
82
105
  #endif
83
106
 
84
107
  /* force no inlining */
@@ -109,10 +132,10 @@
109
132
  /* prefetch
110
133
  * can be disabled, by declaring NO_PREFETCH build macro */
111
134
  #if defined(NO_PREFETCH)
112
- # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
113
- # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
135
+ # define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */
136
+ # define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */
114
137
  #else
115
- # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) /* _mm_prefetch() is not defined outside of x86/x64 */
138
+ # if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC) /* _mm_prefetch() is not defined outside of x86/x64 */
116
139
  # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
117
140
  # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
118
141
  # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)
@@ -120,24 +143,25 @@
120
143
  # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
121
144
  # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
122
145
  # elif defined(__aarch64__)
123
- # define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
124
- # define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
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)
125
148
  # else
126
- # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
127
- # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
149
+ # define PREFETCH_L1(ptr) do { (void)(ptr); } while (0) /* disabled */
150
+ # define PREFETCH_L2(ptr) do { (void)(ptr); } while (0) /* disabled */
128
151
  # endif
129
152
  #endif /* NO_PREFETCH */
130
153
 
131
154
  #define CACHELINE_SIZE 64
132
155
 
133
- #define PREFETCH_AREA(p, s) { \
134
- const char* const _ptr = (const char*)(p); \
135
- size_t const _size = (size_t)(s); \
136
- size_t _pos; \
137
- for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
138
- PREFETCH_L2(_ptr + _pos); \
139
- } \
140
- }
156
+ #define PREFETCH_AREA(p, s) \
157
+ do { \
158
+ const char* const _ptr = (const char*)(p); \
159
+ size_t const _size = (size_t)(s); \
160
+ size_t _pos; \
161
+ for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
162
+ PREFETCH_L2(_ptr + _pos); \
163
+ } \
164
+ } while (0)
141
165
 
142
166
  /* vectorization
143
167
  * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
@@ -166,9 +190,9 @@
166
190
  #endif
167
191
 
168
192
  #if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
169
- # define ZSTD_UNREACHABLE { assert(0), __builtin_unreachable(); }
193
+ # define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0)
170
194
  #else
171
- # define ZSTD_UNREACHABLE { assert(0); }
195
+ # define ZSTD_UNREACHABLE do { assert(0); } while (0)
172
196
  #endif
173
197
 
174
198
  /* disable warnings */
@@ -281,6 +305,74 @@
281
305
  * Sanitizer
282
306
  *****************************************************************/
283
307
 
308
+ /**
309
+ * Zstd relies on pointer overflow in its decompressor.
310
+ * We add this attribute to functions that rely on pointer overflow.
311
+ */
312
+ #ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
313
+ # if __has_attribute(no_sanitize)
314
+ # if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8
315
+ /* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */
316
+ # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("signed-integer-overflow")))
317
+ # else
318
+ /* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */
319
+ # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize("pointer-overflow")))
320
+ # endif
321
+ # else
322
+ # define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
323
+ # endif
324
+ #endif
325
+
326
+ /**
327
+ * Helper function to perform a wrapped pointer difference without trigging
328
+ * UBSAN.
329
+ *
330
+ * @returns lhs - rhs with wrapping
331
+ */
332
+ MEM_STATIC
333
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
334
+ ptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs)
335
+ {
336
+ return lhs - rhs;
337
+ }
338
+
339
+ /**
340
+ * Helper function to perform a wrapped pointer add without triggering UBSAN.
341
+ *
342
+ * @return ptr + add with wrapping
343
+ */
344
+ MEM_STATIC
345
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
346
+ unsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add)
347
+ {
348
+ return ptr + add;
349
+ }
350
+
351
+ /**
352
+ * Helper function to perform a wrapped pointer subtraction without triggering
353
+ * UBSAN.
354
+ *
355
+ * @return ptr - sub with wrapping
356
+ */
357
+ MEM_STATIC
358
+ ZSTD_ALLOW_POINTER_OVERFLOW_ATTR
359
+ unsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub)
360
+ {
361
+ return ptr - sub;
362
+ }
363
+
364
+ /**
365
+ * Helper function to add to a pointer that works around C's undefined behavior
366
+ * of adding 0 to NULL.
367
+ *
368
+ * @returns `ptr + add` except it defines `NULL + 0 == NULL`.
369
+ */
370
+ MEM_STATIC
371
+ unsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add)
372
+ {
373
+ return add > 0 ? ptr + add : ptr;
374
+ }
375
+
284
376
  /* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an
285
377
  * abundance of caution, disable our custom poisoning on mingw. */
286
378
  #ifdef __MINGW32__
@@ -35,6 +35,7 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
35
35
  U32 f7b = 0;
36
36
  U32 f7c = 0;
37
37
  #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
38
+ #if !defined(__clang__)
38
39
  int reg[4];
39
40
  __cpuid((int*)reg, 0);
40
41
  {
@@ -50,6 +51,41 @@ MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
50
51
  f7c = (U32)reg[2];
51
52
  }
52
53
  }
54
+ #else
55
+ /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
56
+ * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
57
+ * to due to being a reserved register. So in that case, do the `cpuid`
58
+ * ourselves. Clang supports inline assembly anyway.
59
+ */
60
+ U32 n;
61
+ __asm__(
62
+ "pushq %%rbx\n\t"
63
+ "cpuid\n\t"
64
+ "popq %%rbx\n\t"
65
+ : "=a"(n)
66
+ : "a"(0)
67
+ : "rcx", "rdx");
68
+ if (n >= 1) {
69
+ U32 f1a;
70
+ __asm__(
71
+ "pushq %%rbx\n\t"
72
+ "cpuid\n\t"
73
+ "popq %%rbx\n\t"
74
+ : "=a"(f1a), "=c"(f1c), "=d"(f1d)
75
+ : "a"(1)
76
+ :);
77
+ }
78
+ if (n >= 7) {
79
+ __asm__(
80
+ "pushq %%rbx\n\t"
81
+ "cpuid\n\t"
82
+ "movq %%rbx, %%rax\n\t"
83
+ "popq %%rbx"
84
+ : "=a"(f7b), "=c"(f7c)
85
+ : "a"(7), "c"(0)
86
+ : "rdx");
87
+ }
88
+ #endif
53
89
  #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
54
90
  /* The following block like the normal cpuid branch below, but gcc
55
91
  * reserves ebx for use of its pic register so we must specially
@@ -21,4 +21,10 @@
21
21
 
22
22
  #include "debug.h"
23
23
 
24
+ #if !defined(ZSTD_LINUX_KERNEL) || (DEBUGLEVEL>=2)
25
+ /* We only use this when DEBUGLEVEL>=2, but we get -Werror=pedantic errors if a
26
+ * translation unit is empty. So remove this from Linux kernel builds, but
27
+ * otherwise just leave it in.
28
+ */
24
29
  int g_debuglevel = DEBUGLEVEL;
30
+ #endif
@@ -85,18 +85,27 @@ extern int g_debuglevel; /* the variable is only declared,
85
85
  It's useful when enabling very verbose levels
86
86
  on selective conditions (such as position in src) */
87
87
 
88
- # define RAWLOG(l, ...) { \
89
- if (l<=g_debuglevel) { \
90
- ZSTD_DEBUG_PRINT(__VA_ARGS__); \
91
- } }
92
- # define DEBUGLOG(l, ...) { \
93
- if (l<=g_debuglevel) { \
94
- ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
95
- ZSTD_DEBUG_PRINT(" \n"); \
96
- } }
88
+ # define RAWLOG(l, ...) \
89
+ do { \
90
+ if (l<=g_debuglevel) { \
91
+ ZSTD_DEBUG_PRINT(__VA_ARGS__); \
92
+ } \
93
+ } while (0)
94
+
95
+ #define STRINGIFY(x) #x
96
+ #define TOSTRING(x) STRINGIFY(x)
97
+ #define LINE_AS_STRING TOSTRING(__LINE__)
98
+
99
+ # define DEBUGLOG(l, ...) \
100
+ do { \
101
+ if (l<=g_debuglevel) { \
102
+ ZSTD_DEBUG_PRINT(__FILE__ ":" LINE_AS_STRING ": " __VA_ARGS__); \
103
+ ZSTD_DEBUG_PRINT(" \n"); \
104
+ } \
105
+ } while (0)
97
106
  #else
98
- # define RAWLOG(l, ...) {} /* disabled */
99
- # define DEBUGLOG(l, ...) {} /* disabled */
107
+ # define RAWLOG(l, ...) do { } while (0) /* disabled */
108
+ # define DEBUGLOG(l, ...) do { } while (0) /* disabled */
100
109
  #endif
101
110
 
102
111
 
@@ -60,8 +60,13 @@ ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
60
60
  ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
61
61
 
62
62
  /* check and forward error code */
63
- #define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
64
- #define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
63
+ #define CHECK_V_F(e, f) \
64
+ size_t const e = f; \
65
+ do { \
66
+ if (ERR_isError(e)) \
67
+ return e; \
68
+ } while (0)
69
+ #define CHECK_F(f) do { CHECK_V_F(_var_err__, f); } while (0)
65
70
 
66
71
 
67
72
  /*-****************************************
@@ -95,10 +100,12 @@ void _force_has_format_string(const char *format, ...) {
95
100
  * We want to force this function invocation to be syntactically correct, but
96
101
  * we don't want to force runtime evaluation of its arguments.
97
102
  */
98
- #define _FORCE_HAS_FORMAT_STRING(...) \
99
- if (0) { \
100
- _force_has_format_string(__VA_ARGS__); \
101
- }
103
+ #define _FORCE_HAS_FORMAT_STRING(...) \
104
+ do { \
105
+ if (0) { \
106
+ _force_has_format_string(__VA_ARGS__); \
107
+ } \
108
+ } while (0)
102
109
 
103
110
  #define ERR_QUOTE(str) #str
104
111
 
@@ -109,48 +116,50 @@ void _force_has_format_string(const char *format, ...) {
109
116
  * In order to do that (particularly, printing the conditional that failed),
110
117
  * this can't just wrap RETURN_ERROR().
111
118
  */
112
- #define RETURN_ERROR_IF(cond, err, ...) \
113
- if (cond) { \
114
- RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
115
- __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
116
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
117
- RAWLOG(3, ": " __VA_ARGS__); \
118
- RAWLOG(3, "\n"); \
119
- return ERROR(err); \
120
- }
119
+ #define RETURN_ERROR_IF(cond, err, ...) \
120
+ do { \
121
+ if (cond) { \
122
+ RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
123
+ __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
124
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
125
+ RAWLOG(3, ": " __VA_ARGS__); \
126
+ RAWLOG(3, "\n"); \
127
+ return ERROR(err); \
128
+ } \
129
+ } while (0)
121
130
 
122
131
  /**
123
132
  * Unconditionally return the specified error.
124
133
  *
125
134
  * In debug modes, prints additional information.
126
135
  */
127
- #define RETURN_ERROR(err, ...) \
128
- do { \
129
- RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
130
- __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
131
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
132
- RAWLOG(3, ": " __VA_ARGS__); \
133
- RAWLOG(3, "\n"); \
134
- return ERROR(err); \
135
- } while(0);
136
+ #define RETURN_ERROR(err, ...) \
137
+ do { \
138
+ RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
139
+ __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
140
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
141
+ RAWLOG(3, ": " __VA_ARGS__); \
142
+ RAWLOG(3, "\n"); \
143
+ return ERROR(err); \
144
+ } while(0)
136
145
 
137
146
  /**
138
147
  * If the provided expression evaluates to an error code, returns that error code.
139
148
  *
140
149
  * In debug modes, prints additional information.
141
150
  */
142
- #define FORWARD_IF_ERROR(err, ...) \
143
- do { \
144
- size_t const err_code = (err); \
145
- if (ERR_isError(err_code)) { \
146
- RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
147
- __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
148
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
149
- RAWLOG(3, ": " __VA_ARGS__); \
150
- RAWLOG(3, "\n"); \
151
- return err_code; \
152
- } \
153
- } while(0);
151
+ #define FORWARD_IF_ERROR(err, ...) \
152
+ do { \
153
+ size_t const err_code = (err); \
154
+ if (ERR_isError(err_code)) { \
155
+ RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
156
+ __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
157
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
158
+ RAWLOG(3, ": " __VA_ARGS__); \
159
+ RAWLOG(3, "\n"); \
160
+ return err_code; \
161
+ } \
162
+ } while(0)
154
163
 
155
164
  #if defined (__cplusplus)
156
165
  }