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 | |
| 21 | # This isn't necessary on MSVC, so avoid command-line switch annoyance |
| 22 | # by only running on GCC-like hosts. |
| 23 | if (LLVM_COMPILER_IS_GCC_COMPATIBLE) |
| 24 | # First check if atomics work without the library. |
| 25 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) |
| 26 | # If not, check if the library exists, and atomics work with it. |
| 27 | if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) |
| 28 | check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) |
| 29 | if( HAVE_LIBATOMIC ) |
| 30 | list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") |
| 31 | check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) |
| 32 | if (NOT HAVE_CXX_ATOMICS_WITH_LIB) |
| 33 | message(FATAL_ERROR "Host compiler must support std::atomic!") |
| 34 | endif() |
| 35 | else() |
| 36 | message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") |
| 37 | endif() |
Saleem Abdulrasool | 5285c12 | 2015-02-25 02:38:03 +0000 | [diff] [blame] | 38 | endif() |
Evgeniy Stepanov | 986460d | 2014-09-12 11:08:59 +0000 | [diff] [blame] | 39 | endif() |
| 40 | |
James Y Knight | 3f9a1dc | 2015-06-16 14:00:01 +0000 | [diff] [blame] | 41 | ## TODO: This define is only used for the legacy atomic operations in |
| 42 | ## llvm's Atomic.h, which should be replaced. Other code simply |
| 43 | ## assumes C++11 <atomic> works. |
Oscar Fuentes | 58eea20 | 2009-12-06 00:06:33 +0000 | [diff] [blame] | 44 | CHECK_CXX_SOURCE_COMPILES(" |
Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 45 | #ifdef _MSC_VER |
Reid Kleckner | 446a0d1 | 2015-03-02 22:00:23 +0000 | [diff] [blame] | 46 | #include <Intrin.h> /* Workaround for PR19898. */ |
Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 47 | #include <windows.h> |
| 48 | #endif |
Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 49 | int main() { |
Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 50 | #ifdef _MSC_VER |
| 51 | volatile LONG val = 1; |
| 52 | MemoryBarrier(); |
| 53 | InterlockedCompareExchange(&val, 0, 1); |
| 54 | InterlockedIncrement(&val); |
| 55 | InterlockedDecrement(&val); |
| 56 | #else |
Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 57 | volatile unsigned long val = 1; |
| 58 | __sync_synchronize(); |
| 59 | __sync_val_compare_and_swap(&val, 1, 0); |
| 60 | __sync_add_and_fetch(&val, 1); |
| 61 | __sync_sub_and_fetch(&val, 1); |
Oscar Fuentes | 4f6d1eb | 2009-12-05 23:19:33 +0000 | [diff] [blame] | 62 | #endif |
Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 63 | return 0; |
| 64 | } |
Eric Christopher | 4418a60 | 2011-09-19 20:43:23 +0000 | [diff] [blame] | 65 | " LLVM_HAS_ATOMICS) |
Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 66 | |
Eric Christopher | 4418a60 | 2011-09-19 20:43:23 +0000 | [diff] [blame] | 67 | if( NOT LLVM_HAS_ATOMICS ) |
Xerxes Ranby | 64c6d42 | 2009-07-17 19:22:41 +0000 | [diff] [blame] | 68 | message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") |
| 69 | endif() |