Coverage Report

Created: 2026-11-12 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zlib-ng/functable.c
Line
Count
Source
1
/* functable.c -- Choose relevant optimized functions at runtime
2
 * Copyright (C) 2017 Hans Kristian Rosbach
3
 * For conditions of distribution and use, see copyright notice in zlib.h
4
 */
5
#ifndef DISABLE_RUNTIME_CPU_DETECTION
6
7
#include "zbuild.h"
8
9
#if defined(_MSC_VER)
10
#  include <intrin.h>
11
#endif
12
13
#include "functable.h"
14
#include "cpu_features.h"
15
#include "arch_functions.h"
16
17
/* Platform has pointer size atomic store */
18
#if defined(__GNUC__) || defined(__clang__)
19
#  define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \
20
28
    __atomic_store(&(functable.FUNC_NAME), &(VAR.FUNC_NAME), __ATOMIC_SEQ_CST)
21
2
#  define FUNCTABLE_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST)
22
#elif defined(_MSC_VER)
23
#  define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \
24
    _InterlockedExchangePointer((void * volatile *)&(functable.FUNC_NAME), (void *)(VAR.FUNC_NAME))
25
#  ifdef ARCH_ARM
26
#    define FUNCTABLE_BARRIER() do { \
27
    _ReadWriteBarrier();  \
28
    __dmb(0xB); /* _ARM_BARRIER_ISH */ \
29
    _ReadWriteBarrier(); \
30
} while (0)
31
#  else
32
#    define FUNCTABLE_BARRIER() _ReadWriteBarrier()
33
#  endif
34
#else
35
#  warning Unable to detect atomic intrinsic support.
36
#  define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \
37
    *((void * volatile *)&(functable.FUNC_NAME)) = (void *)(VAR.FUNC_NAME)
38
#  define FUNCTABLE_BARRIER() do { /* Empty */ } while (0)
39
#endif
40
41
/* Verify all pointers are valid before assigning, return 1 on failure
42
 * This allows inflateinit/deflateinit functions to gracefully return Z_VERSION_ERROR
43
 * if functable initialization fails.
44
 */
45
#define FUNCTABLE_VERIFY_ASSIGN(VAR, FUNC_NAME) \
46
26
    if (!VAR.FUNC_NAME) { \
47
0
        fprintf(stderr, "Zlib-ng functable failed initialization!\n"); \
48
0
        return 1; \
49
0
    } \
50
26
    FUNCTABLE_ASSIGN(VAR, FUNC_NAME);
51
52
/* Functable init & abort on failure.
53
 * Abort is needed because some stub functions are reachable without first
54
 * calling any inflateinit/deflateinit functions, and have no error propagation.
55
 */
56
#define FUNCTABLE_INIT_ABORT \
57
2
    if (init_functable()) { \
58
0
        fprintf(stderr, "Zlib-ng functable failed initialization!\n"); \
59
0
        abort(); \
60
2
    };
61
62
// Empty stub, used when functable has already been initialized
63
7.44k
static int force_init_empty(void) {
64
7.44k
    return 0;
65
7.44k
}
66
67
/* Functable initialization.
68
 * Selects the best available optimized functions appropriate for the runtime cpu.
69
 */
70
2
static int init_functable(void) {
71
2
    struct functable_s ft;
72
2
    struct cpu_features cf;
73
74
2
    memset(&ft, 0, sizeof(struct functable_s));
75
2
    cpu_check_features(&cf);
76
2
    ft.force_init = &force_init_empty;
77
78
    // Only use necessary generic functions when no suitable simd versions are available.
79
2
#ifdef ADLER32_FALLBACK
80
2
    ft.adler32 = &adler32_c;
81
2
    ft.adler32_copy = &adler32_copy_c;
82
2
#endif
83
#ifdef CHUNKSET_FALLBACK
84
    ft.chunkmemset_safe = &chunkmemset_safe_c;
85
    ft.inflate_fast = &inflate_fast_c;
86
    ft.inflate_fast_safe = &inflate_fast_safe_c;
87
#endif
88
#ifdef COMPARE256_FALLBACK
89
    ft.compare256 = &compare256_c;
90
    ft.longest_match = &longest_match_c;
91
    ft.longest_match_slow_knuth = &longest_match_slow_knuth_c;
92
    ft.longest_match_slow_roll = &longest_match_slow_roll_c;
93
#endif
94
2
#ifdef CRC32_BRAID_FALLBACK
95
2
    ft.crc32 = &crc32_braid;
96
2
    ft.crc32_copy = &crc32_copy_braid;
97
2
#endif
98
#ifdef SLIDE_HASH_FALLBACK
99
    ft.slide_hash = &slide_hash_c;
100
    ft.slide_hash_head = &slide_hash_head_c;
101
#endif
102
103
    // Select arch-optimized functions
104
2
#ifdef WITH_OPTIM
105
106
    // Chorba generic C fallback
107
2
#ifdef CRC32_CHORBA_FALLBACK
108
2
    ft.crc32 = &crc32_chorba;
109
2
    ft.crc32_copy = &crc32_copy_chorba;
110
2
#endif
111
112
    // X86 - SSE2
113
2
#ifdef X86_SSE2
114
#  ifndef X86_SSE2_NATIVE
115
    if (cf.x86.has_sse2)
116
#  endif
117
2
    {
118
2
#  ifndef X86_AVX2_NATIVE
119
2
        ft.chunkmemset_safe = &chunkmemset_safe_sse2;
120
2
        ft.compare256 = &compare256_sse2;
121
2
        ft.inflate_fast = &inflate_fast_sse2;
122
2
        ft.inflate_fast_safe = &inflate_fast_safe_sse2;
123
2
        ft.longest_match = &longest_match_sse2;
124
2
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_sse2;
125
2
        ft.longest_match_slow_roll = &longest_match_slow_roll_sse2;
126
2
        ft.slide_hash = &slide_hash_sse2;
127
2
        ft.slide_hash_head = &slide_hash_head_sse2;
128
2
#  endif
129
2
#  if defined(CRC32_CHORBA_SSE_FALLBACK) && !defined(X86_SSE41_NATIVE) && !defined(X86_PCLMULQDQ_NATIVE)
130
2
        ft.crc32 = &crc32_chorba_sse2;
131
2
        ft.crc32_copy = &crc32_copy_chorba_sse2;
132
2
#  endif
133
2
    }
134
2
#endif
135
    // X86 - SSSE3
136
2
#ifdef X86_SSSE3
137
2
#  ifndef X86_SSSE3_NATIVE
138
2
    if (cf.x86.has_ssse3)
139
2
#  endif
140
2
    {
141
2
        ft.adler32 = &adler32_ssse3;
142
2
        ft.adler32_copy = &adler32_copy_ssse3;
143
2
#  ifndef X86_AVX2_NATIVE
144
2
        ft.chunkmemset_safe = &chunkmemset_safe_ssse3;
145
2
        ft.inflate_fast = &inflate_fast_ssse3;
146
2
        ft.inflate_fast_safe = &inflate_fast_safe_ssse3;
147
2
#  endif
148
2
    }
149
2
#endif
150
151
    // X86 - SSE4.1
152
2
#if defined(X86_SSE41) && !defined(X86_PCLMULQDQ_NATIVE)
153
2
#  ifndef X86_SSE41_NATIVE
154
2
    if (cf.x86.has_sse41)
155
2
#  endif
156
2
    {
157
2
#  ifdef CRC32_CHORBA_SSE_FALLBACK
158
2
        ft.crc32 = &crc32_chorba_sse41;
159
2
        ft.crc32_copy = &crc32_copy_chorba_sse41;
160
2
#  endif
161
2
    }
162
2
#endif
163
164
    // X86 - SSE4.2
165
2
#if defined(X86_SSE42) && !defined(X86_AVX512_NATIVE)
166
2
#  ifndef X86_SSE42_NATIVE
167
2
    if (cf.x86.has_sse42)
168
2
#  endif
169
2
    {
170
2
        ft.adler32_copy = &adler32_copy_sse42;
171
2
    }
172
2
#endif
173
    // X86 - PCLMUL
174
2
#if defined(X86_PCLMULQDQ_CRC) && !defined(X86_VPCLMULQDQ_NATIVE)
175
2
#  ifndef X86_PCLMULQDQ_NATIVE
176
2
    if (cf.x86.has_pclmulqdq)
177
2
#  endif
178
2
    {
179
2
        ft.crc32 = &crc32_pclmulqdq;
180
2
        ft.crc32_copy = &crc32_copy_pclmulqdq;
181
2
    }
182
2
#endif
183
    // X86 - AVX2
184
2
#ifdef X86_AVX2
185
    /* BMI2 support is all but implicit with AVX2 but let's sanity check this just in case. Enabling BMI2 allows for
186
     * flagless shifts, resulting in fewer flag stalls for the pipeline, and allows us to set destination registers
187
     * for the shift results as an operand, eliminating several register-register moves when the original value needs
188
     * to remain intact. They also allow for a count operand that isn't the CL register, avoiding contention there */
189
2
#  ifndef X86_AVX2_NATIVE
190
2
    if (cf.x86.has_avx2 && cf.x86.has_bmi2)
191
2
#  endif
192
2
    {
193
2
#  ifndef X86_AVX512_NATIVE
194
2
        ft.adler32 = &adler32_avx2;
195
2
        ft.adler32_copy = &adler32_copy_avx2;
196
2
        ft.chunkmemset_safe = &chunkmemset_safe_avx2;
197
2
        ft.compare256 = &compare256_avx2;
198
2
        ft.inflate_fast = &inflate_fast_avx2;
199
2
        ft.inflate_fast_safe = &inflate_fast_safe_avx2;
200
2
        ft.longest_match = &longest_match_avx2;
201
2
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_avx2;
202
2
        ft.longest_match_slow_roll = &longest_match_slow_roll_avx2;
203
2
#  endif
204
2
        ft.slide_hash = &slide_hash_avx2;
205
2
        ft.slide_hash_head = &slide_hash_head_avx2;
206
2
    }
207
2
#endif
208
2
#ifdef X86_AVX2VNNI
209
2
    if (cf.x86.has_avx2vnni) {
210
0
        ft.adler32 = &adler32_avx2_vnni;
211
        //ft.adler32_copy = &adler32_copy_avx2_vnni;
212
0
    }
213
2
#endif
214
    // X86 - AVX512 (F,DQ,BW,Vl)
215
2
#ifdef X86_AVX512
216
2
#  ifndef X86_AVX512_NATIVE
217
2
    if (cf.x86.has_avx512_common)
218
0
#  endif
219
0
    {
220
0
#  ifndef X86_AVX512VNNI_NATIVE
221
0
        ft.adler32 = &adler32_avx512;
222
0
        ft.adler32_copy = &adler32_copy_avx512;
223
0
#  endif
224
0
        ft.chunkmemset_safe = &chunkmemset_safe_avx512;
225
0
        ft.compare256 = &compare256_avx512;
226
0
        ft.inflate_fast = &inflate_fast_avx512;
227
0
        ft.inflate_fast_safe = &inflate_fast_safe_avx512;
228
0
        ft.longest_match = &longest_match_avx512;
229
0
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_avx512;
230
0
        ft.longest_match_slow_roll = &longest_match_slow_roll_avx512;
231
0
    }
232
2
#endif
233
2
#ifdef X86_AVX512VNNI
234
2
#  ifndef X86_AVX512VNNI_NATIVE
235
2
    if (cf.x86.has_avx512vnni)
236
0
#  endif
237
0
    {
238
0
        ft.adler32 = &adler32_avx512_vnni;
239
0
        ft.adler32_copy = &adler32_copy_avx512_vnni;
240
0
    }
241
2
#endif
242
    // X86 - VPCLMULQDQ (AVX2)
243
2
#ifdef X86_VPCLMULQDQ_AVX2
244
2
#  ifndef X86_VPCLMULQDQ_AVX2_NATIVE
245
2
    if (cf.x86.has_pclmulqdq && cf.x86.has_avx2 && cf.x86.has_vpclmulqdq)
246
0
#  endif
247
0
    {
248
0
        ft.crc32 = &crc32_vpclmulqdq_avx2;
249
0
        ft.crc32_copy = &crc32_copy_vpclmulqdq_avx2;
250
0
    }
251
2
#endif
252
    // X86 - VPCLMULQDQ (AVX-512)
253
2
#ifdef X86_VPCLMULQDQ_AVX512
254
2
#  ifndef X86_VPCLMULQDQ_AVX512_NATIVE
255
2
    if (cf.x86.has_pclmulqdq && cf.x86.has_avx512_common && cf.x86.has_vpclmulqdq)
256
0
#  endif
257
0
    {
258
0
        ft.crc32 = &crc32_vpclmulqdq_avx512;
259
0
        ft.crc32_copy = &crc32_copy_vpclmulqdq_avx512;
260
0
    }
261
2
#endif
262
263
264
    // ARM - SIMD
265
#if defined(ARM_SIMD) && !defined(ARM_NEON_NATIVE)
266
#  ifndef ARM_SIMD_NATIVE
267
    if (cf.arm.has_simd)
268
#  endif
269
    {
270
        ft.slide_hash = &slide_hash_armv6;
271
        ft.slide_hash_head = &slide_hash_head_armv6;
272
    }
273
#endif
274
    // ARM - NEON
275
#ifdef ARM_NEON
276
#  ifndef ARM_NEON_NATIVE
277
    if (cf.arm.has_neon)
278
#  endif
279
    {
280
        ft.adler32 = &adler32_neon;
281
        ft.adler32_copy = &adler32_copy_neon;
282
        ft.chunkmemset_safe = &chunkmemset_safe_neon;
283
        ft.compare256 = &compare256_neon;
284
        ft.inflate_fast = &inflate_fast_neon;
285
        ft.inflate_fast_safe = &inflate_fast_safe_neon;
286
        ft.longest_match = &longest_match_neon;
287
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_neon;
288
        ft.longest_match_slow_roll = &longest_match_slow_roll_neon;
289
        ft.slide_hash = &slide_hash_neon;
290
        ft.slide_hash_head = &slide_hash_head_neon;
291
    }
292
#endif
293
    // ARM - NEON DotProd
294
#ifdef ARM_NEON_DOTPROD
295
#  ifndef ARM_NEON_DOTPROD_NATIVE
296
    if (cf.arm.has_neon && cf.arm.has_dotprod)
297
#  endif
298
    {
299
        ft.adler32 = &adler32_neon_dotprod;
300
        ft.adler32_copy = &adler32_copy_neon_dotprod;
301
    }
302
#endif
303
    // ARM - CRC32
304
#if defined(ARM_CRC32) && !defined(ARM_PMULL_EOR3_NATIVE)
305
#  ifndef ARM_CRC32_NATIVE
306
    if (cf.arm.has_crc32)
307
#  endif
308
    {
309
        ft.crc32 = &crc32_armv8;
310
        ft.crc32_copy = &crc32_copy_armv8;
311
    }
312
#endif
313
    // ARM - PMULL EOR3
314
#ifdef ARM_PMULL_EOR3
315
#  ifndef ARM_PMULL_EOR3_NATIVE
316
    if (cf.arm.has_crc32 && cf.arm.has_pmull && cf.arm.has_eor3 && cf.arm.has_fast_pmull)
317
#  endif
318
    {
319
        ft.crc32 = &crc32_armv8_pmull_eor3;
320
        ft.crc32_copy = &crc32_copy_armv8_pmull_eor3;
321
    }
322
#endif
323
324
325
    // MIPS - MSA
326
#ifdef MIPS_MSA
327
#  ifndef MIPS_MSA_NATIVE
328
    if (cf.mips.has_msa)
329
#  endif
330
    {
331
        ft.adler32 = &adler32_msa;
332
        ft.adler32_copy = &adler32_copy_msa;
333
        ft.slide_hash = &slide_hash_msa;
334
    }
335
#endif
336
337
338
    // Power - VMX
339
#ifdef PPC_VMX
340
#  ifndef PPC_VMX_NATIVE
341
    if (cf.power.has_altivec)
342
#  endif
343
    {
344
        ft.adler32 = &adler32_vmx;
345
        ft.adler32_copy = &adler32_copy_vmx;
346
        ft.slide_hash = &slide_hash_vmx;
347
        ft.slide_hash_head = &slide_hash_head_vmx;
348
    }
349
#endif
350
    // Power8 - VSX
351
#ifdef POWER8_VSX
352
#  ifndef POWER8_VSX_NATIVE
353
    if (cf.power.has_arch_2_07)
354
#  endif
355
    {
356
        ft.adler32 = &adler32_power8;
357
        ft.adler32_copy = &adler32_copy_power8;
358
        ft.chunkmemset_safe = &chunkmemset_safe_power8;
359
        ft.inflate_fast = &inflate_fast_power8;
360
        ft.inflate_fast_safe = &inflate_fast_safe_power8;
361
        ft.slide_hash = &slide_hash_power8;
362
        ft.slide_hash_head = &slide_hash_head_power8;
363
    }
364
#endif
365
#ifdef POWER8_VSX_CRC32
366
#  ifndef POWER8_VSX_CRC32_NATIVE
367
    if (cf.power.has_arch_2_07)
368
#  endif
369
    {
370
        ft.crc32 = &crc32_power8;
371
        ft.crc32_copy = &crc32_copy_power8;
372
    }
373
#endif
374
    // Power9
375
#ifdef POWER9
376
#  ifndef POWER9_NATIVE
377
    if (cf.power.has_arch_3_00)
378
#  endif
379
    {
380
        ft.compare256 = &compare256_power9;
381
        ft.longest_match = &longest_match_power9;
382
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_power9;
383
        ft.longest_match_slow_roll = &longest_match_slow_roll_power9;
384
    }
385
#endif
386
387
388
    // RISCV - RVV
389
#ifdef RISCV_RVV
390
#  ifndef RISCV_RVV_NATIVE
391
    if (cf.riscv.has_rvv)
392
#  endif
393
    {
394
        ft.adler32 = &adler32_rvv;
395
        ft.adler32_copy = &adler32_copy_rvv;
396
        ft.chunkmemset_safe = &chunkmemset_safe_rvv;
397
        ft.compare256 = &compare256_rvv;
398
        ft.inflate_fast = &inflate_fast_rvv;
399
        ft.inflate_fast_safe = &inflate_fast_safe_rvv;
400
        ft.longest_match = &longest_match_rvv;
401
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_rvv;
402
        ft.longest_match_slow_roll = &longest_match_slow_roll_rvv;
403
        ft.slide_hash = &slide_hash_rvv;
404
        ft.slide_hash_head = &slide_hash_head_rvv;
405
    }
406
#endif
407
408
    // RISCV - ZBC
409
#ifdef RISCV_CRC32_ZBC
410
#  ifndef RISCV_ZBC_NATIVE
411
    if (cf.riscv.has_zbc)
412
#  endif
413
    {
414
        ft.crc32 = &crc32_riscv64_zbc;
415
        ft.crc32_copy = &crc32_copy_riscv64_zbc;
416
    }
417
#endif
418
419
    // S390
420
#ifdef S390_VX
421
#  ifndef S390_VX_NATIVE
422
    if (cf.s390.has_vx)
423
#  endif
424
    {
425
        ft.crc32 = &crc32_s390_vx;
426
        ft.crc32_copy = &crc32_copy_s390_vx;
427
        ft.slide_hash = &slide_hash_vx;
428
        ft.slide_hash_head = &slide_hash_head_vx;
429
    }
430
#endif
431
432
    // LOONGARCH
433
#ifdef LOONGARCH_CRC
434
#  ifndef LOONGARCH_CRC_NATIVE
435
    if (cf.loongarch.has_crc)
436
#  endif
437
    {
438
        ft.crc32 = &crc32_loongarch64;
439
        ft.crc32_copy = &crc32_copy_loongarch64;
440
    }
441
#endif
442
#if defined(LOONGARCH_LSX) && !defined(LOONGARCH_LASX_NATIVE)
443
#  ifndef LOONGARCH_LSX_NATIVE
444
    if (cf.loongarch.has_lsx)
445
#  endif
446
    {
447
        ft.adler32 = &adler32_lsx;
448
        ft.adler32_copy = &adler32_copy_lsx;
449
        ft.chunkmemset_safe = &chunkmemset_safe_lsx;
450
        ft.compare256 = &compare256_lsx;
451
        ft.inflate_fast = &inflate_fast_lsx;
452
        ft.inflate_fast_safe = &inflate_fast_safe_lsx;
453
        ft.longest_match = &longest_match_lsx;
454
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_lsx;
455
        ft.longest_match_slow_roll = &longest_match_slow_roll_lsx;
456
        ft.slide_hash = &slide_hash_lsx;
457
        ft.slide_hash_head = &slide_hash_head_lsx;
458
    }
459
#endif
460
#ifdef LOONGARCH_LASX
461
#  ifndef LOONGARCH_LASX_NATIVE
462
    if (cf.loongarch.has_lasx)
463
#  endif
464
    {
465
        ft.adler32 = &adler32_lasx;
466
        ft.adler32_copy = &adler32_copy_lasx;
467
        ft.chunkmemset_safe = &chunkmemset_safe_lasx;
468
        ft.compare256 = &compare256_lasx;
469
        ft.inflate_fast = &inflate_fast_lasx;
470
        ft.inflate_fast_safe = &inflate_fast_safe_lasx;
471
        ft.longest_match = &longest_match_lasx;
472
        ft.longest_match_slow_knuth = &longest_match_slow_knuth_lasx;
473
        ft.longest_match_slow_roll = &longest_match_slow_roll_lasx;
474
        ft.slide_hash = &slide_hash_lasx;
475
        ft.slide_hash_head = &slide_hash_head_lasx;
476
    }
477
#endif
478
479
2
#endif // WITH_OPTIM
480
481
    // Assign function pointers individually for atomic operation
482
2
    FUNCTABLE_ASSIGN(ft, force_init);
483
2
    FUNCTABLE_VERIFY_ASSIGN(ft, adler32);
484
2
    FUNCTABLE_VERIFY_ASSIGN(ft, adler32_copy);
485
2
    FUNCTABLE_VERIFY_ASSIGN(ft, chunkmemset_safe);
486
2
    FUNCTABLE_VERIFY_ASSIGN(ft, compare256);
487
2
    FUNCTABLE_VERIFY_ASSIGN(ft, crc32);
488
2
    FUNCTABLE_VERIFY_ASSIGN(ft, crc32_copy);
489
2
    FUNCTABLE_VERIFY_ASSIGN(ft, inflate_fast);
490
2
    FUNCTABLE_VERIFY_ASSIGN(ft, inflate_fast_safe);
491
2
    FUNCTABLE_VERIFY_ASSIGN(ft, longest_match);
492
2
    FUNCTABLE_VERIFY_ASSIGN(ft, longest_match_slow_knuth);
493
2
    FUNCTABLE_VERIFY_ASSIGN(ft, longest_match_slow_roll);
494
2
    FUNCTABLE_VERIFY_ASSIGN(ft, slide_hash);
495
2
    FUNCTABLE_VERIFY_ASSIGN(ft, slide_hash_head);
496
497
    // Memory barrier for weak memory order CPUs
498
2
    FUNCTABLE_BARRIER();
499
500
2
    return Z_OK;
501
2
}
502
503
#if !defined(_WIN32) && (defined(__GNUC__) || defined(__clang__))
504
2
static void __attribute__((constructor)) functable_constructor(void) {
505
2
    FUNCTABLE_INIT_ABORT;
506
2
}
507
#endif
508
509
/* stub functions */
510
0
static int force_init_stub(void) {
511
0
    return init_functable();
512
0
}
513
514
0
static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) {
515
0
    FUNCTABLE_INIT_ABORT;
516
0
    return functable.adler32(adler, buf, len);
517
0
}
518
519
0
static uint32_t adler32_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) {
520
0
    FUNCTABLE_INIT_ABORT;
521
0
    return functable.adler32_copy(adler, dst, src, len);
522
0
}
523
524
0
static uint8_t* chunkmemset_safe_stub(uint8_t* out, uint8_t *from, size_t len, size_t left) {
525
0
    FUNCTABLE_INIT_ABORT;
526
0
    return functable.chunkmemset_safe(out, from, len, left);
527
0
}
528
529
0
static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) {
530
0
    FUNCTABLE_INIT_ABORT;
531
0
    return functable.compare256(src0, src1);
532
0
}
533
534
0
static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) {
535
0
    FUNCTABLE_INIT_ABORT;
536
0
    return functable.crc32(crc, buf, len);
537
0
}
538
539
0
static uint32_t crc32_copy_stub(uint32_t crc, uint8_t *dst, const uint8_t *src, size_t len) {
540
0
    FUNCTABLE_INIT_ABORT;
541
0
    return functable.crc32_copy(crc, dst, src, len);
542
0
}
543
544
0
static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) {
545
0
    FUNCTABLE_INIT_ABORT;
546
0
    functable.inflate_fast(strm, start);
547
0
}
548
549
0
static void inflate_fast_safe_stub(PREFIX3(stream) *strm, uint32_t start) {
550
0
    FUNCTABLE_INIT_ABORT;
551
0
    functable.inflate_fast_safe(strm, start);
552
0
}
553
554
0
static uint32_t longest_match_stub(deflate_state* const s, uint32_t cur_match) {
555
0
    FUNCTABLE_INIT_ABORT;
556
0
    return functable.longest_match(s, cur_match);
557
0
}
558
559
0
static uint32_t longest_match_slow_knuth_stub(deflate_state* const s, uint32_t cur_match) {
560
0
    FUNCTABLE_INIT_ABORT;
561
0
    return functable.longest_match_slow_knuth(s, cur_match);
562
0
}
563
564
0
static uint32_t longest_match_slow_roll_stub(deflate_state* const s, uint32_t cur_match) {
565
0
    FUNCTABLE_INIT_ABORT;
566
0
    return functable.longest_match_slow_roll(s, cur_match);
567
0
}
568
569
0
static void slide_hash_stub(deflate_state* s) {
570
0
    FUNCTABLE_INIT_ABORT;
571
0
    functable.slide_hash(s);
572
0
}
573
574
0
static void slide_hash_head_stub(deflate_state *s) {
575
0
    FUNCTABLE_INIT_ABORT;
576
0
    functable.slide_hash_head(s);
577
0
}
578
579
/* functable init */
580
Z_INTERNAL struct functable_s functable = {
581
    force_init_stub,
582
    adler32_stub,
583
    adler32_copy_stub,
584
    chunkmemset_safe_stub,
585
    compare256_stub,
586
    crc32_stub,
587
    crc32_copy_stub,
588
    inflate_fast_stub,
589
    inflate_fast_safe_stub,
590
    longest_match_stub,
591
    longest_match_slow_knuth_stub,
592
    longest_match_slow_roll_stub,
593
    slide_hash_stub,
594
    slide_hash_head_stub,
595
};
596
597
#endif