MemoryFlags.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-------- MemoryFlags.h - Memory allocation flags -----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Defines types and operations related to memory protection and allocation
  15. // lifetimes.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
  19. #define LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
  20. #include "llvm/ADT/BitmaskEnum.h"
  21. #include "llvm/ADT/DenseMapInfo.h"
  22. #include "llvm/ADT/STLExtras.h"
  23. #include "llvm/Support/Memory.h"
  24. #include "llvm/Support/raw_ostream.h"
  25. namespace llvm {
  26. namespace orc {
  27. /// Describes Read/Write/Exec permissions for memory.
  28. enum class MemProt {
  29. None = 0,
  30. Read = 1U << 0,
  31. Write = 1U << 1,
  32. Exec = 1U << 2,
  33. LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Exec)
  34. };
  35. /// Print a MemProt as an RWX triple.
  36. inline raw_ostream &operator<<(raw_ostream &OS, MemProt MP) {
  37. return OS << (((MP & MemProt::Read) != MemProt::None) ? 'R' : '-')
  38. << (((MP & MemProt::Write) != MemProt::None) ? 'W' : '-')
  39. << (((MP & MemProt::Exec) != MemProt::None) ? 'X' : '-');
  40. }
  41. /// Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags
  42. /// value.
  43. inline sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP) {
  44. std::underlying_type_t<sys::Memory::ProtectionFlags> PF = 0;
  45. if ((MP & MemProt::Read) != MemProt::None)
  46. PF |= sys::Memory::MF_READ;
  47. if ((MP & MemProt::Write) != MemProt::None)
  48. PF |= sys::Memory::MF_WRITE;
  49. if ((MP & MemProt::Exec) != MemProt::None)
  50. PF |= sys::Memory::MF_EXEC;
  51. return static_cast<sys::Memory::ProtectionFlags>(PF);
  52. }
  53. /// Convert a sys::Memory::ProtectionFlags value to a corresponding MemProt
  54. /// value.
  55. inline MemProt fromSysMemoryProtectionFlags(sys::Memory::ProtectionFlags PF) {
  56. MemProt MP = MemProt::None;
  57. if (PF & sys::Memory::MF_READ)
  58. MP |= MemProt::Read;
  59. if (PF & sys::Memory::MF_WRITE)
  60. MP |= MemProt::Write;
  61. if (PF & sys::Memory::MF_EXEC)
  62. MP |= MemProt::None;
  63. return MP;
  64. }
  65. /// Describes a memory deallocation policy for memory to be allocated by a
  66. /// JITLinkMemoryManager.
  67. ///
  68. /// All memory allocated by a call to JITLinkMemoryManager::allocate should be
  69. /// deallocated if a call is made to
  70. /// JITLinkMemoryManager::InFlightAllocation::abandon. The policies below apply
  71. /// to finalized allocations.
  72. enum class MemDeallocPolicy {
  73. /// Standard memory should be deallocated when the deallocate method is called
  74. /// for the finalized allocation.
  75. Standard,
  76. /// Finalize memory should be overwritten and then deallocated after all
  77. /// finalization functions have been run.
  78. Finalize
  79. };
  80. /// Print a MemDeallocPolicy.
  81. inline raw_ostream &operator<<(raw_ostream &OS, MemDeallocPolicy MDP) {
  82. return OS << (MDP == MemDeallocPolicy::Standard ? "standard" : "finalize");
  83. }
  84. /// A pair of memory protections and allocation policies.
  85. ///
  86. /// Optimized for use as a small map key.
  87. class AllocGroup {
  88. friend struct llvm::DenseMapInfo<AllocGroup>;
  89. using underlying_type = uint8_t;
  90. static constexpr unsigned BitsForProt = 3;
  91. static constexpr unsigned BitsForDeallocPolicy = 1;
  92. static constexpr unsigned MaxIdentifiers =
  93. 1U << (BitsForProt + BitsForDeallocPolicy);
  94. public:
  95. static constexpr unsigned NumGroups = MaxIdentifiers;
  96. /// Create a default AllocGroup. No memory protections, standard
  97. /// deallocation policy.
  98. AllocGroup() = default;
  99. /// Create an AllocGroup from a MemProt only -- uses
  100. /// MemoryDeallocationPolicy::Standard.
  101. AllocGroup(MemProt MP) : Id(static_cast<underlying_type>(MP)) {}
  102. /// Create an AllocGroup from a MemProt and a MemoryDeallocationPolicy.
  103. AllocGroup(MemProt MP, MemDeallocPolicy MDP)
  104. : Id(static_cast<underlying_type>(MP) |
  105. (static_cast<underlying_type>(MDP) << BitsForProt)) {}
  106. /// Returns the MemProt for this group.
  107. MemProt getMemProt() const {
  108. return static_cast<MemProt>(Id & ((1U << BitsForProt) - 1));
  109. }
  110. /// Returns the MemoryDeallocationPolicy for this group.
  111. MemDeallocPolicy getMemDeallocPolicy() const {
  112. return static_cast<MemDeallocPolicy>(Id >> BitsForProt);
  113. }
  114. friend bool operator==(const AllocGroup &LHS, const AllocGroup &RHS) {
  115. return LHS.Id == RHS.Id;
  116. }
  117. friend bool operator!=(const AllocGroup &LHS, const AllocGroup &RHS) {
  118. return !(LHS == RHS);
  119. }
  120. friend bool operator<(const AllocGroup &LHS, const AllocGroup &RHS) {
  121. return LHS.Id < RHS.Id;
  122. }
  123. private:
  124. AllocGroup(underlying_type RawId) : Id(RawId) {}
  125. underlying_type Id = 0;
  126. };
  127. /// A specialized small-map for AllocGroups.
  128. ///
  129. /// Iteration order is guaranteed to match key ordering.
  130. template <typename T> class AllocGroupSmallMap {
  131. private:
  132. using ElemT = std::pair<AllocGroup, T>;
  133. using VectorTy = SmallVector<ElemT, 4>;
  134. static bool compareKey(const ElemT &E, const AllocGroup &G) {
  135. return E.first < G;
  136. }
  137. public:
  138. using iterator = typename VectorTy::iterator;
  139. AllocGroupSmallMap() = default;
  140. AllocGroupSmallMap(std::initializer_list<std::pair<AllocGroup, T>> Inits)
  141. : Elems(Inits) {
  142. llvm::sort(Elems, llvm::less_first());
  143. }
  144. iterator begin() { return Elems.begin(); }
  145. iterator end() { return Elems.end(); }
  146. iterator find(AllocGroup G) {
  147. auto I = lower_bound(Elems, G, compareKey);
  148. return (I->first == G) ? I : end();
  149. }
  150. bool empty() const { return Elems.empty(); }
  151. size_t size() const { return Elems.size(); }
  152. T &operator[](AllocGroup G) {
  153. auto I = lower_bound(Elems, G, compareKey);
  154. if (I == Elems.end() || I->first != G)
  155. I = Elems.insert(I, std::make_pair(G, T()));
  156. return I->second;
  157. }
  158. private:
  159. VectorTy Elems;
  160. };
  161. /// Print an AllocGroup.
  162. inline raw_ostream &operator<<(raw_ostream &OS, AllocGroup AG) {
  163. return OS << '(' << AG.getMemProt() << ", " << AG.getMemDeallocPolicy()
  164. << ')';
  165. }
  166. } // end namespace orc
  167. template <> struct DenseMapInfo<orc::MemProt> {
  168. static inline orc::MemProt getEmptyKey() { return orc::MemProt(~uint8_t(0)); }
  169. static inline orc::MemProt getTombstoneKey() {
  170. return orc::MemProt(~uint8_t(0) - 1);
  171. }
  172. static unsigned getHashValue(const orc::MemProt &Val) {
  173. using UT = std::underlying_type_t<orc::MemProt>;
  174. return DenseMapInfo<UT>::getHashValue(static_cast<UT>(Val));
  175. }
  176. static bool isEqual(const orc::MemProt &LHS, const orc::MemProt &RHS) {
  177. return LHS == RHS;
  178. }
  179. };
  180. template <> struct DenseMapInfo<orc::AllocGroup> {
  181. static inline orc::AllocGroup getEmptyKey() {
  182. return orc::AllocGroup(~uint8_t(0));
  183. }
  184. static inline orc::AllocGroup getTombstoneKey() {
  185. return orc::AllocGroup(~uint8_t(0) - 1);
  186. }
  187. static unsigned getHashValue(const orc::AllocGroup &Val) {
  188. return DenseMapInfo<orc::AllocGroup::underlying_type>::getHashValue(Val.Id);
  189. }
  190. static bool isEqual(const orc::AllocGroup &LHS, const orc::AllocGroup &RHS) {
  191. return LHS == RHS;
  192. }
  193. };
  194. } // end namespace llvm
  195. #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_MEMORYFLAGS_H
  196. #ifdef __GNUC__
  197. #pragma GCC diagnostic pop
  198. #endif