#ifndef LLVM_EXECUTIONENGINE_JITLINK_MEMORYFLAGS_H
#define LLVM_EXECUTIONENGINE_JITLINK_MEMORYFLAGS_H
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace jitlink {
enum class MemProt {
None = 0,
Read = 1U << 0,
Write = 1U << 1,
Exec = 1U << 2,
LLVM_MARK_AS_BITMASK_ENUM( Exec)
};
raw_ostream &operator<<(raw_ostream &OS, MemProt MP);
inline sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP) {
std::underlying_type_t<sys::Memory::ProtectionFlags> PF = 0;
if ((MP & MemProt::Read) != MemProt::None)
PF |= sys::Memory::MF_READ;
if ((MP & MemProt::Write) != MemProt::None)
PF |= sys::Memory::MF_WRITE;
if ((MP & MemProt::Exec) != MemProt::None)
PF |= sys::Memory::MF_EXEC;
return static_cast<sys::Memory::ProtectionFlags>(PF);
}
inline MemProt fromSysMemoryProtectionFlags(sys::Memory::ProtectionFlags PF) {
MemProt MP = MemProt::None;
if (PF & sys::Memory::MF_READ)
MP |= MemProt::Read;
if (PF & sys::Memory::MF_WRITE)
MP |= MemProt::Write;
if (PF & sys::Memory::MF_EXEC)
MP |= MemProt::None;
return MP;
}
enum class MemDeallocPolicy {
Standard,
Finalize
};
raw_ostream &operator<<(raw_ostream &OS, MemDeallocPolicy MDP);
class AllocGroup {
friend struct llvm::DenseMapInfo<AllocGroup>;
using underlying_type = uint8_t;
static constexpr unsigned BitsForProt = 3;
static constexpr unsigned BitsForDeallocPolicy = 1;
static constexpr unsigned MaxIdentifiers =
1U << (BitsForProt + BitsForDeallocPolicy);
public:
static constexpr unsigned NumGroups = MaxIdentifiers;
AllocGroup() = default;
AllocGroup(MemProt MP) : Id(static_cast<underlying_type>(MP)) {}
AllocGroup(MemProt MP, MemDeallocPolicy MDP)
: Id(static_cast<underlying_type>(MP) |
(static_cast<underlying_type>(MDP) << BitsForProt)) {}
MemProt getMemProt() const {
return static_cast<MemProt>(Id & ((1U << BitsForProt) - 1));
}
MemDeallocPolicy getMemDeallocPolicy() const {
return static_cast<MemDeallocPolicy>(Id >> BitsForProt);
}
friend bool operator==(const AllocGroup &LHS, const AllocGroup &RHS) {
return LHS.Id == RHS.Id;
}
friend bool operator!=(const AllocGroup &LHS, const AllocGroup &RHS) {
return !(LHS == RHS);
}
friend bool operator<(const AllocGroup &LHS, const AllocGroup &RHS) {
return LHS.Id < RHS.Id;
}
private:
AllocGroup(underlying_type RawId) : Id(RawId) {}
underlying_type Id = 0;
};
template <typename T> class AllocGroupSmallMap {
private:
using ElemT = std::pair<AllocGroup, T>;
using VectorTy = SmallVector<ElemT, 4>;
static bool compareKey(const ElemT &E, const AllocGroup &G) {
return E.first < G;
}
public:
using iterator = typename VectorTy::iterator;
AllocGroupSmallMap() = default;
AllocGroupSmallMap(std::initializer_list<std::pair<AllocGroup, T>> Inits)
: Elems(Inits) {
llvm::sort(Elems, llvm::less_first());
}
iterator begin() { return Elems.begin(); }
iterator end() { return Elems.end(); }
iterator find(AllocGroup G) {
auto I = lower_bound(Elems, G, compareKey);
return (I->first == G) ? I : end();
}
bool empty() const { return Elems.empty(); }
size_t size() const { return Elems.size(); }
T &operator[](AllocGroup G) {
auto I = lower_bound(Elems, G, compareKey);
if (I == Elems.end() || I->first != G)
I = Elems.insert(I, std::make_pair(G, T()));
return I->second;
}
private:
VectorTy Elems;
};
raw_ostream &operator<<(raw_ostream &OS, AllocGroup AG);
}
template <> struct DenseMapInfo<jitlink::MemProt> {
static inline jitlink::MemProt getEmptyKey() {
return jitlink::MemProt(~uint8_t(0));
}
static inline jitlink::MemProt getTombstoneKey() {
return jitlink::MemProt(~uint8_t(0) - 1);
}
static unsigned getHashValue(const jitlink::MemProt &Val) {
using UT = std::underlying_type_t<jitlink::MemProt>;
return DenseMapInfo<UT>::getHashValue(static_cast<UT>(Val));
}
static bool isEqual(const jitlink::MemProt &LHS,
const jitlink::MemProt &RHS) {
return LHS == RHS;
}
};
template <> struct DenseMapInfo<jitlink::AllocGroup> {
static inline jitlink::AllocGroup getEmptyKey() {
return jitlink::AllocGroup(~uint8_t(0));
}
static inline jitlink::AllocGroup getTombstoneKey() {
return jitlink::AllocGroup(~uint8_t(0) - 1);
}
static unsigned getHashValue(const jitlink::AllocGroup &Val) {
return DenseMapInfo<jitlink::AllocGroup::underlying_type>::getHashValue(
Val.Id);
}
static bool isEqual(const jitlink::AllocGroup &LHS,
const jitlink::AllocGroup &RHS) {
return LHS == RHS;
}
};
}
#endif