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
23namespace 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.
29enum class AtomicOrderingCABI {
30 relaxed = 0,
31 consume = 1,
32 acquire = 2,
33 release = 3,
34 acq_rel = 4,
35 seq_cst = 5,
36};
37
38bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
39bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
40bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
41bool 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.
45template <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--/
57enum 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
68bool operator<(AtomicOrdering, AtomicOrdering) = delete;
69bool operator>(AtomicOrdering, AtomicOrdering) = delete;
70bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
71bool 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.
75template <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.
81inline 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.
90inline 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
105inline 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
120inline bool isStrongerThanUnordered(AtomicOrdering ao) {
121 return isStrongerThan(ao, AtomicOrdering::Unordered);
122}
123
124inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
125 return isStrongerThan(ao, AtomicOrdering::Monotonic);
126}
127
128inline bool isAcquireOrStronger(AtomicOrdering ao) {
129 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
130}
131
132inline bool isReleaseOrStronger(AtomicOrdering ao) {
133 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
134}
135
136inline 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