1# atomic builtins are required for threading support. 2 3INCLUDE(CheckCXXSourceCompiles) 4INCLUDE(CheckLibraryExists) 5 6# Sometimes linking against libatomic is required for atomic ops, if 7# 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 return 0; 36} 37" ${varname}) 38 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) 39endfunction(check_working_cxx_atomics64) 40 41 42# Check for (non-64-bit) atomic operations. 43if(MSVC) 44 set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) 45elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE) 46 # First check if atomics work without the library. 47 check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) 48 # If not, check if the library exists, and atomics work with it. 49 if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) 50 check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) 51 if(HAVE_LIBATOMIC) 52 list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") 53 check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) 54 if (NOT HAVE_CXX_ATOMICS_WITH_LIB) 55 message(FATAL_ERROR "Host compiler must support std::atomic!") 56 endif() 57 else() 58 message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") 59 endif() 60 endif() 61endif() 62 63# Check for 64 bit atomic operations. 64if(MSVC) 65 set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) 66elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE) 67 # First check if atomics work without the library. 68 check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) 69 # If not, check if the library exists, and atomics work with it. 70 if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) 71 check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) 72 if(HAVE_CXX_LIBATOMICS64) 73 list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") 74 check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) 75 if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) 76 message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") 77 endif() 78 else() 79 message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") 80 endif() 81 endif() 82endif() 83 84## TODO: This define is only used for the legacy atomic operations in 85## llvm's Atomic.h, which should be replaced. Other code simply 86## assumes C++11 <atomic> works. 87CHECK_CXX_SOURCE_COMPILES(" 88#ifdef _MSC_VER 89#include <windows.h> 90#endif 91int main() { 92#ifdef _MSC_VER 93 volatile LONG val = 1; 94 MemoryBarrier(); 95 InterlockedCompareExchange(&val, 0, 1); 96 InterlockedIncrement(&val); 97 InterlockedDecrement(&val); 98#else 99 volatile unsigned long val = 1; 100 __sync_synchronize(); 101 __sync_val_compare_and_swap(&val, 1, 0); 102 __sync_add_and_fetch(&val, 1); 103 __sync_sub_and_fetch(&val, 1); 104#endif 105 return 0; 106 } 107" LLVM_HAS_ATOMICS) 108 109if( NOT LLVM_HAS_ATOMICS ) 110 message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") 111endif() 112