Memory.h 6.8 KB

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