153 lines
6.0 KiB
C
153 lines
6.0 KiB
C
|
//===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
///
|
||
|
/// \file
|
||
|
/// 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 memory 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> 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 : unsigned {
|
||
|
NotAtomic = 0,
|
||
|
Unordered = 1,
|
||
|
Monotonic = 2, // Equivalent to C++'s relaxed.
|
||
|
// Consume = 3, // Not specified yet.
|
||
|
Acquire = 4,
|
||
|
Release = 5,
|
||
|
AcquireRelease = 6,
|
||
|
SequentiallyConsistent = 7,
|
||
|
LAST = SequentiallyConsistent
|
||
|
};
|
||
|
|
||
|
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> inline bool isValidAtomicOrdering(Int I) {
|
||
|
return static_cast<Int>(AtomicOrdering::NotAtomic) <= I &&
|
||
|
I <= static_cast<Int>(AtomicOrdering::SequentiallyConsistent);
|
||
|
}
|
||
|
|
||
|
/// String used by LLVM IR to represent atomic ordering.
|
||
|
inline const char *toIRString(AtomicOrdering ao) {
|
||
|
static const char *names[8] = {"not_atomic", "unordered", "monotonic",
|
||
|
"consume", "acquire", "release",
|
||
|
"acq_rel", "seq_cst"};
|
||
|
return names[static_cast<size_t>(ao)];
|
||
|
}
|
||
|
|
||
|
/// Returns true if ao is stronger than other as defined by the AtomicOrdering
|
||
|
/// lattice, which is based on C++'s definition.
|
||
|
inline bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
|
||
|
static const bool lookup[8][8] = {
|
||
|
// NA UN RX CO AC RE AR SC
|
||
|
/* NotAtomic */ {false, false, false, false, false, false, false, false},
|
||
|
/* Unordered */ { true, false, false, false, false, false, false, false},
|
||
|
/* relaxed */ { true, true, false, false, false, false, false, false},
|
||
|
/* consume */ { true, true, true, false, false, false, false, false},
|
||
|
/* acquire */ { true, true, true, true, false, false, false, false},
|
||
|
/* release */ { true, true, true, false, false, false, false, false},
|
||
|
/* acq_rel */ { true, true, true, true, true, true, false, false},
|
||
|
/* seq_cst */ { true, true, true, true, true, true, true, false},
|
||
|
};
|
||
|
return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
|
||
|
}
|
||
|
|
||
|
inline bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
|
||
|
static const bool lookup[8][8] = {
|
||
|
// NA UN RX CO AC RE AR SC
|
||
|
/* NotAtomic */ { true, false, false, false, false, false, false, false},
|
||
|
/* Unordered */ { true, true, false, false, false, false, false, false},
|
||
|
/* relaxed */ { true, true, true, false, false, false, false, false},
|
||
|
/* consume */ { true, true, true, true, false, false, false, false},
|
||
|
/* acquire */ { true, true, true, true, true, false, false, false},
|
||
|
/* release */ { true, true, true, false, false, true, false, false},
|
||
|
/* acq_rel */ { true, true, true, true, true, true, true, false},
|
||
|
/* seq_cst */ { true, true, true, true, true, true, true, true},
|
||
|
};
|
||
|
return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
|
||
|
}
|
||
|
|
||
|
inline bool isStrongerThanUnordered(AtomicOrdering AO) {
|
||
|
return isStrongerThan(AO, AtomicOrdering::Unordered);
|
||
|
}
|
||
|
|
||
|
inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
|
||
|
return isStrongerThan(AO, AtomicOrdering::Monotonic);
|
||
|
}
|
||
|
|
||
|
inline bool isAcquireOrStronger(AtomicOrdering AO) {
|
||
|
return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire);
|
||
|
}
|
||
|
|
||
|
inline bool isReleaseOrStronger(AtomicOrdering AO) {
|
||
|
return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release);
|
||
|
}
|
||
|
|
||
|
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[static_cast<size_t>(AO)];
|
||
|
}
|
||
|
|
||
|
} // end namespace llvm
|
||
|
|
||
|
#endif // LLVM_SUPPORT_ATOMICORDERING_H
|