From ff34d401ff385ef7173ca612432b4ea717fff690 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Apr 2012 05:08:17 +0000 Subject: Implement support for 18 of the GNU-compatible __atomic builtins. This is not quite sufficient for libstdc++'s : we still need __atomic_test_and_set and __atomic_clear, and may need a more complete __atomic_is_lock_free implementation. We are also missing an implementation of __atomic_always_lock_free, __atomic_nand_fetch, and __atomic_fetch_nand, but those aren't needed for libstdc++. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154579 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 37 ++++++++++++----- include/clang/Basic/Builtins.def | 66 +++++++++++++++++++----------- include/clang/Basic/DiagnosticSemaKinds.td | 41 ++++++++++--------- 3 files changed, 90 insertions(+), 54 deletions(-) (limited to 'include/clang') diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 0db9195a27..558bd00ba9 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -4470,14 +4470,21 @@ public: /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the -/// similarly-named C++11 instructions. All of these instructions take one -/// primary pointer and at least one memory order. +/// similarly-named C++11 instructions, and __c11 variants for . +/// All of these instructions take one primary pointer and at least one memory +/// order. class AtomicExpr : public Expr { public: - enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg, - Add, Sub, And, Or, Xor, Init }; + enum AtomicOp { +#define BUILTIN(ID, TYPE, ATTRS) +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, +#include "clang/Basic/Builtins.def" + // Avoid trailing comma + BI_First = 0 + }; + private: - enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR }; + enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; unsigned NumSubExprs; SourceLocation BuiltinLoc, RParenLoc; @@ -4503,19 +4510,25 @@ public: return cast(SubExprs[ORDER]); } Expr *getVal1() const { - if (Op == Init) + if (Op == AO__c11_atomic_init) return cast(SubExprs[ORDER]); - assert(NumSubExprs >= 3); + assert(NumSubExprs > VAL1); return cast(SubExprs[VAL1]); } Expr *getOrderFail() const { - assert(NumSubExprs == 5); + assert(NumSubExprs > ORDER_FAIL); return cast(SubExprs[ORDER_FAIL]); } Expr *getVal2() const { - assert(NumSubExprs == 5); + if (Op == AO__atomic_exchange) + return cast(SubExprs[ORDER_FAIL]); + assert(NumSubExprs > VAL2); return cast(SubExprs[VAL2]); } + Expr *getWeak() const { + assert(NumSubExprs > WEAK); + return cast(SubExprs[WEAK]); + } AtomicOp getOp() const { return Op; } unsigned getNumSubExprs() { return NumSubExprs; } @@ -4527,8 +4540,10 @@ public: } bool isCmpXChg() const { - return getOp() == AtomicExpr::CmpXchgStrong || - getOp() == AtomicExpr::CmpXchgWeak; + return getOp() == AO__c11_atomic_compare_exchange_strong || + getOp() == AO__c11_atomic_compare_exchange_weak || + getOp() == AO__atomic_compare_exchange || + getOp() == AO__atomic_compare_exchange_n; } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 82f0463d8c..2823190ca4 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -594,37 +594,55 @@ BUILTIN(__sync_swap_4, "iiD*i.", "tn") BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "tn") +// Some of our atomics builtins are handled by AtomicExpr rather than +// as normal builtin CallExprs. This macro is used for such builtins. +#ifndef ATOMIC_BUILTIN +#define ATOMIC_BUILTIN(ID, TYPE, ATTRS) BUILTIN(ID, TYPE, ATTRS) +#endif + // C11 _Atomic operations for . -BUILTIN(__c11_atomic_load, "v.", "t") -BUILTIN(__c11_atomic_store, "v.", "t") -BUILTIN(__c11_atomic_exchange, "v.", "t") -BUILTIN(__c11_atomic_compare_exchange_strong, "v.", "t") -BUILTIN(__c11_atomic_compare_exchange_weak, "v.", "t") -BUILTIN(__c11_atomic_fetch_add, "v.", "t") -BUILTIN(__c11_atomic_fetch_sub, "v.", "t") -BUILTIN(__c11_atomic_fetch_and, "v.", "t") -BUILTIN(__c11_atomic_fetch_or, "v.", "t") -BUILTIN(__c11_atomic_fetch_xor, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_init, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_load, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_store, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_compare_exchange_strong, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_compare_exchange_weak, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__c11_atomic_fetch_xor, "v.", "t") BUILTIN(__c11_atomic_thread_fence, "vi", "n") BUILTIN(__c11_atomic_signal_fence, "vi", "n") -BUILTIN(__c11_atomic_init, "v.", "t") BUILTIN(__c11_atomic_is_lock_free, "iz", "n") -// FIXME: Convert these to implementing GNU atomic builtins. -BUILTIN(__atomic_load, "v.", "t") -BUILTIN(__atomic_store, "v.", "t") -BUILTIN(__atomic_exchange, "v.", "t") -BUILTIN(__atomic_compare_exchange_strong, "v.", "t") -BUILTIN(__atomic_compare_exchange_weak, "v.", "t") -BUILTIN(__atomic_fetch_add, "v.", "t") -BUILTIN(__atomic_fetch_sub, "v.", "t") -BUILTIN(__atomic_fetch_and, "v.", "t") -BUILTIN(__atomic_fetch_or, "v.", "t") -BUILTIN(__atomic_fetch_xor, "v.", "t") +// GNU atomic builtins. +ATOMIC_BUILTIN(__atomic_load, "v.", "t") +ATOMIC_BUILTIN(__atomic_load_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_store, "v.", "t") +ATOMIC_BUILTIN(__atomic_store_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_exchange, "v.", "t") +ATOMIC_BUILTIN(__atomic_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_compare_exchange, "v.", "t") +ATOMIC_BUILTIN(__atomic_compare_exchange_n, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_add, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_sub, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_and, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_or, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_xor, "v.", "t") +ATOMIC_BUILTIN(__atomic_add_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_sub_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_and_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_or_fetch, "v.", "t") +ATOMIC_BUILTIN(__atomic_xor_fetch, "v.", "t") +BUILTIN(__atomic_test_and_set, "vv*i", "n") +BUILTIN(__atomic_clear, "vb*i", "n") BUILTIN(__atomic_thread_fence, "vi", "n") BUILTIN(__atomic_signal_fence, "vi", "n") -BUILTIN(__atomic_init, "v.", "t") -BUILTIN(__atomic_is_lock_free, "iz", "n") +BUILTIN(__atomic_always_lock_free, "izv*", "n") +BUILTIN(__atomic_is_lock_free, "izv*", "n") + +#undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. BUILTIN(__sync_synchronize, "v.", "n") diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 39bd5ac94e..86d139da0c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -4367,22 +4367,22 @@ def ext_typecheck_convert_pointer_int : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1; " - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">, + "with an expression of type|to parameter of type|to type}2 %1" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, InGroup; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1; " - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">, + "with an expression of type|to parameter of type|to type}2 %1" + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, InGroup; def ext_typecheck_convert_pointer_void_func : Extension< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" @@ -4403,10 +4403,10 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn< " %0 " "%select{from|to parameter of type|from a function with result type|to type|" "with an expression of type|to parameter of type|to type}2 %1" - "%select{|dereference with *|" - "take the address with &|" - "remove *|" - "remove &}3">, + "%select{|; dereference with *|" + "; take the address with &|" + "; remove *|" + "; remove &}3">, InGroup; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" @@ -4522,12 +4522,15 @@ def err_atomic_builtin_pointer_size : Error< def err_atomic_op_needs_atomic : Error< "first argument to atomic operation must be a pointer to _Atomic " "type (%0 invalid)">; +def err_atomic_op_needs_trivial_copy : Error< + "first argument to atomic operation must be a pointer to a trivially-copyable" + " type (%0 invalid)">; def err_atomic_op_needs_atomic_int_or_ptr : Error< - "first argument to atomic operation must be a pointer to atomic " - "integer or pointer (%0 invalid)">; -def err_atomic_op_logical_needs_atomic_int : Error< - "first argument to logical atomic operation must be a pointer to atomic " - "integer (%0 invalid)">; + "first argument to atomic operation must be a pointer to %select{|atomic }0" + "integer or pointer (%1 invalid)">; +def err_atomic_op_bitwise_needs_atomic_int : Error< + "first argument to bitwise atomic operation must be a pointer to " + "%select{|atomic }0integer (%1 invalid)">; def err_deleted_function_use : Error<"attempt to use a deleted function">; -- cgit v1.2.3