Home | History | Annotate | Line # | Download | only in Support
      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 memory 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 : 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 
     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> 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 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 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 inline 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 
    120 inline bool isStrongerThanUnordered(AtomicOrdering AO) {
    121   return isStrongerThan(AO, AtomicOrdering::Unordered);
    122 }
    123 
    124 inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
    125   return isStrongerThan(AO, AtomicOrdering::Monotonic);
    126 }
    127 
    128 inline bool isAcquireOrStronger(AtomicOrdering AO) {
    129   return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire);
    130 }
    131 
    132 inline bool isReleaseOrStronger(AtomicOrdering AO) {
    133   return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release);
    134 }
    135 
    136 inline 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