# # 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() # 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, 32-bit, and 64-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()