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 | /// 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. |
45 | template <typename Int> 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. |
75 | template <typename Int> inline bool isValidAtomicOrdering(Int I) { |
76 | return static_cast<Int>(AtomicOrdering::NotAtomic) <= I && |
77 | I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent); |
78 | } |
79 | |
80 | /// String used by LLVM IR to represent atomic ordering. |
81 | 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)]; |
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. |
90 | 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}, |
101 | }; |
102 | return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)]; |
103 | } |
104 | |
105 | inline bool isAtLeastOrStrongerThan(AtomicOrdering ao, AtomicOrdering other) { |
106 | static const bool lookup[8][8] = { |
107 | // NA UN RX CO AC RE AR SC |
108 | /* NotAtomic */ { true, false, false, false, false, false, false, false}, |
109 | /* Unordered */ { true, true, false, false, false, false, false, false}, |
110 | /* relaxed */ { true, true, true, false, false, false, false, false}, |
111 | /* consume */ { true, true, true, true, false, false, false, false}, |
112 | /* acquire */ { true, true, true, true, true, false, false, false}, |
113 | /* release */ { true, true, true, false, false, true, false, false}, |
114 | /* acq_rel */ { true, true, true, true, true, true, true, false}, |
115 | /* seq_cst */ { true, true, true, true, true, true, true, true}, |
116 | }; |
117 | return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)]; |
118 | } |
119 | |
120 | inline bool isStrongerThanUnordered(AtomicOrdering ao) { |
121 | return isStrongerThan(ao, AtomicOrdering::Unordered); |
122 | } |
123 | |
124 | inline bool isStrongerThanMonotonic(AtomicOrdering ao) { |
125 | return isStrongerThan(ao, AtomicOrdering::Monotonic); |
126 | } |
127 | |
128 | inline bool isAcquireOrStronger(AtomicOrdering ao) { |
129 | return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire); |
130 | } |
131 | |
132 | inline bool isReleaseOrStronger(AtomicOrdering ao) { |
133 | return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release); |
134 | } |
135 | |
136 | inline AtomicOrderingCABI toCABI(AtomicOrdering ao) { |
137 | static const AtomicOrderingCABI lookup[8] = { |
138 | /* NotAtomic */ AtomicOrderingCABI::relaxed, |
139 | /* Unordered */ AtomicOrderingCABI::relaxed, |
140 | /* relaxed */ AtomicOrderingCABI::relaxed, |
141 | /* consume */ AtomicOrderingCABI::consume, |
142 | /* acquire */ AtomicOrderingCABI::acquire, |
143 | /* release */ AtomicOrderingCABI::release, |
144 | /* acq_rel */ AtomicOrderingCABI::acq_rel, |
145 | /* seq_cst */ AtomicOrderingCABI::seq_cst, |
146 | }; |
147 | return lookup[static_cast<size_t>(ao)]; |
148 | } |
149 | |
150 | } // end namespace llvm |
151 | |
152 | #endif // LLVM_SUPPORT_ATOMICORDERING_H |
153 | |