Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:51

0001 //===-------- MemoryFlags.h - Memory allocation flags -----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Defines types and operations related to memory protection and allocation
0010 // lifetimes.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
0015 #define LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
0016 
0017 #include "llvm/ADT/BitmaskEnum.h"
0018 #include "llvm/ADT/DenseMapInfo.h"
0019 #include "llvm/ADT/STLExtras.h"
0020 #include "llvm/Support/Memory.h"
0021 #include "llvm/Support/raw_ostream.h"
0022 
0023 namespace llvm {
0024 namespace orc {
0025 
0026 /// Describes Read/Write/Exec permissions for memory.
0027 enum class MemProt {
0028   None = 0,
0029   Read = 1U << 0,
0030   Write = 1U << 1,
0031   Exec = 1U << 2,
0032   LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Exec)
0033 };
0034 
0035 /// Print a MemProt as an RWX triple.
0036 inline raw_ostream &operator<<(raw_ostream &OS, MemProt MP) {
0037   return OS << (((MP & MemProt::Read) != MemProt::None) ? 'R' : '-')
0038             << (((MP & MemProt::Write) != MemProt::None) ? 'W' : '-')
0039             << (((MP & MemProt::Exec) != MemProt::None) ? 'X' : '-');
0040 }
0041 
0042 /// Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags
0043 /// value.
0044 inline sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP) {
0045   std::underlying_type_t<sys::Memory::ProtectionFlags> PF = 0;
0046   if ((MP & MemProt::Read) != MemProt::None)
0047     PF |= sys::Memory::MF_READ;
0048   if ((MP & MemProt::Write) != MemProt::None)
0049     PF |= sys::Memory::MF_WRITE;
0050   if ((MP & MemProt::Exec) != MemProt::None)
0051     PF |= sys::Memory::MF_EXEC;
0052   return static_cast<sys::Memory::ProtectionFlags>(PF);
0053 }
0054 
0055 /// Convert a sys::Memory::ProtectionFlags value to a corresponding MemProt
0056 /// value.
0057 inline MemProt fromSysMemoryProtectionFlags(sys::Memory::ProtectionFlags PF) {
0058   MemProt MP = MemProt::None;
0059   if (PF & sys::Memory::MF_READ)
0060     MP |= MemProt::Read;
0061   if (PF & sys::Memory::MF_WRITE)
0062     MP |= MemProt::Write;
0063   if (PF & sys::Memory::MF_EXEC)
0064     MP |= MemProt::None;
0065   return MP;
0066 }
0067 
0068 /// Describes a memory lifetime policy for memory to be allocated by a
0069 /// JITLinkMemoryManager.
0070 ///
0071 /// All memory allocated by a call to JITLinkMemoryManager::allocate should be
0072 /// deallocated if a call is made to
0073 /// JITLinkMemoryManager::InFlightAllocation::abandon. The policies below apply
0074 /// to finalized allocations.
0075 enum class MemLifetime {
0076   /// Standard memory should be allocated by the allocator and then deallocated
0077   /// when the deallocate method is called for the finalized allocation.
0078   Standard,
0079 
0080   /// Finalize memory should be allocated by the allocator, and then be
0081   /// overwritten and deallocated after all finalization functions have been
0082   /// run.
0083   Finalize,
0084 
0085   /// NoAlloc memory should not be allocated by the JITLinkMemoryManager at
0086   /// all. It is used for sections that don't need to be transferred to the
0087   /// executor process, typically metadata sections.
0088   NoAlloc
0089 };
0090 
0091 /// Print a MemDeallocPolicy.
0092 inline raw_ostream &operator<<(raw_ostream &OS, MemLifetime MLP) {
0093   switch (MLP) {
0094   case MemLifetime::Standard:
0095     OS << "standard";
0096     break;
0097   case MemLifetime::Finalize:
0098     OS << "finalize";
0099     break;
0100   case MemLifetime::NoAlloc:
0101     OS << "noalloc";
0102     break;
0103   }
0104   return OS;
0105 }
0106 
0107 /// A pair of memory protections and allocation policies.
0108 ///
0109 /// Optimized for use as a small map key.
0110 class AllocGroup {
0111   friend struct llvm::DenseMapInfo<AllocGroup>;
0112 
0113   using underlying_type = uint8_t;
0114   static constexpr unsigned BitsForProt = 3;
0115   static constexpr unsigned BitsForLifetimePolicy = 2;
0116   static constexpr unsigned MaxIdentifiers =
0117       1U << (BitsForProt + BitsForLifetimePolicy);
0118 
0119 public:
0120   static constexpr unsigned NumGroups = MaxIdentifiers;
0121 
0122   /// Create a default AllocGroup. No memory protections, standard
0123   /// lifetime policy.
0124   AllocGroup() = default;
0125 
0126   /// Create an AllocGroup from a MemProt only -- uses
0127   /// MemLifetime::Standard.
0128   AllocGroup(MemProt MP) : Id(static_cast<underlying_type>(MP)) {}
0129 
0130   /// Create an AllocGroup from a MemProt and a MemLifetime.
0131   AllocGroup(MemProt MP, MemLifetime MLP)
0132       : Id(static_cast<underlying_type>(MP) |
0133            (static_cast<underlying_type>(MLP) << BitsForProt)) {}
0134 
0135   /// Returns the MemProt for this group.
0136   MemProt getMemProt() const {
0137     return static_cast<MemProt>(Id & ((1U << BitsForProt) - 1));
0138   }
0139 
0140   /// Returns the MemLifetime for this group.
0141   MemLifetime getMemLifetime() const {
0142     return static_cast<MemLifetime>(Id >> BitsForProt);
0143   }
0144 
0145   friend bool operator==(const AllocGroup &LHS, const AllocGroup &RHS) {
0146     return LHS.Id == RHS.Id;
0147   }
0148 
0149   friend bool operator!=(const AllocGroup &LHS, const AllocGroup &RHS) {
0150     return !(LHS == RHS);
0151   }
0152 
0153   friend bool operator<(const AllocGroup &LHS, const AllocGroup &RHS) {
0154     return LHS.Id < RHS.Id;
0155   }
0156 
0157 private:
0158   AllocGroup(underlying_type RawId) : Id(RawId) {}
0159   underlying_type Id = 0;
0160 };
0161 
0162 /// A specialized small-map for AllocGroups.
0163 ///
0164 /// Iteration order is guaranteed to match key ordering.
0165 template <typename T> class AllocGroupSmallMap {
0166 private:
0167   using ElemT = std::pair<AllocGroup, T>;
0168   using VectorTy = SmallVector<ElemT, 4>;
0169 
0170   static bool compareKey(const ElemT &E, const AllocGroup &G) {
0171     return E.first < G;
0172   }
0173 
0174 public:
0175   using iterator = typename VectorTy::iterator;
0176 
0177   AllocGroupSmallMap() = default;
0178   AllocGroupSmallMap(std::initializer_list<std::pair<AllocGroup, T>> Inits)
0179       : Elems(Inits) {
0180     llvm::sort(Elems, llvm::less_first());
0181   }
0182 
0183   iterator begin() { return Elems.begin(); }
0184   iterator end() { return Elems.end(); }
0185   iterator find(AllocGroup G) {
0186     auto I = lower_bound(Elems, G, compareKey);
0187     return (I == end() || I->first == G) ? I : end();
0188   }
0189 
0190   bool empty() const { return Elems.empty(); }
0191   size_t size() const { return Elems.size(); }
0192 
0193   T &operator[](AllocGroup G) {
0194     auto I = lower_bound(Elems, G, compareKey);
0195     if (I == Elems.end() || I->first != G)
0196       I = Elems.insert(I, std::make_pair(G, T()));
0197     return I->second;
0198   }
0199 
0200 private:
0201   VectorTy Elems;
0202 };
0203 
0204 /// Print an AllocGroup.
0205 inline raw_ostream &operator<<(raw_ostream &OS, AllocGroup AG) {
0206   return OS << '(' << AG.getMemProt() << ", " << AG.getMemLifetime() << ')';
0207 }
0208 
0209 } // end namespace orc
0210 
0211 template <> struct DenseMapInfo<orc::MemProt> {
0212   static inline orc::MemProt getEmptyKey() { return orc::MemProt(~uint8_t(0)); }
0213   static inline orc::MemProt getTombstoneKey() {
0214     return orc::MemProt(~uint8_t(0) - 1);
0215   }
0216   static unsigned getHashValue(const orc::MemProt &Val) {
0217     using UT = std::underlying_type_t<orc::MemProt>;
0218     return DenseMapInfo<UT>::getHashValue(static_cast<UT>(Val));
0219   }
0220   static bool isEqual(const orc::MemProt &LHS, const orc::MemProt &RHS) {
0221     return LHS == RHS;
0222   }
0223 };
0224 
0225 template <> struct DenseMapInfo<orc::AllocGroup> {
0226   static inline orc::AllocGroup getEmptyKey() {
0227     return orc::AllocGroup(~uint8_t(0));
0228   }
0229   static inline orc::AllocGroup getTombstoneKey() {
0230     return orc::AllocGroup(~uint8_t(0) - 1);
0231   }
0232   static unsigned getHashValue(const orc::AllocGroup &Val) {
0233     return DenseMapInfo<orc::AllocGroup::underlying_type>::getHashValue(Val.Id);
0234   }
0235   static bool isEqual(const orc::AllocGroup &LHS, const orc::AllocGroup &RHS) {
0236     return LHS == RHS;
0237   }
0238 };
0239 
0240 } // end namespace llvm
0241 
0242 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H