1 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Atomic ordering constants.
13 /// These values are used by LLVM to represent atomic ordering for C++11's
14 /// memory model and more, as detailed in docs/Atomics.rst.
16 //===----------------------------------------------------------------------===//
18 #ifndef LLVM_SUPPORT_ATOMICORDERING_H
19 #define LLVM_SUPPORT_ATOMICORDERING_H
25 /// Atomic ordering for C11 / C++11's memody models.
27 /// These values cannot change because they are shared with standard library
28 /// implementations as well as with other compilers.
29 enum class AtomicOrderingCABI {
38 bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
39 bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
40 bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
41 bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
43 // Validate an integral value which isn't known to fit within the enum's range
44 // is a valid AtomicOrderingCABI.
45 template <typename Int> static inline bool isValidAtomicOrderingCABI(Int I) {
46 return (Int)AtomicOrderingCABI::relaxed <= I &&
47 I <= (Int)AtomicOrderingCABI::seq_cst;
50 /// Atomic ordering for LLVM's memory model.
52 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
53 /// Unordered, which are both below the C++ orders.
55 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
56 /// \-->consume-->acquire--/
57 enum class AtomicOrdering {
60 Monotonic = 2, // Equivalent to C++'s relaxed.
61 // Consume = 3, // Not specified yet.
65 SequentiallyConsistent = 7
68 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
69 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
70 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
71 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
73 // Validate an integral value which isn't known to fit within the enum's range
74 // is a valid AtomicOrdering.
75 template <typename Int> static inline bool isValidAtomicOrdering(Int I) {
76 return static_cast<Int>(AtomicOrdering::NotAtomic) <= I &&
77 I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent);
80 /// String used by LLVM IR to represent atomic ordering.
81 static inline const char *toIRString(AtomicOrdering ao) {
82 static const char *names[8] = {"not_atomic", "unordered", "monotonic",
83 "consume", "acquire", "release",
84 "acq_rel", "seq_cst"};
85 return names[static_cast<size_t>(ao)];
88 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
89 /// lattice, which is based on C++'s definition.
90 static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
91 static const bool lookup[8][8] = {
92 // NA UN RX CO AC RE AR SC
93 /* NotAtomic */ {false, false, false, false, false, false, false, false},
94 /* Unordered */ { true, false, false, false, false, false, false, false},
95 /* relaxed */ { true, true, false, false, false, false, false, false},
96 /* consume */ { true, true, true, false, false, false, false, false},
97 /* acquire */ { true, true, true, true, false, false, false, false},
98 /* release */ { true, true, true, false, false, false, false, false},
99 /* acq_rel */ { true, true, true, true, true, true, false, false},
100 /* seq_cst */ { true, true, true, true, true, true, true, false},
102 return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
105 static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao,
106 AtomicOrdering other) {
107 static const bool lookup[8][8] = {
108 // NA UN RX CO AC RE AR SC
109 /* NotAtomic */ { true, false, false, false, false, false, false, false},
110 /* Unordered */ { true, true, false, false, false, false, false, false},
111 /* relaxed */ { true, true, true, false, false, false, false, false},
112 /* consume */ { true, true, true, true, false, false, false, false},
113 /* acquire */ { true, true, true, true, true, false, false, false},
114 /* release */ { true, true, true, false, false, true, false, false},
115 /* acq_rel */ { true, true, true, true, true, true, true, false},
116 /* seq_cst */ { true, true, true, true, true, true, true, true},
118 return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
121 static inline bool isStrongerThanUnordered(AtomicOrdering ao) {
122 return isStrongerThan(ao, AtomicOrdering::Unordered);
125 static inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
126 return isStrongerThan(ao, AtomicOrdering::Monotonic);
129 static inline bool isAcquireOrStronger(AtomicOrdering ao) {
130 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
133 static inline bool isReleaseOrStronger(AtomicOrdering ao) {
134 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
137 static inline AtomicOrderingCABI toCABI(AtomicOrdering ao) {
138 static const AtomicOrderingCABI lookup[8] = {
139 /* NotAtomic */ AtomicOrderingCABI::relaxed,
140 /* Unordered */ AtomicOrderingCABI::relaxed,
141 /* relaxed */ AtomicOrderingCABI::relaxed,
142 /* consume */ AtomicOrderingCABI::consume,
143 /* acquire */ AtomicOrderingCABI::acquire,
144 /* release */ AtomicOrderingCABI::release,
145 /* acq_rel */ AtomicOrderingCABI::acq_rel,
146 /* seq_cst */ AtomicOrderingCABI::seq_cst,
148 return lookup[static_cast<size_t>(ao)];
151 } // end namespace llvm
153 #endif // LLVM_SUPPORT_ATOMICORDERING_H