diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:41:05 +0000 |
| commit | 01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch) | |
| tree | 4def12e759965de927d963ac65840d663ef9d1ea /include/llvm/Support/AtomicOrdering.h | |
| parent | f0f4822ed4b66e3579e92a89f368f8fb860e218e (diff) | |
Diffstat (limited to 'include/llvm/Support/AtomicOrdering.h')
| -rw-r--r-- | include/llvm/Support/AtomicOrdering.h | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/include/llvm/Support/AtomicOrdering.h b/include/llvm/Support/AtomicOrdering.h new file mode 100644 index 0000000000000..8837fab195757 --- /dev/null +++ b/include/llvm/Support/AtomicOrdering.h @@ -0,0 +1,153 @@ +//===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Atomic ordering constants. +/// +/// These values are used by LLVM to represent atomic ordering for C++11's +/// memory model and more, as detailed in docs/Atomics.rst. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ATOMICORDERING_H +#define LLVM_SUPPORT_ATOMICORDERING_H + +#include <cstddef> + +namespace llvm { + +/// Atomic ordering for C11 / C++11's memody models. +/// +/// These values cannot change because they are shared with standard library +/// implementations as well as with other compilers. +enum class AtomicOrderingCABI { + relaxed = 0, + consume = 1, + acquire = 2, + release = 3, + acq_rel = 4, + seq_cst = 5, +}; + +bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; + +// Validate an integral value which isn't known to fit within the enum's range +// is a valid AtomicOrderingCABI. +template <typename Int> static inline bool isValidAtomicOrderingCABI(Int I) { + return (Int)AtomicOrderingCABI::relaxed <= I && + I <= (Int)AtomicOrderingCABI::seq_cst; +} + +/// Atomic ordering for LLVM's memory model. +/// +/// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and +/// Unordered, which are both below the C++ orders. +/// +/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst +/// \-->consume-->acquire--/ +enum class AtomicOrdering { + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, // Equivalent to C++'s relaxed. + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7 +}; + +bool operator<(AtomicOrdering, AtomicOrdering) = delete; +bool operator>(AtomicOrdering, AtomicOrdering) = delete; +bool operator<=(AtomicOrdering, AtomicOrdering) = delete; +bool operator>=(AtomicOrdering, AtomicOrdering) = delete; + +// Validate an integral value which isn't known to fit within the enum's range +// is a valid AtomicOrdering. +template <typename Int> static inline bool isValidAtomicOrdering(Int I) { + return (Int)AtomicOrdering::NotAtomic <= I && + I <= (Int)AtomicOrdering::SequentiallyConsistent; +} + +/// String used by LLVM IR to represent atomic ordering. +static inline const char *toIRString(AtomicOrdering ao) { + static const char *names[8] = {"not_atomic", "unordered", "monotonic", + "consume", "acquire", "release", + "acq_rel", "seq_cst"}; + return names[(size_t)ao]; +} + +/// Returns true if ao is stronger than other as defined by the AtomicOrdering +/// lattice, which is based on C++'s definition. +static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) { + static const bool lookup[8][8] = { + // NA UN RX CO AC RE AR SC + /* NotAtomic */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0}, + /* relaxed */ {1, 1, 0, 0, 0, 0, 0, 0}, + /* consume */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* acquire */ {1, 1, 1, 1, 0, 0, 0, 0}, + /* release */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* acq_rel */ {1, 1, 1, 1, 1, 1, 0, 0}, + /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 0}, + }; + return lookup[(size_t)ao][(size_t)other]; +} + +static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao, + AtomicOrdering other) { + static const bool lookup[8][8] = { + // NA UN RX CO AC RE AR SC + /* NotAtomic */ {1, 0, 0, 0, 0, 0, 0, 0}, + /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0}, + /* relaxed */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* consume */ {1, 1, 1, 1, 0, 0, 0, 0}, + /* acquire */ {1, 1, 1, 1, 1, 0, 0, 0}, + /* release */ {1, 1, 1, 0, 0, 1, 0, 0}, + /* acq_rel */ {1, 1, 1, 1, 1, 1, 1, 0}, + /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 1}, + }; + return lookup[(size_t)ao][(size_t)other]; +} + +static inline bool isStrongerThanUnordered(AtomicOrdering ao) { + return isStrongerThan(ao, AtomicOrdering::Unordered); +} + +static inline bool isStrongerThanMonotonic(AtomicOrdering ao) { + return isStrongerThan(ao, AtomicOrdering::Monotonic); +} + +static inline bool isAcquireOrStronger(AtomicOrdering ao) { + return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire); +} + +static inline bool isReleaseOrStronger(AtomicOrdering ao) { + return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release); +} + +static inline AtomicOrderingCABI toCABI(AtomicOrdering ao) { + static const AtomicOrderingCABI lookup[8] = { + /* NotAtomic */ AtomicOrderingCABI::relaxed, + /* Unordered */ AtomicOrderingCABI::relaxed, + /* relaxed */ AtomicOrderingCABI::relaxed, + /* consume */ AtomicOrderingCABI::consume, + /* acquire */ AtomicOrderingCABI::acquire, + /* release */ AtomicOrderingCABI::release, + /* acq_rel */ AtomicOrderingCABI::acq_rel, + /* seq_cst */ AtomicOrderingCABI::seq_cst, + }; + return lookup[(size_t)ao]; +} + +} // end namespace llvm + +#endif // LLVM_SUPPORT_ATOMICORDERING_H |
