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