Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. /// Return a single atomic ordering that is at least as strong as both the \p AO
  137. /// and \p Other orderings for an atomic operation.
  138. inline AtomicOrdering getMergedAtomicOrdering(AtomicOrdering AO,
  139.                                               AtomicOrdering Other) {
  140.   if ((AO == AtomicOrdering::Acquire && Other == AtomicOrdering::Release) ||
  141.       (AO == AtomicOrdering::Release && Other == AtomicOrdering::Acquire))
  142.     return AtomicOrdering::AcquireRelease;
  143.   return isStrongerThan(AO, Other) ? AO : Other;
  144. }
  145.  
  146. inline AtomicOrderingCABI toCABI(AtomicOrdering AO) {
  147.   static const AtomicOrderingCABI lookup[8] = {
  148.       /* NotAtomic */ AtomicOrderingCABI::relaxed,
  149.       /* Unordered */ AtomicOrderingCABI::relaxed,
  150.       /* relaxed   */ AtomicOrderingCABI::relaxed,
  151.       /* consume   */ AtomicOrderingCABI::consume,
  152.       /* acquire   */ AtomicOrderingCABI::acquire,
  153.       /* release   */ AtomicOrderingCABI::release,
  154.       /* acq_rel   */ AtomicOrderingCABI::acq_rel,
  155.       /* seq_cst   */ AtomicOrderingCABI::seq_cst,
  156.   };
  157.   return lookup[static_cast<size_t>(AO)];
  158. }
  159.  
  160. } // end namespace llvm
  161.  
  162. #endif // LLVM_SUPPORT_ATOMICORDERING_H
  163.