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. 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. 75 template <typename Int> static 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 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[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 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 */ {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 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 */ { true, false, false, false, false, false, false, false}, 110 /* Unordered */ { true, true, false, false, false, false, false, false}, 111 /* relaxed */ { true, true, true, false, false, false, false, false}, 112 /* consume */ { true, true, true, true, false, false, false, false}, 113 /* acquire */ { true, true, true, true, true, false, false, false}, 114 /* release */ { true, true, true, false, false, true, false, false}, 115 /* acq_rel */ { true, true, true, true, true, true, true, false}, 116 /* seq_cst */ { true, true, true, true, true, true, true, true}, 117 }; 118 return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)]; 119 } 120 121 static inline bool isStrongerThanUnordered(AtomicOrdering ao) { 122 return isStrongerThan(ao, AtomicOrdering::Unordered); 123 } 124 125 static inline bool isStrongerThanMonotonic(AtomicOrdering ao) { 126 return isStrongerThan(ao, AtomicOrdering::Monotonic); 127 } 128 129 static inline bool isAcquireOrStronger(AtomicOrdering ao) { 130 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire); 131 } 132 133 static inline bool isReleaseOrStronger(AtomicOrdering ao) { 134 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release); 135 } 136 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[static_cast<size_t>(ao)]; 149 } 150 151 } // end namespace llvm 152 153 #endif // LLVM_SUPPORT_ATOMICORDERING_H 154