126 lines · plain
1# atomic builtins are required for threading support.2 3INCLUDE(CheckCXXSourceCompiles)4INCLUDE(CheckLibraryExists)5 6# Sometimes linking against libatomic is required for atomic ops, if7# the platform doesn't support lock-free atomics.8 9function(check_working_cxx_atomics varname)10 set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})11 set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11")12 CHECK_CXX_SOURCE_COMPILES("13#include <atomic>14std::atomic<int> x;15std::atomic<short> y;16std::atomic<char> z;17int main() {18 ++z;19 ++y;20 return ++x;21}22" ${varname})23 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})24endfunction(check_working_cxx_atomics)25 26function(check_working_cxx_atomics64 varname)27 set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})28 set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")29 CHECK_CXX_SOURCE_COMPILES("30#include <atomic>31#include <cstdint>32std::atomic<uint64_t> x (0);33int main() {34 uint64_t i = x.load(std::memory_order_relaxed);35 (void)i;36 return 0;37}38" ${varname})39 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})40endfunction(check_working_cxx_atomics64)41 42 43# Check for (non-64-bit) atomic operations.44if(MSVC)45 set(HAVE_CXX_ATOMICS_WITHOUT_LIB True)46elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")47 # First check if atomics work without the library.48 check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)49 # If not, check if the library exists, and atomics work with it.50 if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)51 check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)52 if(HAVE_LIBATOMIC)53 list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")54 check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)55 if (NOT HAVE_CXX_ATOMICS_WITH_LIB)56 message(FATAL_ERROR "Host compiler must support std::atomic!")57 endif()58 else()59 message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")60 endif()61 endif()62endif()63 64# Check for 64 bit atomic operations.65if(MSVC)66 set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)67elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE OR CMAKE_CXX_COMPILER_ID MATCHES "XL")68 # First check if atomics work without the library.69 check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)70 # If not, check if the library exists, and atomics work with it.71 if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)72 check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)73 if(HAVE_CXX_LIBATOMICS64)74 list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")75 check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)76 if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)77 message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!")78 endif()79 else()80 message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.")81 endif()82 endif()83endif()84 85# Set variable LLVM_ATOMIC_LIB specifying flags for linking against libatomic.86if(HAVE_CXX_ATOMICS_WITH_LIB OR HAVE_CXX_ATOMICS64_WITH_LIB)87 # Use options --push-state, --as-needed and --pop-state if linker is known to support them.88 # Use single option -Wl of compiler driver to avoid incorrect re-ordering of options by CMake.89 if(LLVM_LINKER_IS_GNULD OR LLVM_LINKER_IS_GOLD OR LLVM_LINKER_IS_LLD OR LLVM_LINKER_IS_MOLD)90 set(LLVM_ATOMIC_LIB "-Wl,--push-state,--as-needed,-latomic,--pop-state")91 else()92 set(LLVM_ATOMIC_LIB "-latomic")93 endif()94else()95 set(LLVM_ATOMIC_LIB)96endif()97 98## TODO: This define is only used for the legacy atomic operations in99## llvm's Atomic.h, which should be replaced. Other code simply100## assumes C++11 <atomic> works.101CHECK_CXX_SOURCE_COMPILES("102#ifdef _MSC_VER103#include <windows.h>104#endif105int main() {106#ifdef _MSC_VER107 volatile LONG val = 1;108 MemoryBarrier();109 InterlockedCompareExchange(&val, 0, 1);110 InterlockedIncrement(&val);111 InterlockedDecrement(&val);112#else113 volatile unsigned long val = 1;114 __sync_synchronize();115 __sync_val_compare_and_swap(&val, 1, 0);116 __sync_add_and_fetch(&val, 1);117 __sync_sub_and_fetch(&val, 1);118#endif119 return 0;120 }121" LLVM_HAS_ATOMICS)122 123if( NOT LLVM_HAS_ATOMICS )124 message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")125endif()126