Home | History | Annotate | Download | only in Support
      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