123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===-------- MemoryFlags.h - Memory allocation flags -----------*- 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
- //
- //===----------------------------------------------------------------------===//
- //
- // Defines types and operations related to memory protection and allocation
- // lifetimes.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
- #define LLVM_EXECUTIONENGINE_ORC_SHARED_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 orc {
- /// Describes Read/Write/Exec permissions for memory.
- enum class MemProt {
- None = 0,
- Read = 1U << 0,
- Write = 1U << 1,
- Exec = 1U << 2,
- LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Exec)
- };
- /// Print a MemProt as an RWX triple.
- inline raw_ostream &operator<<(raw_ostream &OS, MemProt MP) {
- return OS << (((MP & MemProt::Read) != MemProt::None) ? 'R' : '-')
- << (((MP & MemProt::Write) != MemProt::None) ? 'W' : '-')
- << (((MP & MemProt::Exec) != MemProt::None) ? 'X' : '-');
- }
- /// Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags
- /// value.
- 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);
- }
- /// Convert a sys::Memory::ProtectionFlags value to a corresponding MemProt
- /// value.
- 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;
- }
- /// Describes a memory deallocation policy for memory to be allocated by a
- /// JITLinkMemoryManager.
- ///
- /// All memory allocated by a call to JITLinkMemoryManager::allocate should be
- /// deallocated if a call is made to
- /// JITLinkMemoryManager::InFlightAllocation::abandon. The policies below apply
- /// to finalized allocations.
- enum class MemDeallocPolicy {
- /// Standard memory should be deallocated when the deallocate method is called
- /// for the finalized allocation.
- Standard,
- /// Finalize memory should be overwritten and then deallocated after all
- /// finalization functions have been run.
- Finalize
- };
- /// Print a MemDeallocPolicy.
- inline raw_ostream &operator<<(raw_ostream &OS, MemDeallocPolicy MDP) {
- return OS << (MDP == MemDeallocPolicy::Standard ? "standard" : "finalize");
- }
- /// A pair of memory protections and allocation policies.
- ///
- /// Optimized for use as a small map key.
- 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;
- /// Create a default AllocGroup. No memory protections, standard
- /// deallocation policy.
- AllocGroup() = default;
- /// Create an AllocGroup from a MemProt only -- uses
- /// MemoryDeallocationPolicy::Standard.
- AllocGroup(MemProt MP) : Id(static_cast<underlying_type>(MP)) {}
- /// Create an AllocGroup from a MemProt and a MemoryDeallocationPolicy.
- AllocGroup(MemProt MP, MemDeallocPolicy MDP)
- : Id(static_cast<underlying_type>(MP) |
- (static_cast<underlying_type>(MDP) << BitsForProt)) {}
- /// Returns the MemProt for this group.
- MemProt getMemProt() const {
- return static_cast<MemProt>(Id & ((1U << BitsForProt) - 1));
- }
- /// Returns the MemoryDeallocationPolicy for this group.
- 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;
- };
- /// A specialized small-map for AllocGroups.
- ///
- /// Iteration order is guaranteed to match key ordering.
- 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;
- };
- /// Print an AllocGroup.
- inline raw_ostream &operator<<(raw_ostream &OS, AllocGroup AG) {
- return OS << '(' << AG.getMemProt() << ", " << AG.getMemDeallocPolicy()
- << ')';
- }
- } // end namespace orc
- template <> struct DenseMapInfo<orc::MemProt> {
- static inline orc::MemProt getEmptyKey() { return orc::MemProt(~uint8_t(0)); }
- static inline orc::MemProt getTombstoneKey() {
- return orc::MemProt(~uint8_t(0) - 1);
- }
- static unsigned getHashValue(const orc::MemProt &Val) {
- using UT = std::underlying_type_t<orc::MemProt>;
- return DenseMapInfo<UT>::getHashValue(static_cast<UT>(Val));
- }
- static bool isEqual(const orc::MemProt &LHS, const orc::MemProt &RHS) {
- return LHS == RHS;
- }
- };
- template <> struct DenseMapInfo<orc::AllocGroup> {
- static inline orc::AllocGroup getEmptyKey() {
- return orc::AllocGroup(~uint8_t(0));
- }
- static inline orc::AllocGroup getTombstoneKey() {
- return orc::AllocGroup(~uint8_t(0) - 1);
- }
- static unsigned getHashValue(const orc::AllocGroup &Val) {
- return DenseMapInfo<orc::AllocGroup::underlying_type>::getHashValue(Val.Id);
- }
- static bool isEqual(const orc::AllocGroup &LHS, const orc::AllocGroup &RHS) {
- return LHS == RHS;
- }
- };
- } // end namespace llvm
- #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|