Line data Source code
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 16154 : 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 4620 : 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 18563513 : 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 6007 : 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 182 : return lookup[static_cast<size_t>(ao)];
148 : }
149 :
150 : } // end namespace llvm
151 :
152 : #endif // LLVM_SUPPORT_ATOMICORDERING_H
|