| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 1 | # atomic builtins are required for threading support. | 
|  | 2 |  | 
|  | 3 | INCLUDE(CheckCXXSourceCompiles) | 
| Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 4 |  | 
| James Y Knight | 3f9a1dc | 2015-06-16 14:00:01 +0000 | [diff] [blame] | 5 | # Sometimes linking against libatomic is required for atomic ops, if | 
|  | 6 | # the platform doesn't support lock-free atomics. | 
|  | 7 |  | 
|  | 8 | function(check_working_cxx_atomics varname) | 
|  | 9 | set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) | 
|  | 10 | set(CMAKE_REQUIRED_FLAGS "-std=c++11") | 
|  | 11 | CHECK_CXX_SOURCE_COMPILES(" | 
|  | 12 | #include <atomic> | 
|  | 13 | std::atomic<int> x; | 
|  | 14 | int main() { | 
|  | 15 | return x; | 
|  | 16 | } | 
|  | 17 | " ${varname}) | 
|  | 18 | set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) | 
|  | 19 | endfunction(check_working_cxx_atomics) | 
|  | 20 |  | 
| Sagar Thakur | 9e1de09 | 2016-06-23 06:39:35 +0000 | [diff] [blame] | 21 | function(check_working_cxx_atomics64 varname) | 
|  | 22 | set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) | 
|  | 23 | set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}") | 
|  | 24 | CHECK_CXX_SOURCE_COMPILES(" | 
|  | 25 | #include <atomic> | 
|  | 26 | #include <cstdint> | 
|  | 27 | std::atomic<uint64_t> x (0); | 
|  | 28 | int main() { | 
|  | 29 | uint64_t i = x.load(std::memory_order_relaxed); | 
|  | 30 | return 0; | 
|  | 31 | } | 
|  | 32 | " ${varname}) | 
|  | 33 | set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) | 
|  | 34 | endfunction(check_working_cxx_atomics64) | 
|  | 35 |  | 
|  | 36 |  | 
| James Y Knight | 3f9a1dc | 2015-06-16 14:00:01 +0000 | [diff] [blame] | 37 | # This isn't necessary on MSVC, so avoid command-line switch annoyance | 
|  | 38 | # by only running on GCC-like hosts. | 
|  | 39 | if (LLVM_COMPILER_IS_GCC_COMPATIBLE) | 
|  | 40 | # First check if atomics work without the library. | 
|  | 41 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) | 
|  | 42 | # If not, check if the library exists, and atomics work with it. | 
|  | 43 | if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) | 
|  | 44 | check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) | 
|  | 45 | if( HAVE_LIBATOMIC ) | 
|  | 46 | list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") | 
|  | 47 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) | 
|  | 48 | if (NOT HAVE_CXX_ATOMICS_WITH_LIB) | 
|  | 49 | message(FATAL_ERROR "Host compiler must support std::atomic!") | 
|  | 50 | endif() | 
|  | 51 | else() | 
|  | 52 | message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") | 
|  | 53 | endif() | 
| Saleem Abdulrasool | 5285c12 | 2015-02-25 02:38:03 +0000 | [diff] [blame] | 54 | endif() | 
| Evgeniy Stepanov | 986460d | 2014-09-12 11:08:59 +0000 | [diff] [blame] | 55 | endif() | 
|  | 56 |  | 
| Sagar Thakur | 9e1de09 | 2016-06-23 06:39:35 +0000 | [diff] [blame] | 57 | # Check for 64 bit atomic operations. | 
|  | 58 | if(MSVC) | 
|  | 59 | set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) | 
|  | 60 | else() | 
|  | 61 | check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) | 
|  | 62 | endif() | 
|  | 63 |  | 
|  | 64 | # If not, check if the library exists, and atomics work with it. | 
|  | 65 | if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) | 
|  | 66 | check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) | 
|  | 67 | if(HAVE_CXX_LIBATOMICS64) | 
|  | 68 | list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") | 
|  | 69 | check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) | 
|  | 70 | if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) | 
|  | 71 | message(FATAL_ERROR "Host compiler must support std::atomic!") | 
|  | 72 | endif() | 
|  | 73 | else() | 
|  | 74 | message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") | 
|  | 75 | endif() | 
|  | 76 | endif() | 
|  | 77 |  | 
| James Y Knight | 3f9a1dc | 2015-06-16 14:00:01 +0000 | [diff] [blame] | 78 | ## TODO: This define is only used for the legacy atomic operations in | 
|  | 79 | ## llvm's Atomic.h, which should be replaced.  Other code simply | 
|  | 80 | ## assumes C++11 <atomic> works. | 
| Oscar Fuentes | 58eea20 | 2009-12-06 00:06:33 +0000 | [diff] [blame] | 81 | CHECK_CXX_SOURCE_COMPILES(" | 
| Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 82 | #ifdef _MSC_VER | 
| Reid Kleckner | 446a0d1 | 2015-03-02 22:00:23 +0000 | [diff] [blame] | 83 | #include <Intrin.h> /* Workaround for PR19898. */ | 
| Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 84 | #include <windows.h> | 
|  | 85 | #endif | 
| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 86 | int main() { | 
| Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 87 | #ifdef _MSC_VER | 
|  | 88 | volatile LONG val = 1; | 
|  | 89 | MemoryBarrier(); | 
|  | 90 | InterlockedCompareExchange(&val, 0, 1); | 
|  | 91 | InterlockedIncrement(&val); | 
|  | 92 | InterlockedDecrement(&val); | 
|  | 93 | #else | 
| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 94 | volatile unsigned long val = 1; | 
|  | 95 | __sync_synchronize(); | 
|  | 96 | __sync_val_compare_and_swap(&val, 1, 0); | 
|  | 97 | __sync_add_and_fetch(&val, 1); | 
|  | 98 | __sync_sub_and_fetch(&val, 1); | 
| Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 99 | #endif | 
| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 100 | return 0; | 
|  | 101 | } | 
| Eric Christopher | 4418a60 | 2011-09-19 20:43:23 +0000 | [diff] [blame] | 102 | " LLVM_HAS_ATOMICS) | 
| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 103 |  | 
| Eric Christopher | 4418a60 | 2011-09-19 20:43:23 +0000 | [diff] [blame] | 104 | if( NOT LLVM_HAS_ATOMICS ) | 
| Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 105 | message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") | 
|  | 106 | endif() |