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 (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) 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) 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## TODO: This define is only used for the legacy atomic operations in 86## llvm's Atomic.h, which should be replaced. Other code simply 87## assumes C++11 <atomic> works. 88CHECK_CXX_SOURCE_COMPILES(" 89#ifdef _MSC_VER 90#include <windows.h> 91#endif 92int main() { 93#ifdef _MSC_VER 94 volatile LONG val = 1; 95 MemoryBarrier(); 96 InterlockedCompareExchange(&val, 0, 1); 97 InterlockedIncrement(&val); 98 InterlockedDecrement(&val); 99#else 100 volatile unsigned long val = 1; 101 __sync_synchronize(); 102 __sync_val_compare_and_swap(&val, 1, 0); 103 __sync_add_and_fetch(&val, 1); 104 __sync_sub_and_fetch(&val, 1); 105#endif 106 return 0; 107 } 108" LLVM_HAS_ATOMICS) 109 110if( NOT LLVM_HAS_ATOMICS ) 111 message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") 112endif() 113