diff --git a/cmake/crc32c.cmake b/cmake/crc32c.cmake index 25f046bb43..b53b119941 100644 --- a/cmake/crc32c.cmake +++ b/cmake/crc32c.cmake @@ -2,25 +2,29 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://opensource.org/license/mit/. -# This file is part of the transition from Autotools to CMake. Once CMake -# support has been merged we should switch to using the upstream CMake -# buildsystem. +# This file handles compiler feature detection for hardware-accelerated CRC32c. +# Include necessary modules for checking compiler features. include(CheckCXXSourceCompiles) include(CheckSourceCompilesWithFlags) -# Check for __builtin_prefetch support in the compiler. +# ----------------------------------------------------------------------------- +# 1. Prefetch Support Checks +# ----------------------------------------------------------------------------- + +# Check for __builtin_prefetch support (GCC/Clang built-in). check_cxx_source_compiles(" int main() { char data = 0; const char* address = &data; + // Check for the ability to issue a data prefetch instruction. __builtin_prefetch(address, 0, 0); return 0; } " HAVE_BUILTIN_PREFETCH ) -# Check for _mm_prefetch support in the compiler. +# Check for _mm_prefetch support (Intel/MSVC intrinsic). check_cxx_source_compiles(" #if defined(_MSC_VER) #include @@ -31,18 +35,27 @@ check_cxx_source_compiles(" int main() { char data = 0; const char* address = &data; + // Check for the specific x86/MSVC intrinsic. _MM_HINT_NTA is a common hint type. _mm_prefetch(address, _MM_HINT_NTA); return 0; } " HAVE_MM_PREFETCH ) -# Check for SSE4.2 support in the compiler. +# ----------------------------------------------------------------------------- +# 2. SSE4.2 Support Check (x86/x64) +# ----------------------------------------------------------------------------- + +# Set flags required to enable SSE4.2 intrinsics. if(MSVC) + # /arch:AVX generally enables all instruction sets up to AVX, which includes SSE4.2. set(SSE42_CXXFLAGS /arch:AVX) else() + # Standard flag for GCC/Clang to enable SSE4.2. set(SSE42_CXXFLAGS -msse4.2) endif() + +# Check for SSE4.2 support by compiling code that uses the CRC32 instruction intrinsic. check_cxx_source_compiles_with_flags(" #include #if defined(_MSC_VER) @@ -53,6 +66,7 @@ check_cxx_source_compiles_with_flags(" int main() { uint64_t l = 0; + // _mm_crc32_u64 is a reliable way to check for SSE4.2 compiler support. l = _mm_crc32_u8(l, 0); l = _mm_crc32_u32(l, 0); l = _mm_crc32_u64(l, 0); @@ -62,15 +76,23 @@ check_cxx_source_compiles_with_flags(" CXXFLAGS ${SSE42_CXXFLAGS} ) -# Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler. +# ----------------------------------------------------------------------------- +# 3. ARMv8 CRC/CRYPTO Support Check (AArch64) +# ----------------------------------------------------------------------------- + +# Set required flags for ARMv8 hardware acceleration extensions. set(ARM64_CRC_CXXFLAGS -march=armv8-a+crc+crypto) + +# Check for ARMv8 support by testing CRC32C and NEON intrinsics. check_cxx_source_compiles_with_flags(" #include #include int main() { #ifdef __aarch64__ + // Test for CRC32C intrinsics (byte, half-word, word, double-word) __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); + // Test for CRYPTO extension intrinsic (vmull_p64 used for polynomial multiplication) vmull_p64(0, 0); #else #error crc32c library does not support hardware acceleration on 32-bit ARM @@ -81,35 +103,58 @@ check_cxx_source_compiles_with_flags(" CXXFLAGS ${ARM64_CRC_CXXFLAGS} ) +# ----------------------------------------------------------------------------- +# 4. Library Definition and Configuration +# ----------------------------------------------------------------------------- + +# Define the static library with portable implementation files. add_library(crc32c STATIC EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c.cc ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_portable.cc ) + +# Set compile definitions using Generator Expressions for conditional feature flags. target_compile_definitions(crc32c PRIVATE HAVE_BUILTIN_PREFETCH=$ HAVE_MM_PREFETCH=$ + # Note: HAVE_STRONG_GETAUXVAL check is assumed to be performed elsewhere. HAVE_STRONG_GETAUXVAL=$ BYTE_ORDER_BIG_ENDIAN=$ HAVE_SSE42=$ HAVE_ARM64_CRC32C=$ ) + +# Set public include directory. $ prevents the include path +# from leaking when the library is installed. target_include_directories(crc32c PUBLIC $ ) + +# Link against the core interface library (assuming it provides utilities/interfaces). target_link_libraries(crc32c PRIVATE core_interface) +# Disable writing compile commands for this utility target. set_target_properties(crc32c PROPERTIES EXPORT_COMPILE_COMMANDS OFF) +# ----------------------------------------------------------------------------- +# 5. Conditional Source File Inclusion +# ----------------------------------------------------------------------------- + +# Include and apply specific flags for the SSE4.2 implementation if supported. if(HAVE_SSE42) set(_crc32_src ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_sse42.cc) target_sources(crc32c PRIVATE ${_crc32_src}) + # Apply the aggressive SSE4.2 compilation flags only to the SSE-specific file. set_property(SOURCE ${_crc32_src} PROPERTY COMPILE_OPTIONS ${SSE42_CXXFLAGS}) endif() +# Include and apply specific flags for the ARMv8 implementation if supported. if(HAVE_ARM64_CRC32C) set(_crc32_src ${PROJECT_SOURCE_DIR}/src/crc32c/src/crc32c_arm64.cc) target_sources(crc32c PRIVATE ${_crc32_src}) + # Apply the ARMv8 CRC/CRYPTO compilation flags only to the ARM-specific file. set_property(SOURCE ${_crc32_src} PROPERTY COMPILE_OPTIONS ${ARM64_CRC_CXXFLAGS}) endif() +# Clean up the temporary variable. unset(_crc32_src)