-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] constexpr atomic builtins (__c11_atomic_OP and __atomic_OP) #98756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7d65b13
1994a55
8aee298
9de180f
537178b
b87075c
5318bcc
34b174d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4340,6 +4340,18 @@ whole system, the current device, an OpenCL workgroup, wavefront, or just a | |||||||||
| single thread. If these are used on a target that does not support atomic | ||||||||||
| scopes, then they will behave exactly as the standard GNU atomic builtins. | ||||||||||
|
|
||||||||||
| Constant evaluatable atomic builtins | ||||||||||
| ------------------------------------ | ||||||||||
|
|
||||||||||
| Clang supports constant evaluation of all ``__c11_atomic_*`` and GCC-compatible | ||||||||||
| ``__atomic_*`` builtins. Behaviour of identical as if evaluating these builtins | ||||||||||
| in a single-threaded environment. | ||||||||||
|
|
||||||||||
| (Note the GCC-compatible ``__atomic_fetch_OP`` and ``__atomic_OP_fetch`` | ||||||||||
| builtins with a pointer argument operates as if pointer was pointing to bytes. | ||||||||||
| Evaluating these builtins which would result in a non-aligned pointer to pointee | ||||||||||
|
Comment on lines
+4351
to
+4352
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| type is unsupported.) | ||||||||||
|
|
||||||||||
| Low-level ARM exclusive memory builtins | ||||||||||
| --------------------------------------- | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1744,97 +1744,97 @@ def SyncSwapN : Builtin, SyncBuiltinsTemplate { | |
| // C11 _Atomic operations for <stdatomic.h>. | ||
| def C11AtomicInit : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_init"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicLoad : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_load"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm worried about changing the C11 atomic builtins for a C++26 feature; I think there are more changes needed as a result. For example, changing this to be constexpr means we now run the risk of accepting this code in C: https://godbolt.org/z/hc3oqYx6b We likely are missing test coverage for this kind of thing in C, so I would recommend 1) add test coverage to this PR and if it breaks as a result of these changes, then 2) I would probably add some Hmm, but I just remembered that |
||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicStore : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_store"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicExchange : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicCompareExchangeStrong : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_compare_exchange_strong"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicCompareExchangeWeak : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_compare_exchange_weak"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchAdd : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_add"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchSub : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_sub"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchAnd : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_and"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchOr : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_or"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchXor : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_xor"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchNand : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_nand"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchMax : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_max"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicFetchMin : AtomicBuiltin { | ||
| let Spellings = ["__c11_atomic_fetch_min"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def C11AtomicThreadFence : Builtin { | ||
| let Spellings = ["__c11_atomic_thread_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
| def C11AtomicSignalFence : Builtin { | ||
| let Spellings = ["__c11_atomic_signal_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
@@ -1847,133 +1847,133 @@ def C11AtomicIsLockFree : Builtin { | |
| // GNU atomic builtins. | ||
| def AtomicLoad : AtomicBuiltin { | ||
| let Spellings = ["__atomic_load"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When removing the constexpr-ness from these functions in C, please also make sure |
||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicLoadN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_load_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicStore : AtomicBuiltin { | ||
| let Spellings = ["__atomic_store"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicStoreN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_store_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicExchange : AtomicBuiltin { | ||
| let Spellings = ["__atomic_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicExchangeN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_exchange_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicCompareExchange : AtomicBuiltin { | ||
| let Spellings = ["__atomic_compare_exchange"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicCompareExchangeN : AtomicBuiltin { | ||
| let Spellings = ["__atomic_compare_exchange_n"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchAdd : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_add"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchSub : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_sub"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchAnd : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_and"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchOr : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_or"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchXor : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_xor"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicFetchNand : AtomicBuiltin { | ||
| let Spellings = ["__atomic_fetch_nand"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicAddFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_add_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicSubFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_sub_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicAndFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_and_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicOrFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_or_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicXorFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_xor_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicMaxFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_max_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicMinFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_min_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
| def AtomicNandFetch : AtomicBuiltin { | ||
| let Spellings = ["__atomic_nand_fetch"]; | ||
| let Attributes = [CustomTypeChecking]; | ||
| let Attributes = [CustomTypeChecking, Constexpr]; | ||
| let Prototype = "void(...)"; | ||
| } | ||
|
|
||
|
|
@@ -1991,7 +1991,7 @@ def AtomicClear : Builtin { | |
|
|
||
| def AtomicThreadFence : Builtin { | ||
| let Spellings = ["__atomic_thread_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
@@ -2003,7 +2003,7 @@ def ScopedAtomicThreadFence : Builtin { | |
|
|
||
| def AtomicSignalFence : Builtin { | ||
| let Spellings = ["__atomic_signal_fence"]; | ||
| let Attributes = [NoThrow]; | ||
| let Attributes = [NoThrow, Constexpr]; | ||
| let Prototype = "void(int)"; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -389,6 +389,12 @@ def note_constexpr_assumption_failed : Note< | |
| "assumption evaluated to false">; | ||
| def err_experimental_clang_interp_failed : Error< | ||
| "the experimental clang interpreter failed to evaluate an expression">; | ||
| def note_unaligned_atomic_pointer_op : Note< | ||
| "atomic pointer operation with argument %0 not aligned to size of pointee type (sizeof %1 is %2)">; | ||
| def note_constexpr_atomic_ops_only_in_cpp : Note< | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This note is not emitted anywhere, but also, I don't think a note's the correct way to go because that will fail at constant expression time but |
||
| "constant evaluated atomic operations are supported only in C++ mode">; | ||
| def note_atomic_op_with_invalid_memory_order : Note< | ||
| "evaluated %select{|success |failure }0memory order argument to atomic operation is not allowed">; | ||
|
|
||
| def warn_integer_constant_overflow : Warning< | ||
| "overflow in expression; result is %0 with type %1">, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.