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 22namespace llvm { 23 24/// Atomic ordering for C11 / C++11's memory models. 25/// 26/// These values cannot change because they are shared with standard library 27/// implementations as well as with other compilers. 28enum class AtomicOrderingCABI { 29 relaxed = 0, 30 consume = 1, 31 acquire = 2, 32 release = 3, 33 acq_rel = 4, 34 seq_cst = 5, 35}; 36 37bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 38bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 39bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; 40bool 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. 44template <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--/ 56enum class AtomicOrdering : unsigned { 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 LAST = SequentiallyConsistent 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