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