• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// Atomic ordering constants.
11 ///
12 /// These values are used by LLVM to represent atomic ordering for C++11's
13 /// memory model and more, as detailed in docs/Atomics.rst.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_SUPPORT_ATOMICORDERING_H
18 #define LLVM_SUPPORT_ATOMICORDERING_H
19 
20 #include <cstddef>
21 
22 namespace llvm {
23 
24 /// Atomic ordering for C11 / C++11's memody models.
25 ///
26 /// These values cannot change because they are shared with standard library
27 /// implementations as well as with other compilers.
28 enum class AtomicOrderingCABI {
29   relaxed = 0,
30   consume = 1,
31   acquire = 2,
32   release = 3,
33   acq_rel = 4,
34   seq_cst = 5,
35 };
36 
37 bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
38 bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
39 bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
40 bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
41 
42 // Validate an integral value which isn't known to fit within the enum's range
43 // is a valid AtomicOrderingCABI.
isValidAtomicOrderingCABI(Int I)44 template <typename Int> inline bool isValidAtomicOrderingCABI(Int I) {
45   return (Int)AtomicOrderingCABI::relaxed <= I &&
46          I <= (Int)AtomicOrderingCABI::seq_cst;
47 }
48 
49 /// Atomic ordering for LLVM's memory model.
50 ///
51 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
52 /// Unordered, which are both below the C++ orders.
53 ///
54 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
55 ///                                   \-->consume-->acquire--/
56 enum class AtomicOrdering {
57   NotAtomic = 0,
58   Unordered = 1,
59   Monotonic = 2, // Equivalent to C++'s relaxed.
60   // Consume = 3,  // Not specified yet.
61   Acquire = 4,
62   Release = 5,
63   AcquireRelease = 6,
64   SequentiallyConsistent = 7
65 };
66 
67 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
68 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
69 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
70 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
71 
72 // Validate an integral value which isn't known to fit within the enum's range
73 // is a valid AtomicOrdering.
isValidAtomicOrdering(Int I)74 template <typename Int> inline bool isValidAtomicOrdering(Int I) {
75   return static_cast<Int>(AtomicOrdering::NotAtomic) <= I &&
76          I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent);
77 }
78 
79 /// String used by LLVM IR to represent atomic ordering.
toIRString(AtomicOrdering ao)80 inline const char *toIRString(AtomicOrdering ao) {
81   static const char *names[8] = {"not_atomic", "unordered", "monotonic",
82                                  "consume",    "acquire",   "release",
83                                  "acq_rel",    "seq_cst"};
84   return names[static_cast<size_t>(ao)];
85 }
86 
87 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
88 /// lattice, which is based on C++'s definition.
isStrongerThan(AtomicOrdering ao,AtomicOrdering other)89 inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
90   static const bool lookup[8][8] = {
91       //               NA     UN     RX     CO     AC     RE     AR     SC
92       /* NotAtomic */ {false, false, false, false, false, false, false, false},
93       /* Unordered */ { true, false, false, false, false, false, false, false},
94       /* relaxed   */ { true,  true, false, false, false, false, false, false},
95       /* consume   */ { true,  true,  true, false, false, false, false, false},
96       /* acquire   */ { true,  true,  true,  true, false, false, false, false},
97       /* release   */ { true,  true,  true, false, false, false, false, false},
98       /* acq_rel   */ { true,  true,  true,  true,  true,  true, false, false},
99       /* seq_cst   */ { true,  true,  true,  true,  true,  true,  true, false},
100   };
101   return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
102 }
103 
isAtLeastOrStrongerThan(AtomicOrdering ao,AtomicOrdering other)104 inline bool isAtLeastOrStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
105   static const bool lookup[8][8] = {
106       //               NA     UN     RX     CO     AC     RE     AR     SC
107       /* NotAtomic */ { true, false, false, false, false, false, false, false},
108       /* Unordered */ { true,  true, false, false, false, false, false, false},
109       /* relaxed   */ { true,  true,  true, false, false, false, false, false},
110       /* consume   */ { true,  true,  true,  true, false, false, false, false},
111       /* acquire   */ { true,  true,  true,  true,  true, false, false, false},
112       /* release   */ { true,  true,  true, false, false,  true, false, false},
113       /* acq_rel   */ { true,  true,  true,  true,  true,  true,  true, false},
114       /* seq_cst   */ { true,  true,  true,  true,  true,  true,  true,  true},
115   };
116   return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
117 }
118 
isStrongerThanUnordered(AtomicOrdering ao)119 inline bool isStrongerThanUnordered(AtomicOrdering ao) {
120   return isStrongerThan(ao, AtomicOrdering::Unordered);
121 }
122 
isStrongerThanMonotonic(AtomicOrdering ao)123 inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
124   return isStrongerThan(ao, AtomicOrdering::Monotonic);
125 }
126 
isAcquireOrStronger(AtomicOrdering ao)127 inline bool isAcquireOrStronger(AtomicOrdering ao) {
128   return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
129 }
130 
isReleaseOrStronger(AtomicOrdering ao)131 inline bool isReleaseOrStronger(AtomicOrdering ao) {
132   return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
133 }
134 
toCABI(AtomicOrdering ao)135 inline AtomicOrderingCABI toCABI(AtomicOrdering ao) {
136   static const AtomicOrderingCABI lookup[8] = {
137       /* NotAtomic */ AtomicOrderingCABI::relaxed,
138       /* Unordered */ AtomicOrderingCABI::relaxed,
139       /* relaxed   */ AtomicOrderingCABI::relaxed,
140       /* consume   */ AtomicOrderingCABI::consume,
141       /* acquire   */ AtomicOrderingCABI::acquire,
142       /* release   */ AtomicOrderingCABI::release,
143       /* acq_rel   */ AtomicOrderingCABI::acq_rel,
144       /* seq_cst   */ AtomicOrderingCABI::seq_cst,
145   };
146   return lookup[static_cast<size_t>(ao)];
147 }
148 
149 } // end namespace llvm
150 
151 #endif // LLVM_SUPPORT_ATOMICORDERING_H
152