Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:27

0001 //===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// Atomic ordering constants.
0011 ///
0012 /// These values are used by LLVM to represent atomic ordering for C++11's
0013 /// memory model and more, as detailed in docs/Atomics.rst.
0014 ///
0015 //===----------------------------------------------------------------------===//
0016 
0017 #ifndef LLVM_SUPPORT_ATOMICORDERING_H
0018 #define LLVM_SUPPORT_ATOMICORDERING_H
0019 
0020 #include <cstddef>
0021 
0022 namespace llvm {
0023 
0024 /// Atomic ordering for C11 / C++11's memory models.
0025 ///
0026 /// These values cannot change because they are shared with standard library
0027 /// implementations as well as with other compilers.
0028 enum class AtomicOrderingCABI {
0029   relaxed = 0,
0030   consume = 1,
0031   acquire = 2,
0032   release = 3,
0033   acq_rel = 4,
0034   seq_cst = 5,
0035 };
0036 
0037 bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
0038 bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
0039 bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
0040 bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete;
0041 
0042 // Validate an integral value which isn't known to fit within the enum's range
0043 // is a valid AtomicOrderingCABI.
0044 template <typename Int> inline bool isValidAtomicOrderingCABI(Int I) {
0045   return (Int)AtomicOrderingCABI::relaxed <= I &&
0046          I <= (Int)AtomicOrderingCABI::seq_cst;
0047 }
0048 
0049 /// Atomic ordering for LLVM's memory model.
0050 ///
0051 /// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and
0052 /// Unordered, which are both below the C++ orders.
0053 ///
0054 /// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
0055 ///                                   \-->consume-->acquire--/
0056 enum class AtomicOrdering : unsigned {
0057   NotAtomic = 0,
0058   Unordered = 1,
0059   Monotonic = 2, // Equivalent to C++'s relaxed.
0060   // Consume = 3,  // Not specified yet.
0061   Acquire = 4,
0062   Release = 5,
0063   AcquireRelease = 6,
0064   SequentiallyConsistent = 7,
0065   LAST = SequentiallyConsistent
0066 };
0067 
0068 bool operator<(AtomicOrdering, AtomicOrdering) = delete;
0069 bool operator>(AtomicOrdering, AtomicOrdering) = delete;
0070 bool operator<=(AtomicOrdering, AtomicOrdering) = delete;
0071 bool operator>=(AtomicOrdering, AtomicOrdering) = delete;
0072 
0073 // Validate an integral value which isn't known to fit within the enum's range
0074 // is a valid AtomicOrdering.
0075 template <typename Int> inline bool isValidAtomicOrdering(Int I) {
0076   return static_cast<Int>(AtomicOrdering::NotAtomic) <= I &&
0077          I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent) &&
0078          I != 3;
0079 }
0080 
0081 /// String used by LLVM IR to represent atomic ordering.
0082 inline const char *toIRString(AtomicOrdering ao) {
0083   static const char *names[8] = {"not_atomic", "unordered", "monotonic",
0084                                  "consume",    "acquire",   "release",
0085                                  "acq_rel",    "seq_cst"};
0086   return names[static_cast<size_t>(ao)];
0087 }
0088 
0089 /// Returns true if ao is stronger than other as defined by the AtomicOrdering
0090 /// lattice, which is based on C++'s definition.
0091 inline bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
0092   static const bool lookup[8][8] = {
0093       //               NA     UN     RX     CO     AC     RE     AR     SC
0094       /* NotAtomic */ {false, false, false, false, false, false, false, false},
0095       /* Unordered */ { true, false, false, false, false, false, false, false},
0096       /* relaxed   */ { true,  true, false, false, false, false, false, false},
0097       /* consume   */ { true,  true,  true, false, false, false, false, false},
0098       /* acquire   */ { true,  true,  true,  true, false, false, false, false},
0099       /* release   */ { true,  true,  true, false, false, false, false, false},
0100       /* acq_rel   */ { true,  true,  true,  true,  true,  true, false, false},
0101       /* seq_cst   */ { true,  true,  true,  true,  true,  true,  true, false},
0102   };
0103   return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
0104 }
0105 
0106 inline bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
0107   static const bool lookup[8][8] = {
0108       //               NA     UN     RX     CO     AC     RE     AR     SC
0109       /* NotAtomic */ { true, false, false, false, false, false, false, false},
0110       /* Unordered */ { true,  true, false, false, false, false, false, false},
0111       /* relaxed   */ { true,  true,  true, false, false, false, false, false},
0112       /* consume   */ { true,  true,  true,  true, false, false, false, false},
0113       /* acquire   */ { true,  true,  true,  true,  true, false, false, false},
0114       /* release   */ { true,  true,  true, false, false,  true, false, false},
0115       /* acq_rel   */ { true,  true,  true,  true,  true,  true,  true, false},
0116       /* seq_cst   */ { true,  true,  true,  true,  true,  true,  true,  true},
0117   };
0118   return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
0119 }
0120 
0121 inline bool isStrongerThanUnordered(AtomicOrdering AO) {
0122   return isStrongerThan(AO, AtomicOrdering::Unordered);
0123 }
0124 
0125 inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
0126   return isStrongerThan(AO, AtomicOrdering::Monotonic);
0127 }
0128 
0129 inline bool isAcquireOrStronger(AtomicOrdering AO) {
0130   return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire);
0131 }
0132 
0133 inline bool isReleaseOrStronger(AtomicOrdering AO) {
0134   return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release);
0135 }
0136 
0137 /// Return a single atomic ordering that is at least as strong as both the \p AO
0138 /// and \p Other orderings for an atomic operation.
0139 inline AtomicOrdering getMergedAtomicOrdering(AtomicOrdering AO,
0140                                               AtomicOrdering Other) {
0141   if ((AO == AtomicOrdering::Acquire && Other == AtomicOrdering::Release) ||
0142       (AO == AtomicOrdering::Release && Other == AtomicOrdering::Acquire))
0143     return AtomicOrdering::AcquireRelease;
0144   return isStrongerThan(AO, Other) ? AO : Other;
0145 }
0146 
0147 inline AtomicOrderingCABI toCABI(AtomicOrdering AO) {
0148   static const AtomicOrderingCABI lookup[8] = {
0149       /* NotAtomic */ AtomicOrderingCABI::relaxed,
0150       /* Unordered */ AtomicOrderingCABI::relaxed,
0151       /* relaxed   */ AtomicOrderingCABI::relaxed,
0152       /* consume   */ AtomicOrderingCABI::consume,
0153       /* acquire   */ AtomicOrderingCABI::acquire,
0154       /* release   */ AtomicOrderingCABI::release,
0155       /* acq_rel   */ AtomicOrderingCABI::acq_rel,
0156       /* seq_cst   */ AtomicOrderingCABI::seq_cst,
0157   };
0158   return lookup[static_cast<size_t>(AO)];
0159 }
0160 
0161 } // end namespace llvm
0162 
0163 #endif // LLVM_SUPPORT_ATOMICORDERING_H