]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Add WITH_C_FALLBACK
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Sat, 27 Sep 2025 14:54:59 +0000 (16:54 +0200)
committerHans Kristian Rosbach <hk-git@circlestorm.org>
Sat, 27 Sep 2025 14:54:59 +0000 (16:54 +0200)
CMakeLists.txt
arch/generic/crc32_braid_c.c
functable.c
test/benchmarks/benchmark_adler32_copy.cc
test/benchmarks/benchmark_crc32.cc
test/benchmarks/benchmark_slidehash.cc
test/test_adler32.cc
test/test_crc32.cc

index d16336464b3b5516bf81f1909a83a9bb2ab568fd..5f43a2302b9b2701882892ed529dc630e8dd10b4 100644 (file)
@@ -104,6 +104,10 @@ option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF)
 option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF)
 option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF)
 
+option(WITH_C_FALLBACK "Build with C fallback functions.
+Causes abort() on init if optimized functions are missing!
+Currently known safe on X86-64 if WITH_OPTIM and WITH_SSE2 is on." ON)
+
 set(ZLIB_SYMBOL_PREFIX "" CACHE STRING "Give this prefix to all publicly exported symbols.
 Useful when embedding into a larger library.
 Default is no prefix (empty prefix).")
@@ -153,6 +157,7 @@ option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF)
 mark_as_advanced(FORCE
     ZLIB_SYMBOL_PREFIX
     WITH_REDUCED_MEM
+    WITH_C_FALLBACK
     WITH_CRC32_CHORBA
     WITH_ARMV8 WITH_NEON
     WITH_ARMV6
@@ -195,6 +200,14 @@ if(NOT WITH_CRC32_CHORBA)
     add_definitions(-DWITHOUT_CHORBA)
 endif()
 
+if(${ARCH} MATCHES "x86_64")
+
+endif()
+
+if(NOT WITH_C_FALLBACK)
+    add_definitions(-DNO_C_FALLBACK=1)
+endif()
+
 if(CMAKE_C_COMPILER_ID MATCHES "^Intel")
     if(CMAKE_HOST_UNIX)
         set(WARNFLAGS -Wall)
@@ -1277,15 +1290,19 @@ set(ZLIB_PRIVATE_HDRS
     zutil.h
     zutil_p.h
 )
-set(ZLIB_SRCS
+set(ZLIB_C_FALLBACK_SRCS
     arch/generic/adler32_c.c
     arch/generic/adler32_fold_c.c
     arch/generic/chunkset_c.c
     arch/generic/compare256_c.c
-    arch/generic/crc32_braid_c.c
     arch/generic/crc32_c.c
+    arch/generic/crc32_braid_c.c
     arch/generic/crc32_fold_c.c
     arch/generic/slide_hash_c.c
+)
+
+
+set(ZLIB_SRCS
     adler32.c
     compress.c
     crc32.c
@@ -1311,6 +1328,9 @@ set(ZLIB_SRCS
 
 if(WITH_CRC32_CHORBA)
     list(APPEND ZLIB_SRCS arch/generic/crc32_chorba_c.c)
+    if(NOT WITH_C_FALLBACK)
+        list(APPEND ZLIB_SRCS arch/generic/crc32_braid_c.c)
+    endif()
 endif()
 
 if(WITH_RUNTIME_CPU_DETECTION)
@@ -1332,6 +1352,10 @@ if(WITH_GZFILEOP)
     list(APPEND ZLIB_ALL_SRCS ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS})
 endif()
 
+if(WITH_C_FALLBACK)
+    list(APPEND ZLIB_ALL_SRCS ${ZLIB_C_FALLBACK_SRCS})
+endif()
+
 if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)
     set(ZLIB_DLL_SRCS win32/zlib${SUFFIX}1.rc)
 endif()
@@ -1553,6 +1577,7 @@ add_feature_info(WITH_GTEST WITH_GTEST "Build gtest_zlib")
 add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
 add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks")
 add_feature_info(WITH_BENCHMARK_APPS WITH_BENCHMARK_APPS "Build application benchmarks")
+add_feature_info(WITH_C_FALLBACK WITH_C_FALLBACK "Build with C fallbacks")
 add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
 add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
 add_feature_info(WITH_CRC32_CHORBA WITH_CRC32_CHORBA "Use optimized CRC32 algorithm Chorba")
index 40c5610595b36f381f805ffc8be19c3d0fef5fe2..efa3b1b68ce72d872a32144ce1b898341fb7cebe 100644 (file)
@@ -212,6 +212,7 @@ Z_INTERNAL uint32_t crc32_braid_internal(uint32_t c, const uint8_t *buf, size_t
     return c;
 }
 
+#ifndef NO_C_FALLBACK
 Z_INTERNAL uint32_t crc32_braid(uint32_t c, const uint8_t *buf, size_t len) {
     c = (~c) & 0xffffffff;
 
@@ -220,3 +221,4 @@ Z_INTERNAL uint32_t crc32_braid(uint32_t c, const uint8_t *buf, size_t len) {
     /* Return the CRC, post-conditioned. */
     return c ^ 0xffffffff;
 }
+#endif
index dd6400df3f92c08660140034303e857b26c97fbe..78104b23c4dcc66d0c39a48dbf98479e63195c77 100644 (file)
@@ -13,6 +13,7 @@
 #include "functable.h"
 #include "cpu_features.h"
 #include "arch_functions.h"
+#include <stdio.h>
 
 /* Platform has pointer size atomic store */
 #if defined(__GNUC__) || defined(__clang__)
 #  define FUNCTABLE_BARRIER() do { /* Empty */ } while (0)
 #endif
 
+// Verify all pointers are valid before assigning, abort on failure
+#define FUNCTABLE_VERIFY_ASSIGN(VAR, FUNC_NAME) \
+    if (!VAR.FUNC_NAME) { \
+        fprintf(stderr, "Functable entry not set!\n"); \
+        abort(); \
+    } \
+    FUNCTABLE_ASSIGN(VAR, FUNC_NAME);
+
+
 static void force_init_empty(void) {
     // empty
 }
@@ -48,8 +58,10 @@ static void init_functable(void) {
 
     cpu_check_features(&cf);
 
-    // Generic code
     ft.force_init = &force_init_empty;
+
+#ifndef NO_C_FALLBACK
+    // Generic code
     ft.adler32 = &adler32_c;
     ft.adler32_fold_copy = &adler32_fold_copy_c;
     ft.chunkmemset_safe = &chunkmemset_safe_c;
@@ -64,6 +76,7 @@ static void init_functable(void) {
     ft.longest_match = &longest_match_c;
     ft.longest_match_slow = &longest_match_slow_c;
     ft.compare256 = &compare256_c;
+#endif
 
     // Select arch-optimized functions
 
@@ -309,21 +322,21 @@ static void init_functable(void) {
 #endif
 
     // Assign function pointers individually for atomic operation
-    FUNCTABLE_ASSIGN(ft, force_init);
-    FUNCTABLE_ASSIGN(ft, adler32);
-    FUNCTABLE_ASSIGN(ft, adler32_fold_copy);
-    FUNCTABLE_ASSIGN(ft, chunkmemset_safe);
-    FUNCTABLE_ASSIGN(ft, chunksize);
-    FUNCTABLE_ASSIGN(ft, compare256);
-    FUNCTABLE_ASSIGN(ft, crc32);
-    FUNCTABLE_ASSIGN(ft, crc32_fold);
-    FUNCTABLE_ASSIGN(ft, crc32_fold_copy);
-    FUNCTABLE_ASSIGN(ft, crc32_fold_final);
-    FUNCTABLE_ASSIGN(ft, crc32_fold_reset);
-    FUNCTABLE_ASSIGN(ft, inflate_fast);
-    FUNCTABLE_ASSIGN(ft, longest_match);
-    FUNCTABLE_ASSIGN(ft, longest_match_slow);
-    FUNCTABLE_ASSIGN(ft, slide_hash);
+    FUNCTABLE_VERIFY_ASSIGN(ft, force_init);
+    FUNCTABLE_VERIFY_ASSIGN(ft, adler32);
+    FUNCTABLE_VERIFY_ASSIGN(ft, adler32_fold_copy);
+    FUNCTABLE_VERIFY_ASSIGN(ft, chunkmemset_safe);
+    FUNCTABLE_VERIFY_ASSIGN(ft, chunksize);
+    FUNCTABLE_VERIFY_ASSIGN(ft, compare256);
+    FUNCTABLE_VERIFY_ASSIGN(ft, crc32);
+    FUNCTABLE_VERIFY_ASSIGN(ft, crc32_fold);
+    FUNCTABLE_VERIFY_ASSIGN(ft, crc32_fold_copy);
+    FUNCTABLE_VERIFY_ASSIGN(ft, crc32_fold_final);
+    FUNCTABLE_VERIFY_ASSIGN(ft, crc32_fold_reset);
+    FUNCTABLE_VERIFY_ASSIGN(ft, inflate_fast);
+    FUNCTABLE_VERIFY_ASSIGN(ft, longest_match);
+    FUNCTABLE_VERIFY_ASSIGN(ft, longest_match_slow);
+    FUNCTABLE_VERIFY_ASSIGN(ft, slide_hash);
 
     // Memory barrier for weak memory order CPUs
     FUNCTABLE_BARRIER();
index 2027904af529fa62dbf93207dcae2bf125824fa4..610c1c55353dbb9d7fd00c49d3bc76feda7bc342 100644 (file)
@@ -84,7 +84,9 @@ public:
     } \
     BENCHMARK_REGISTER_F(adler32_copy, name)->Range(8192, MAX_RANDOM_INTS_SIZE);
 
+#ifndef NO_C_FALLBACK
 BENCHMARK_ADLER32_BASELINE_COPY(c, adler32_c, 1);
+#endif
 
 #ifdef DISABLE_RUNTIME_CPU_DETECTION
 BENCHMARK_ADLER32_BASELINE_COPY(native, native_adler32, 1);
index 1e95b27770522ceb9a23bea590d4d46701e52c0d..d308ce2debadc6557ed9992eb9fa47842d13035d 100644 (file)
@@ -56,13 +56,15 @@ public:
     } \
     BENCHMARK_REGISTER_F(crc32, name)->Arg(1)->Arg(8)->Arg(12)->Arg(16)->Arg(32)->Arg(64)->Arg(512)->Arg(4<<10)->Arg(32<<10)->Arg(256<<10)->Arg(4096<<10);
 
-#ifndef WITHOUT_CHORBA
-BENCHMARK_CRC32(generic_chorba, crc32_c, 1);
-#else
-BENCHMARK_CRC32(generic, crc32_c, 1);
-#endif
+#ifndef NO_C_FALLBACK
+#   ifndef WITHOUT_CHORBA
+        BENCHMARK_CRC32(generic_chorba, crc32_c, 1);
+#   else
+        BENCHMARK_CRC32(generic, crc32_c, 1);
+#   endif
 
-BENCHMARK_CRC32(braid, crc32_braid, 1);
+    BENCHMARK_CRC32(braid, crc32_braid, 1);
+#endif
 
 #ifdef DISABLE_RUNTIME_CPU_DETECTION
 BENCHMARK_CRC32(native, native_crc32, 1);
index 53e9516817770141a7e4d03d53de7b15143d03cf..7348e4d1129cc7a551aaf3328eacf1e01e96cd71 100644 (file)
@@ -68,7 +68,9 @@ public:
     } \
     BENCHMARK_REGISTER_F(slide_hash, name)->RangeMultiplier(2)->Range(512, MAX_RANDOM_INTS);
 
+#ifndef NO_C_FALLBACK
 BENCHMARK_SLIDEHASH(c, slide_hash_c, 1);
+#endif
 
 #ifdef DISABLE_RUNTIME_CPU_DETECTION
 BENCHMARK_SLIDEHASH(native, native_slide_hash, 1);
index c52122c43d702efe75f5e4f59b4d01deeabfd305..5a5912b3385070fc388b866766d1509f18abcfca 100644 (file)
@@ -363,7 +363,9 @@ INSTANTIATE_TEST_SUITE_P(adler32, adler32_variant, testing::ValuesIn(tests));
         hash(GetParam(), func); \
     }
 
+#ifndef NO_C_FALLBACK
 TEST_ADLER32(c, adler32_c, 1)
+#endif
 
 #ifdef DISABLE_RUNTIME_CPU_DETECTION
 TEST_ADLER32(native, native_adler32, 1)
index d44d079e9791dd9f214f59f0bbf1896a35fa0743..1b728e7ca3f2f58d99945d6f4ba8522ca988c65e 100644 (file)
@@ -269,13 +269,15 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests));
         hash(func); \
     }
 
-#ifndef WITHOUT_CHORBA
-TEST_CRC32(generic_chorba, crc32_c, 1)
-#else
-TEST_CRC32(generic, crc32_c, 1)
-#endif
+#ifndef NO_C_FALLBACK
+#   ifndef WITHOUT_CHORBA
+        TEST_CRC32(generic_chorba, crc32_c, 1)
+#   else
+        TEST_CRC32(generic, crc32_c, 1)
+#   endif
 
-TEST_CRC32(braid, crc32_braid, 1)
+    TEST_CRC32(braid, crc32_braid, 1)
+#endif
 
 #ifdef DISABLE_RUNTIME_CPU_DETECTION
 TEST_CRC32(native, native_crc32, 1)