Переглянути джерело

newlib,clang: implement __sync_* atomics for clang/llvm toolchain.

Andrei Safronov 4 роки тому
батько
коміт
40daaa9d56
1 змінених файлів з 31 додано та 8 видалено
  1. 31 8
      components/newlib/stdatomic.c

+ 31 - 8
components/newlib/stdatomic.c

@@ -75,6 +75,24 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED;
 
 #endif // SOC_CPU_CORES_NUM
 
+#ifdef __clang__
+// Clang doesn't allow to define "__sync_*" atomics. The workaround is to define function with name "__sync_*_builtin",
+// which implements "__sync_*" atomic functionality and use asm directive to set the value of symbol "__sync_*" to the name
+// of defined function.
+
+#define CLANG_ATOMIC_SUFFIX(name_) name_ ## _builtin
+#define CLANG_DECLARE_ALIAS(name_) \
+__asm__(".type " # name_ ", @function\n"        \
+        ".global " #name_ "\n"                  \
+        ".equ " #name_ ", " #name_ "_builtin");
+
+#else // __clang__
+
+#define CLANG_ATOMIC_SUFFIX(name_) name_
+#define CLANG_DECLARE_ALIAS(name_)
+
+#endif // __clang__
+
 #define ATOMIC_LOAD(n, type) type __atomic_load_ ## n (const type* mem, int memorder) \
 {                                                   \
     unsigned state = _ATOMIC_ENTER_CRITICAL();      \
@@ -158,12 +176,14 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED;
     return ret; \
 }
 
-#define SYNC_FETCH_OP(op, n, type) type __sync_fetch_and_ ## op ##_ ## n (type* ptr, type value) \
-{                                                                               \
-    return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST);       \
-}
 
-#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool  __sync_bool_compare_and_swap_ ## n  (type *ptr, type oldval, type newval) \
+#define SYNC_FETCH_OP(op, n, type) type CLANG_ATOMIC_SUFFIX(__sync_fetch_and_ ## op ##_ ## n) (type* ptr, type value) \
+{                                                                                \
+    return __atomic_fetch_ ## op ##_ ## n (ptr, value, __ATOMIC_SEQ_CST);        \
+}                                                                                \
+CLANG_DECLARE_ALIAS( __sync_fetch_and_ ## op ##_ ## n )
+
+#define SYNC_BOOL_CMP_EXCHANGE(n, type) bool  CLANG_ATOMIC_SUFFIX(__sync_bool_compare_and_swap_ ## n)  (type *ptr, type oldval, type newval) \
 {                                                                                \
     bool ret = false;                                                            \
     unsigned state = _ATOMIC_ENTER_CRITICAL();                                   \
@@ -173,9 +193,10 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED;
     }                                                                            \
     _ATOMIC_EXIT_CRITICAL(state);                                                \
     return ret;                                                                  \
-}
+}                                                                                \
+CLANG_DECLARE_ALIAS( __sync_bool_compare_and_swap_ ## n )
 
-#define SYNC_VAL_CMP_EXCHANGE(n, type) type  __sync_val_compare_and_swap_ ## n  (type *ptr, type oldval, type newval) \
+#define SYNC_VAL_CMP_EXCHANGE(n, type) type  CLANG_ATOMIC_SUFFIX(__sync_val_compare_and_swap_ ## n)  (type *ptr, type oldval, type newval) \
 {                                                                                \
     unsigned state = _ATOMIC_ENTER_CRITICAL();                                   \
     type ret = *ptr;                                                             \
@@ -184,7 +205,9 @@ static portMUX_TYPE s_atomic_lock = portMUX_INITIALIZER_UNLOCKED;
     }                                                                            \
     _ATOMIC_EXIT_CRITICAL(state);                                                \
     return ret;                                                                  \
-}
+}                                                                                \
+CLANG_DECLARE_ALIAS( __sync_val_compare_and_swap_ ## n )
+
 
 #if !HAS_ATOMICS_32