Changes to atomic.c are based on libatomic-chimera --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -270,7 +270,8 @@ function(add_compiler_rt_runtime name type) endif() endif() if(COMPILER_RT_USE_BUILTINS_LIBRARY AND NOT type STREQUAL "OBJECT" AND - NOT name STREQUAL "clang_rt.builtins") + NOT name STREQUAL "clang_rt.builtins" AND + NOT name STREQUAL "clang_rt.atomic") get_compiler_rt_target(${arch} target) find_compiler_rt_library(builtins builtins_${libname} TARGET ${target}) if(builtins_${libname} STREQUAL "NOTFOUND") --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -940,6 +940,7 @@ option(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC if(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC) add_custom_target(builtins-standalone-atomic) + add_dependencies(builtins-standalone-atomic builtins) set(BUILTIN_TYPE SHARED) if(OS_NAME MATCHES "AIX") include(CompilerRTAIXUtils) @@ -950,8 +951,6 @@ if(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC) # For different versions of cmake, SHARED behaves differently. For some # versions, we might need MODULE rather than SHARED. get_aix_libatomic_type(BUILTIN_TYPE) - else() - list(APPEND COMPILER_RT_LIBATOMIC_LINK_FLAGS -nodefaultlibs) endif() foreach (arch ${BUILTIN_SUPPORTED_ARCH}) if(CAN_TARGET_${arch}) @@ -960,10 +959,15 @@ if(COMPILER_RT_BUILD_STANDALONE_LIBATOMIC) add_compiler_rt_runtime(clang_rt.atomic ${BUILTIN_TYPE} ARCHS ${arch} - SOURCES atomic.c + SOURCES "atomic.c;atomic_flag_clear.c;atomic_flag_clear_explicit.c;atomic_flag_test_and_set.c;atomic_flag_test_and_set_explicit.c;atomic_signal_fence.c;atomic_thread_fence.c" LINK_FLAGS ${COMPILER_RT_LIBATOMIC_LINK_FLAGS} LINK_LIBS ${COMPILER_RT_LIBATOMIC_LINK_LIBS_${arch}} PARENT_TARGET builtins-standalone-atomic) + set_target_properties(clang_rt.atomic-dynamic-${arch} + PROPERTIES + OUTPUT_NAME "atomic" + SOVERSION "1" + ) endif() endforeach() # FIXME: On AIX, we have to archive built shared libraries into a static --- a/compiler-rt/lib/builtins/atomic.c +++ b/compiler-rt/lib/builtins/atomic.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "assembly.h" @@ -346,6 +347,18 @@ OPTIMISED_CASES *ptr = tmp op val; \ unlock(l); \ return tmp; \ + } \ + \ + type __atomic_##opname##_fetch_##n(type *ptr, type val, int model) { \ + if (lockfree(ptr)) \ + return __atomic_##opname##_fetch(ptr, val, model); \ + Lock *l = lock_for_pointer(ptr); \ + lock(l); \ + type tmp = *ptr; \ + tmp = tmp op val; \ + *ptr = tmp; \ + unlock(l); \ + return tmp; \ } #define ATOMIC_RMW_NAND(n, lockfree, type) \ @@ -358,6 +371,30 @@ OPTIMISED_CASES *ptr = ~(tmp & val); \ unlock(l); \ return tmp; \ + } \ + \ + type __atomic_nand_fetch_##n(type *ptr, type val, int model) { \ + if (lockfree(ptr)) \ + return __atomic_nand_fetch(ptr, val, model); \ + Lock *l = lock_for_pointer(ptr); \ + lock(l); \ + type tmp = *ptr; \ + tmp = ~(tmp & val); \ + *ptr = tmp; \ + unlock(l); \ + return tmp; \ + } + +#define ATOMIC_TAS(n, lockfree, type) \ + bool __atomic_test_and_set_##n(type *ptr, int model) { \ + if (lockfree(ptr)) \ + return __atomic_test_and_set(ptr, model); \ + Lock *l = lock_for_pointer(ptr); \ + lock(l); \ + type tmp = *ptr; \ + *ptr = 1; \ + unlock(l); \ + return !!tmp; \ } #define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, add, +) @@ -381,3 +418,42 @@ OPTIMISED_CASES OPTIMISED_CASES #undef OPTIMISED_CASE #endif +#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_TAS(n, lockfree, type) +OPTIMISED_CASES +#undef OPTIMISED_CASE + +/* provided by gcc libatomic */ + +void __atomic_feraiseexcept(int e) { + volatile float r __attribute__((unused)); +#ifdef FE_INVALID + if (e & FE_INVALID) { + volatile float z = 0.0f; + r = z / z; + } +#endif +#ifdef FE_DIVBYZERO + if (e & FE_DIVBYZERO) { + volatile float z = 0.0f; + r = 1.0f / z; + } +#endif +#ifdef FE_OVERFLOW + if (e & FE_OVERFLOW) { + volatile float m = __FLT_MAX__; + r = m * m; + } +#endif +#ifdef FE_UNDERFLOW + if (e & FE_UNDERFLOW) { + volatile float m = __FLT_MIN__; + r = m * m; + } +#endif +#ifdef FE_INEXACT + if (e & FE_INEXACT) { + volatile float t = 3.0f; + r = 1.0f / t; + } +#endif +}