Memory.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Support/Memory.h - Memory Support -------------------*- 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. // This file declares the llvm::sys::Memory class.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_SUPPORT_MEMORY_H
  18. #define LLVM_SUPPORT_MEMORY_H
  19. #include "llvm/Support/DataTypes.h"
  20. #include <system_error>
  21. namespace llvm {
  22. // Forward declare raw_ostream: it is used for debug dumping below.
  23. class raw_ostream;
  24. namespace sys {
  25. /// This class encapsulates the notion of a memory block which has an address
  26. /// and a size. It is used by the Memory class (a friend) as the result of
  27. /// various memory allocation operations.
  28. /// @see Memory
  29. /// Memory block abstraction.
  30. class MemoryBlock {
  31. public:
  32. MemoryBlock() : Address(nullptr), AllocatedSize(0) {}
  33. MemoryBlock(void *addr, size_t allocatedSize)
  34. : Address(addr), AllocatedSize(allocatedSize) {}
  35. void *base() const { return Address; }
  36. /// The size as it was allocated. This is always greater or equal to the
  37. /// size that was originally requested.
  38. size_t allocatedSize() const { return AllocatedSize; }
  39. private:
  40. void *Address; ///< Address of first byte of memory area
  41. size_t AllocatedSize; ///< Size, in bytes of the memory area
  42. unsigned Flags = 0;
  43. friend class Memory;
  44. };
  45. /// This class provides various memory handling functions that manipulate
  46. /// MemoryBlock instances.
  47. /// @since 1.4
  48. /// An abstraction for memory operations.
  49. class Memory {
  50. public:
  51. enum ProtectionFlags {
  52. MF_READ = 0x1000000,
  53. MF_WRITE = 0x2000000,
  54. MF_EXEC = 0x4000000,
  55. MF_RWE_MASK = 0x7000000,
  56. /// The \p MF_HUGE_HINT flag is used to indicate that the request for
  57. /// a memory block should be satisfied with large pages if possible.
  58. /// This is only a hint and small pages will be used as fallback.
  59. ///
  60. /// The presence or absence of this flag in the returned memory block
  61. /// is (at least currently) *not* a reliable indicator that the memory
  62. /// block will use or will not use large pages. On some systems a request
  63. /// without this flag can be backed by large pages without this flag being
  64. /// set, and on some other systems a request with this flag can fallback
  65. /// to small pages without this flag being cleared.
  66. MF_HUGE_HINT = 0x0000001
  67. };
  68. /// This method allocates a block of memory that is suitable for loading
  69. /// dynamically generated code (e.g. JIT). An attempt to allocate
  70. /// \p NumBytes bytes of virtual memory is made.
  71. /// \p NearBlock may point to an existing allocation in which case
  72. /// an attempt is made to allocate more memory near the existing block.
  73. /// The actual allocated address is not guaranteed to be near the requested
  74. /// address.
  75. /// \p Flags is used to set the initial protection flags for the block
  76. /// of the memory.
  77. /// \p EC [out] returns an object describing any error that occurs.
  78. ///
  79. /// This method may allocate more than the number of bytes requested. The
  80. /// actual number of bytes allocated is indicated in the returned
  81. /// MemoryBlock.
  82. ///
  83. /// The start of the allocated block must be aligned with the
  84. /// system allocation granularity (64K on Windows, page size on Linux).
  85. /// If the address following \p NearBlock is not so aligned, it will be
  86. /// rounded up to the next allocation granularity boundary.
  87. ///
  88. /// \r a non-null MemoryBlock if the function was successful,
  89. /// otherwise a null MemoryBlock is with \p EC describing the error.
  90. ///
  91. /// Allocate mapped memory.
  92. static MemoryBlock allocateMappedMemory(size_t NumBytes,
  93. const MemoryBlock *const NearBlock,
  94. unsigned Flags,
  95. std::error_code &EC);
  96. /// This method releases a block of memory that was allocated with the
  97. /// allocateMappedMemory method. It should not be used to release any
  98. /// memory block allocated any other way.
  99. /// \p Block describes the memory to be released.
  100. ///
  101. /// \r error_success if the function was successful, or an error_code
  102. /// describing the failure if an error occurred.
  103. ///
  104. /// Release mapped memory.
  105. static std::error_code releaseMappedMemory(MemoryBlock &Block);
  106. /// This method sets the protection flags for a block of memory to the
  107. /// state specified by /p Flags. The behavior is not specified if the
  108. /// memory was not allocated using the allocateMappedMemory method.
  109. /// \p Block describes the memory block to be protected.
  110. /// \p Flags specifies the new protection state to be assigned to the block.
  111. ///
  112. /// If \p Flags is MF_WRITE, the actual behavior varies
  113. /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
  114. /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
  115. ///
  116. /// \r error_success if the function was successful, or an error_code
  117. /// describing the failure if an error occurred.
  118. ///
  119. /// Set memory protection state.
  120. static std::error_code protectMappedMemory(const MemoryBlock &Block,
  121. unsigned Flags);
  122. /// InvalidateInstructionCache - Before the JIT can run a block of code
  123. /// that has been emitted it must invalidate the instruction cache on some
  124. /// platforms.
  125. static void InvalidateInstructionCache(const void *Addr, size_t Len);
  126. };
  127. /// Owning version of MemoryBlock.
  128. class OwningMemoryBlock {
  129. public:
  130. OwningMemoryBlock() = default;
  131. explicit OwningMemoryBlock(MemoryBlock M) : M(M) {}
  132. OwningMemoryBlock(OwningMemoryBlock &&Other) {
  133. M = Other.M;
  134. Other.M = MemoryBlock();
  135. }
  136. OwningMemoryBlock& operator=(OwningMemoryBlock &&Other) {
  137. M = Other.M;
  138. Other.M = MemoryBlock();
  139. return *this;
  140. }
  141. ~OwningMemoryBlock() {
  142. if (M.base())
  143. Memory::releaseMappedMemory(M);
  144. }
  145. void *base() const { return M.base(); }
  146. /// The size as it was allocated. This is always greater or equal to the
  147. /// size that was originally requested.
  148. size_t allocatedSize() const { return M.allocatedSize(); }
  149. MemoryBlock getMemoryBlock() const { return M; }
  150. std::error_code release() {
  151. std::error_code EC;
  152. if (M.base()) {
  153. EC = Memory::releaseMappedMemory(M);
  154. M = MemoryBlock();
  155. }
  156. return EC;
  157. }
  158. private:
  159. MemoryBlock M;
  160. };
  161. #ifndef NDEBUG
  162. /// Debugging output for Memory::ProtectionFlags.
  163. raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF);
  164. /// Debugging output for MemoryBlock.
  165. raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB);
  166. #endif // ifndef NDEBUG
  167. } // end namespace sys
  168. } // end namespace llvm
  169. #endif
  170. #ifdef __GNUC__
  171. #pragma GCC diagnostic pop
  172. #endif