From a92b20eec6082692f84b7ff9eaaf1689bf8d33d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E9=98=B3?= <657837019@qq.com> Date: Wed, 10 Jun 2026 00:45:31 +0800 Subject: [PATCH] Add RISC-V target detection --- CMakeLists.txt | 188 +++++++++++++++++++++++++---------------- src/crc32c_config.h.in | 3 + 2 files changed, 117 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e75211f..d0cfc77 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,26 @@ option(CRC32C_BUILD_BENCHMARKS "Build CRC32C's benchmarks" ON) option(CRC32C_USE_GLOG "Build CRC32C's tests with Google Logging" ON) option(CRC32C_INSTALL "Install CRC32C's header and library" ON) +set(CRC32C_TARGET_X86 0) +set(CRC32C_TARGET_ARM64 0) +set(CRC32C_TARGET_RISCV 0) +set(CRC32C_TARGET_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") +if(NOT CRC32C_TARGET_PROCESSOR AND NOT CMAKE_CROSSCOMPILING) + set(CRC32C_TARGET_PROCESSOR "${CMAKE_HOST_SYSTEM_PROCESSOR}") +endif() +string(TOLOWER "${CRC32C_TARGET_PROCESSOR}" CRC32C_TARGET_PROCESSOR_LOWER) +string(TOLOWER "${CMAKE_CXX_COMPILER_TARGET}" CRC32C_CXX_COMPILER_TARGET_LOWER) +if(CRC32C_TARGET_PROCESSOR_LOWER MATCHES "riscv" OR + CRC32C_CXX_COMPILER_TARGET_LOWER MATCHES "riscv") + set(CRC32C_TARGET_RISCV 1) +elseif(CRC32C_TARGET_PROCESSOR_LOWER MATCHES "^(x86_64|amd64|i[3-6]86|x86)$" OR + CRC32C_CXX_COMPILER_TARGET_LOWER MATCHES "^(x86_64|amd64|i[3-6]86|x86)") + set(CRC32C_TARGET_X86 1) +elseif(CRC32C_TARGET_PROCESSOR_LOWER MATCHES "^(aarch64|arm64)$" OR + CRC32C_CXX_COMPILER_TARGET_LOWER MATCHES "^(aarch64|arm64)") + set(CRC32C_TARGET_ARM64 1) +endif() + include(TestBigEndian) test_big_endian(BYTE_ORDER_BIG_ENDIAN) @@ -96,88 +116,108 @@ int main() { # Check for _mm_prefetch support in the compiler. include(CheckCXXSourceCompiles) -check_cxx_source_compiles(" -#if defined(_MSC_VER) -#include -#else // !defined(_MSC_VER) -#include -#endif // defined(_MSC_VER) - -int main() { - char data = 0; - const char* address = &data; - _mm_prefetch(address, _MM_HINT_NTA); - return 0; -} -" HAVE_MM_PREFETCH) +if(CRC32C_TARGET_X86) + check_cxx_source_compiles(" + #if defined(_MSC_VER) + #include + #else // !defined(_MSC_VER) + #include + #endif // defined(_MSC_VER) + + int main() { + char data = 0; + const char* address = &data; + _mm_prefetch(address, _MM_HINT_NTA); + return 0; + } + " HAVE_MM_PREFETCH) +else() + set(HAVE_MM_PREFETCH 0) +endif() # Check for SSE4.2 support in the compiler. -set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX") -else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2") -endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") -check_cxx_source_compiles(" -#if defined(_MSC_VER) -#include -#else // !defined(_MSC_VER) -#include -#include -#endif // defined(_MSC_VER) - -int main() { - _mm_crc32_u8(0, 0); _mm_crc32_u32(0, 0); -#if defined(_M_X64) || defined(__x86_64__) - _mm_crc32_u64(0, 0); -#endif // defined(_M_X64) || defined(__x86_64__) - return 0; -} -" HAVE_SSE42) -set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) +if(CRC32C_TARGET_X86) + set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:AVX") + else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -msse4.2") + endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + check_cxx_source_compiles(" + #if defined(_MSC_VER) + #include + #else // !defined(_MSC_VER) + #include + #include + #endif // defined(_MSC_VER) + + int main() { + _mm_crc32_u8(0, 0); _mm_crc32_u32(0, 0); + #if defined(_M_X64) || defined(__x86_64__) + _mm_crc32_u64(0, 0); + #endif // defined(_M_X64) || defined(__x86_64__) + return 0; + } + " HAVE_SSE42) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) +else() + set(HAVE_SSE42 0) +endif() # Check for ARMv8 w/ CRC and CRYPTO extensions support in the compiler. -set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) -if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # TODO(pwnall): Insert correct flag when VS gets ARM CRC32C support. - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:NOTYET") -else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=armv8-a+crc+crypto") -endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") -check_cxx_source_compiles(" -#include -#include - -int main() { - __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); - vmull_p64(0, 0); - return 0; -} -" HAVE_ARM64_CRC32C) -set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) +if(CRC32C_TARGET_ARM64) + set(OLD_CMAKE_REQURED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # TODO(pwnall): Insert correct flag when VS gets ARM CRC32C support. + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} /arch:NOTYET") + else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -march=armv8-a+crc+crypto") + endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + check_cxx_source_compiles(" + #include + #include + + int main() { + __crc32cb(0, 0); __crc32ch(0, 0); __crc32cw(0, 0); __crc32cd(0, 0); + vmull_p64(0, 0); + return 0; + } + " HAVE_ARM64_CRC32C) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQURED_FLAGS}) +else() + set(HAVE_ARM64_CRC32C 0) +endif() # Check for strong getauxval() support in the system headers. -check_cxx_source_compiles(" -#include -#include -#include - -int main() { - getauxval(AT_HWCAP); - return 0; -} -" HAVE_STRONG_GETAUXVAL) +if(CRC32C_TARGET_ARM64) + check_cxx_source_compiles(" + #include + #include + #include + + int main() { + getauxval(AT_HWCAP); + return 0; + } + " HAVE_STRONG_GETAUXVAL) +else() + set(HAVE_STRONG_GETAUXVAL 0) +endif() # Check for weak getauxval() support in the compiler. -check_cxx_source_compiles(" -unsigned long getauxval(unsigned long type) __attribute__((weak)); -#define AT_HWCAP 16 - -int main() { - getauxval(AT_HWCAP); - return 0; -} -" HAVE_WEAK_GETAUXVAL) +if(CRC32C_TARGET_ARM64) + check_cxx_source_compiles(" + unsigned long getauxval(unsigned long type) __attribute__((weak)); + #define AT_HWCAP 16 + + int main() { + getauxval(AT_HWCAP); + return 0; + } + " HAVE_WEAK_GETAUXVAL) +else() + set(HAVE_WEAK_GETAUXVAL 0) +endif() if(CRC32C_USE_GLOG) # glog requires this setting to avoid using dynamic_cast. diff --git a/src/crc32c_config.h.in b/src/crc32c_config.h.in index 4034fa5..dbe293a 100644 --- a/src/crc32c_config.h.in +++ b/src/crc32c_config.h.in @@ -8,6 +8,9 @@ // Define to 1 if building for a big-endian platform. #cmakedefine01 BYTE_ORDER_BIG_ENDIAN +// Define to 1 when targeting RISC-V and using the portable implementation. +#cmakedefine01 CRC32C_TARGET_RISCV + // Define to 1 if the compiler has the __builtin_prefetch intrinsic. #cmakedefine01 HAVE_BUILTIN_PREFETCH