aboutsummaryrefslogtreecommitdiff
path: root/cmake/tuklib_integer.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/tuklib_integer.cmake')
-rw-r--r--cmake/tuklib_integer.cmake100
1 files changed, 100 insertions, 0 deletions
diff --git a/cmake/tuklib_integer.cmake b/cmake/tuklib_integer.cmake
new file mode 100644
index 00000000..aeb7ff6f
--- /dev/null
+++ b/cmake/tuklib_integer.cmake
@@ -0,0 +1,100 @@
+#
+# tuklib_integer.cmake - see tuklib_integer.m4 for description and comments
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+
+include(${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake)
+include(TestBigEndian)
+include(CheckCSourceCompiles)
+include(CheckIncludeFile)
+include(CheckSymbolExists)
+
+function(tuklib_integer TARGET_OR_ALL)
+ # Check for endianness. Unlike the Autoconf's AC_C_BIGENDIAN, this doesn't
+ # support Apple universal binaries. The CMake module will leave the
+ # variable unset so we can catch that situation here instead of continuing
+ # as if we were little endian.
+ test_big_endian(WORDS_BIGENDIAN)
+ if(NOT DEFINED WORDS_BIGENDIAN)
+ message(FATAL_ERROR "Cannot determine endianness")
+ endif()
+ tuklib_add_definition_if(${TARGET_OR_ALL} WORDS_BIGENDIAN)
+
+ # Look for a byteswapping method.
+ check_c_source_compiles("
+ int main(void)
+ {
+ __builtin_bswap16(1);
+ __builtin_bswap32(1);
+ __builtin_bswap64(1);
+ return 0;
+ }
+ "
+ HAVE___BUILTIN_BSWAPXX)
+ if(HAVE___BUILTIN_BSWAPXX)
+ tuklib_add_definitions(${TARGET_OR_ALL} HAVE___BUILTIN_BSWAPXX)
+ else()
+ check_include_file(byteswap.h HAVE_BYTESWAP_H)
+ if(HAVE_BYTESWAP_H)
+ tuklib_add_definitions(${TARGET_OR_ALL} HAVE_BYTESWAP_H)
+ check_symbol_exists(bswap_16 byteswap.h HAVE_BSWAP_16)
+ tuklib_add_definition_if(${TARGET_OR_ALL} HAVE_BSWAP_16)
+ check_symbol_exists(bswap_32 byteswap.h HAVE_BSWAP_32)
+ tuklib_add_definition_if(${TARGET_OR_ALL} HAVE_BSWAP_32)
+ check_symbol_exists(bswap_64 byteswap.h HAVE_BSWAP_64)
+ tuklib_add_definition_if(${TARGET_OR_ALL} HAVE_BSWAP_64)
+ else()
+ check_include_file(sys/endian.h HAVE_SYS_ENDIAN_H)
+ if(HAVE_SYS_ENDIAN_H)
+ tuklib_add_definitions(${TARGET_OR_ALL} HAVE_SYS_ENDIAN_H)
+ else()
+ check_include_file(sys/byteorder.h HAVE_SYS_BYTEORDER_H)
+ tuklib_add_definition_if(${TARGET_OR_ALL} HAVE_SYS_BYTEORDER_H)
+ endif()
+ endif()
+ endif()
+
+ # 16-bit and 32-bit unaligned access is fast on x86(-64),
+ # big endian PowerPC, and usually on 32/64-bit ARM too.
+ # There are others too and ARM could be a false match.
+ #
+ # Guess the default value for the option.
+ # CMake's ability to give info about the target arch seems bad.
+ # The the same arch can have different name depending on the OS.
+ #
+ # FIXME: The regex is based on guessing, not on factual information!
+ #
+ # NOTE: Compared to the Autoconf test, this lacks the GCC/Clang test
+ # on ARM and always assumes that unaligned is fast on ARM.
+ set(FAST_UNALIGNED_GUESS OFF)
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES
+ [Xx3456]86|^[Xx]64|^[Aa][Mm][Dd]64|^[Aa][Rr][Mm]|^aarch|^powerpc|^ppc)
+ if(NOT WORDS_BIGENDIAN OR
+ NOT CMAKE_SYSTEM_PROCESSOR MATCHES ^powerpc|^ppc)
+ set(FAST_UNALIGNED_GUESS ON)
+ endif()
+ endif()
+ option(TUKLIB_FAST_UNALIGNED_ACCESS
+ "Enable if the system supports *fast* unaligned memory access with 16-bit and 32-bit integers."
+ ${FAST_UNALIGNED_GUESS})
+ tuklib_add_definition_if(${TARGET_OR_ALL} TUKLIB_FAST_UNALIGNED_ACCESS)
+
+ # Unsafe type punning:
+ option(TUKLIB_USE_UNSAFE_TYPE_PUNNING
+ "This introduces strict aliasing violations and \
+may result in broken code. However, this might improve performance \
+in some cases, especially with old compilers \
+(e.g. GCC 3 and early 4.x on x86, GCC < 6 on ARMv6 and ARMv7)."
+ OFF)
+ tuklib_add_definition_if(${TARGET_OR_ALL} TUKLIB_USE_UNSAFE_TYPE_PUNNING)
+
+ # Check for GCC/Clang __builtin_assume_aligned().
+ check_c_source_compiles(
+ "int main(void) { __builtin_assume_aligned(\"\", 1); return 0; }"
+ HAVE___BUILTIN_ASSUME_ALIGNED)
+ tuklib_add_definition_if(${TARGET_OR_ALL} HAVE___BUILTIN_ASSUME_ALIGNED)
+endfunction()