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. 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. 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. 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. 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 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 119 inline bool isStrongerThanUnordered(AtomicOrdering ao) { 120 return isStrongerThan(ao, AtomicOrdering::Unordered); 121 } 122 123 inline bool isStrongerThanMonotonic(AtomicOrdering ao) { 124 return isStrongerThan(ao, AtomicOrdering::Monotonic); 125 } 126 127 inline bool isAcquireOrStronger(AtomicOrdering ao) { 128 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire); 129 } 130 131 inline bool isReleaseOrStronger(AtomicOrdering ao) { 132 return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release); 133 } 134 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