• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Atomic ordering constants.
12 ///
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.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_SUPPORT_ATOMICORDERING_H
19 #define LLVM_SUPPORT_ATOMICORDERING_H
20 
21 #include <cstddef>
22 
23 namespace llvm {
24 
25 /// Atomic ordering for C11 / C++11's memody models.
26 ///
27 /// These values cannot change because they are shared with standard library
28 /// implementations as well as with other compilers.
29 enum class AtomicOrderingCABI {
30   relaxed = 0,
31   consume = 1,
32   acquire = 2,
33   release = 3,
34   acq_rel = 4,
35   seq_cst = 5,
36 };
37 
38 bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
39 bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
40 bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
41 bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
42 
43 // Validate an integral value which isn't known to fit within the enum's range
44 // is a valid AtomicOrderingCABI.
isValidAtomicOrderingCABI(Int I)45 template <typename Int> static inline bool isValidAtomicOrderingCABI(Int I) {
46   return (Int)AtomicOrderingCABI::relaxed <= I &&
47          I <= (Int)AtomicOrderingCABI::seq_cst;
48 }
49 
50 /// Atomic ordering for LLVM's memory model.
51 ///
52 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
53 /// Unordered, which are both below the C++ orders.
54 ///
55 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
56 ///                                   \-->consume-->acquire--/
57 enum class AtomicOrdering {
58   NotAtomic = 0,
59   Unordered = 1,
60   Monotonic = 2, // Equivalent to C++'s relaxed.
61   // Consume = 3,  // Not specified yet.
62   Acquire = 4,
63   Release = 5,
64   AcquireRelease = 6,
65   SequentiallyConsistent = 7
66 };
67 
68 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
69 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
70 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
71 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
72 
73 // Validate an integral value which isn't known to fit within the enum's range
74 // is a valid AtomicOrdering.
isValidAtomicOrdering(Int I)75 template <typename Int> static inline bool isValidAtomicOrdering(Int I) {
76   return (Int)AtomicOrdering::NotAtomic <= I &&
77          I <= (Int)AtomicOrdering::SequentiallyConsistent;
78 }
79 
80 /// String used by LLVM IR to represent atomic ordering.
toIRString(AtomicOrdering ao)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[(size_t)ao];
86 }
87 
88 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
89 /// lattice, which is based on C++'s definition.
isStrongerThan(AtomicOrdering ao,AtomicOrdering other)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 */ {0, 0, 0, 0, 0, 0, 0, 0},
94       /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0},
95       /* relaxed   */ {1, 1, 0, 0, 0, 0, 0, 0},
96       /* consume   */ {1, 1, 1, 0, 0, 0, 0, 0},
97       /* acquire   */ {1, 1, 1, 1, 0, 0, 0, 0},
98       /* release   */ {1, 1, 1, 0, 0, 0, 0, 0},
99       /* acq_rel   */ {1, 1, 1, 1, 1, 1, 0, 0},
100       /* seq_cst   */ {1, 1, 1, 1, 1, 1, 1, 0},
101   };
102   return lookup[(size_t)ao][(size_t)other];
103 }
104 
isAtLeastOrStrongerThan(AtomicOrdering ao,AtomicOrdering 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 */ {1, 0, 0, 0, 0, 0, 0, 0},
110       /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0},
111       /* relaxed   */ {1, 1, 1, 0, 0, 0, 0, 0},
112       /* consume   */ {1, 1, 1, 1, 0, 0, 0, 0},
113       /* acquire   */ {1, 1, 1, 1, 1, 0, 0, 0},
114       /* release   */ {1, 1, 1, 0, 0, 1, 0, 0},
115       /* acq_rel   */ {1, 1, 1, 1, 1, 1, 1, 0},
116       /* seq_cst   */ {1, 1, 1, 1, 1, 1, 1, 1},
117   };
118   return lookup[(size_t)ao][(size_t)other];
119 }
120 
isStrongerThanUnordered(AtomicOrdering ao)121 static inline bool isStrongerThanUnordered(AtomicOrdering ao) {
122   return isStrongerThan(ao, AtomicOrdering::Unordered);
123 }
124 
isStrongerThanMonotonic(AtomicOrdering ao)125 static inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
126   return isStrongerThan(ao, AtomicOrdering::Monotonic);
127 }
128 
isAcquireOrStronger(AtomicOrdering ao)129 static inline bool isAcquireOrStronger(AtomicOrdering ao) {
130   return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
131 }
132 
isReleaseOrStronger(AtomicOrdering ao)133 static inline bool isReleaseOrStronger(AtomicOrdering ao) {
134   return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
135 }
136 
toCABI(AtomicOrdering ao)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,
147   };
148   return lookup[(size_t)ao];
149 }
150 
151 } // end namespace llvm
152 
153 #endif // LLVM_SUPPORT_ATOMICORDERING_H
154