MemoryFlags.h 7.1 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_JITLINK_MEMORYFLAGS_H
  19. #define LLVM_EXECUTIONENGINE_JITLINK_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 jitlink {
  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. raw_ostream &operator<<(raw_ostream &OS, MemProt MP);
  37. /// Convert a MemProt value to a corresponding sys::Memory::ProtectionFlags
  38. /// value.
  39. inline sys::Memory::ProtectionFlags toSysMemoryProtectionFlags(MemProt MP) {
  40. std::underlying_type_t<sys::Memory::ProtectionFlags> PF = 0;
  41. if ((MP & MemProt::Read) != MemProt::None)
  42. PF |= sys::Memory::MF_READ;
  43. if ((MP & MemProt::Write) != MemProt::None)
  44. PF |= sys::Memory::MF_WRITE;
  45. if ((MP & MemProt::Exec) != MemProt::None)
  46. PF |= sys::Memory::MF_EXEC;
  47. return static_cast<sys::Memory::ProtectionFlags>(PF);
  48. }
  49. /// Convert a sys::Memory::ProtectionFlags value to a corresponding MemProt
  50. /// value.
  51. inline MemProt fromSysMemoryProtectionFlags(sys::Memory::ProtectionFlags PF) {
  52. MemProt MP = MemProt::None;
  53. if (PF & sys::Memory::MF_READ)
  54. MP |= MemProt::Read;
  55. if (PF & sys::Memory::MF_WRITE)
  56. MP |= MemProt::Write;
  57. if (PF & sys::Memory::MF_EXEC)
  58. MP |= MemProt::None;
  59. return MP;
  60. }
  61. /// Describes a memory deallocation policy for memory to be allocated by a
  62. /// JITLinkMemoryManager.
  63. ///
  64. /// All memory allocated by a call to JITLinkMemoryManager::allocate should be
  65. /// deallocated if a call is made to
  66. /// JITLinkMemoryManager::InFlightAllocation::abandon. The policies below apply
  67. /// to finalized allocations.
  68. enum class MemDeallocPolicy {
  69. /// Standard memory should be deallocated when the deallocate method is called
  70. /// for the finalized allocation.
  71. Standard,
  72. /// Finalize memory should be overwritten and then deallocated after all
  73. /// finalization functions have been run.
  74. Finalize
  75. };
  76. /// Print a MemDeallocPolicy.
  77. raw_ostream &operator<<(raw_ostream &OS, MemDeallocPolicy MDP);
  78. /// A pair of memory protections and allocation policies.
  79. ///
  80. /// Optimized for use as a small map key.
  81. class AllocGroup {
  82. friend struct llvm::DenseMapInfo<AllocGroup>;
  83. using underlying_type = uint8_t;
  84. static constexpr unsigned BitsForProt = 3;
  85. static constexpr unsigned BitsForDeallocPolicy = 1;
  86. static constexpr unsigned MaxIdentifiers =
  87. 1U << (BitsForProt + BitsForDeallocPolicy);
  88. public:
  89. static constexpr unsigned NumGroups = MaxIdentifiers;
  90. /// Create a default AllocGroup. No memory protections, standard
  91. /// deallocation policy.
  92. AllocGroup() = default;
  93. /// Create an AllocGroup from a MemProt only -- uses
  94. /// MemoryDeallocationPolicy::Standard.
  95. AllocGroup(MemProt MP) : Id(static_cast<underlying_type>(MP)) {}
  96. /// Create an AllocGroup from a MemProt and a MemoryDeallocationPolicy.
  97. AllocGroup(MemProt MP, MemDeallocPolicy MDP)
  98. : Id(static_cast<underlying_type>(MP) |
  99. (static_cast<underlying_type>(MDP) << BitsForProt)) {}
  100. /// Returns the MemProt for this group.
  101. MemProt getMemProt() const {
  102. return static_cast<MemProt>(Id & ((1U << BitsForProt) - 1));
  103. }
  104. /// Returns the MemoryDeallocationPolicy for this group.
  105. MemDeallocPolicy getMemDeallocPolicy() const {
  106. return static_cast<MemDeallocPolicy>(Id >> BitsForProt);
  107. }
  108. friend bool operator==(const AllocGroup &LHS, const AllocGroup &RHS) {
  109. return LHS.Id == RHS.Id;
  110. }
  111. friend bool operator!=(const AllocGroup &LHS, const AllocGroup &RHS) {
  112. return !(LHS == RHS);
  113. }
  114. friend bool operator<(const AllocGroup &LHS, const AllocGroup &RHS) {
  115. return LHS.Id < RHS.Id;
  116. }
  117. private:
  118. AllocGroup(underlying_type RawId) : Id(RawId) {}
  119. underlying_type Id = 0;
  120. };
  121. /// A specialized small-map for AllocGroups.
  122. ///
  123. /// Iteration order is guaranteed to match key ordering.
  124. template <typename T> class AllocGroupSmallMap {
  125. private:
  126. using ElemT = std::pair<AllocGroup, T>;
  127. using VectorTy = SmallVector<ElemT, 4>;
  128. static bool compareKey(const ElemT &E, const AllocGroup &G) {
  129. return E.first < G;
  130. }
  131. public:
  132. using iterator = typename VectorTy::iterator;
  133. AllocGroupSmallMap() = default;
  134. AllocGroupSmallMap(std::initializer_list<std::pair<AllocGroup, T>> Inits) {
  135. Elems.reserve(Inits.size());
  136. for (const auto &E : Inits)
  137. Elems.push_back(E);
  138. llvm::sort(Elems, [](const ElemT &LHS, const ElemT &RHS) {
  139. return LHS.first < RHS.first;
  140. });
  141. }
  142. iterator begin() { return Elems.begin(); }
  143. iterator end() { return Elems.end(); }
  144. iterator find(AllocGroup G) {
  145. auto I = lower_bound(Elems, G, compareKey);
  146. return (I->first == G) ? I : end();
  147. }
  148. bool empty() const { return Elems.empty(); }
  149. size_t size() const { return Elems.size(); }
  150. T &operator[](AllocGroup G) {
  151. auto I = lower_bound(Elems, G, compareKey);
  152. if (I == Elems.end() || I->first != G)
  153. I = Elems.insert(I, std::make_pair(G, T()));
  154. return I->second;
  155. }
  156. private:
  157. VectorTy Elems;
  158. };
  159. /// Print an AllocGroup.
  160. raw_ostream &operator<<(raw_ostream &OS, AllocGroup AG);
  161. } // end namespace jitlink
  162. template <> struct DenseMapInfo<jitlink::MemProt> {
  163. static inline jitlink::MemProt getEmptyKey() {
  164. return jitlink::MemProt(~uint8_t(0));
  165. }
  166. static inline jitlink::MemProt getTombstoneKey() {
  167. return jitlink::MemProt(~uint8_t(0) - 1);
  168. }
  169. static unsigned getHashValue(const jitlink::MemProt &Val) {
  170. using UT = std::underlying_type_t<jitlink::MemProt>;
  171. return DenseMapInfo<UT>::getHashValue(static_cast<UT>(Val));
  172. }
  173. static bool isEqual(const jitlink::MemProt &LHS,
  174. const jitlink::MemProt &RHS) {
  175. return LHS == RHS;
  176. }
  177. };
  178. template <> struct DenseMapInfo<jitlink::AllocGroup> {
  179. static inline jitlink::AllocGroup getEmptyKey() {
  180. return jitlink::AllocGroup(~uint8_t(0));
  181. }
  182. static inline jitlink::AllocGroup getTombstoneKey() {
  183. return jitlink::AllocGroup(~uint8_t(0) - 1);
  184. }
  185. static unsigned getHashValue(const jitlink::AllocGroup &Val) {
  186. return DenseMapInfo<jitlink::AllocGroup::underlying_type>::getHashValue(
  187. Val.Id);
  188. }
  189. static bool isEqual(const jitlink::AllocGroup &LHS,
  190. const jitlink::AllocGroup &RHS) {
  191. return LHS == RHS;
  192. }
  193. };
  194. } // end namespace llvm
  195. #endif // LLVM_EXECUTIONENGINE_JITLINK_MEMORYFLAGS_H
  196. #ifdef __GNUC__
  197. #pragma GCC diagnostic pop
  198. #endif