Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:32

0001 //===- llvm/Support/Memory.h - Memory Support -------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file declares the llvm::sys::Memory class.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_SUPPORT_MEMORY_H
0014 #define LLVM_SUPPORT_MEMORY_H
0015 
0016 #include "llvm/Support/DataTypes.h"
0017 #include <system_error>
0018 #include <utility>
0019 
0020 namespace llvm {
0021 
0022 // Forward declare raw_ostream: it is used for debug dumping below.
0023 class raw_ostream;
0024 
0025 namespace sys {
0026 
0027   /// This class encapsulates the notion of a memory block which has an address
0028   /// and a size. It is used by the Memory class (a friend) as the result of
0029   /// various memory allocation operations.
0030   /// @see Memory
0031   /// Memory block abstraction.
0032   class MemoryBlock {
0033   public:
0034     MemoryBlock() : Address(nullptr), AllocatedSize(0) {}
0035     MemoryBlock(void *addr, size_t allocatedSize)
0036         : Address(addr), AllocatedSize(allocatedSize) {}
0037     void *base() const { return Address; }
0038     /// The size as it was allocated. This is always greater or equal to the
0039     /// size that was originally requested.
0040     size_t allocatedSize() const { return AllocatedSize; }
0041 
0042   private:
0043     void *Address;    ///< Address of first byte of memory area
0044     size_t AllocatedSize; ///< Size, in bytes of the memory area
0045     unsigned Flags = 0;
0046     friend class Memory;
0047   };
0048 
0049   /// This class provides various memory handling functions that manipulate
0050   /// MemoryBlock instances.
0051   /// @since 1.4
0052   /// An abstraction for memory operations.
0053   class Memory {
0054   public:
0055     enum ProtectionFlags {
0056       MF_READ = 0x1000000,
0057       MF_WRITE = 0x2000000,
0058       MF_EXEC = 0x4000000,
0059       MF_RWE_MASK = 0x7000000,
0060 
0061       /// The \p MF_HUGE_HINT flag is used to indicate that the request for
0062       /// a memory block should be satisfied with large pages if possible.
0063       /// This is only a hint and small pages will be used as fallback.
0064       ///
0065       /// The presence or absence of this flag in the returned memory block
0066       /// is (at least currently) *not* a reliable indicator that the memory
0067       /// block will use or will not use large pages. On some systems a request
0068       /// without this flag can be backed by large pages without this flag being
0069       /// set, and on some other systems a request with this flag can fallback
0070       /// to small pages without this flag being cleared.
0071       MF_HUGE_HINT = 0x0000001
0072     };
0073 
0074     /// This method allocates a block of memory that is suitable for loading
0075     /// dynamically generated code (e.g. JIT). An attempt to allocate
0076     /// \p NumBytes bytes of virtual memory is made.
0077     /// \p NearBlock may point to an existing allocation in which case
0078     /// an attempt is made to allocate more memory near the existing block.
0079     /// The actual allocated address is not guaranteed to be near the requested
0080     /// address.
0081     /// \p Flags is used to set the initial protection flags for the block
0082     /// of the memory.
0083     /// \p EC [out] returns an object describing any error that occurs.
0084     ///
0085     /// This method may allocate more than the number of bytes requested.  The
0086     /// actual number of bytes allocated is indicated in the returned
0087     /// MemoryBlock.
0088     ///
0089     /// The start of the allocated block must be aligned with the
0090     /// system allocation granularity (64K on Windows, page size on Linux).
0091     /// If the address following \p NearBlock is not so aligned, it will be
0092     /// rounded up to the next allocation granularity boundary.
0093     ///
0094     /// \r a non-null MemoryBlock if the function was successful,
0095     /// otherwise a null MemoryBlock is with \p EC describing the error.
0096     ///
0097     /// Allocate mapped memory.
0098     static MemoryBlock allocateMappedMemory(size_t NumBytes,
0099                                             const MemoryBlock *const NearBlock,
0100                                             unsigned Flags,
0101                                             std::error_code &EC);
0102 
0103     /// This method releases a block of memory that was allocated with the
0104     /// allocateMappedMemory method. It should not be used to release any
0105     /// memory block allocated any other way.
0106     /// \p Block describes the memory to be released.
0107     ///
0108     /// \r error_success if the function was successful, or an error_code
0109     /// describing the failure if an error occurred.
0110     ///
0111     /// Release mapped memory.
0112     static std::error_code releaseMappedMemory(MemoryBlock &Block);
0113 
0114     /// This method sets the protection flags for a block of memory to the
0115     /// state specified by /p Flags.  The behavior is not specified if the
0116     /// memory was not allocated using the allocateMappedMemory method.
0117     /// \p Block describes the memory block to be protected.
0118     /// \p Flags specifies the new protection state to be assigned to the block.
0119     ///
0120     /// If \p Flags is MF_WRITE, the actual behavior varies
0121     /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
0122     /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
0123     ///
0124     /// \r error_success if the function was successful, or an error_code
0125     /// describing the failure if an error occurred.
0126     ///
0127     /// Set memory protection state.
0128     static std::error_code protectMappedMemory(const MemoryBlock &Block,
0129                                                unsigned Flags);
0130 
0131     /// InvalidateInstructionCache - Before the JIT can run a block of code
0132     /// that has been emitted it must invalidate the instruction cache on some
0133     /// platforms.
0134     static void InvalidateInstructionCache(const void *Addr, size_t Len);
0135   };
0136 
0137   /// Owning version of MemoryBlock.
0138   class OwningMemoryBlock {
0139   public:
0140     OwningMemoryBlock() = default;
0141     explicit OwningMemoryBlock(MemoryBlock M) : M(std::move(M)) {}
0142     OwningMemoryBlock(OwningMemoryBlock &&Other) {
0143       M = Other.M;
0144       Other.M = MemoryBlock();
0145     }
0146     OwningMemoryBlock& operator=(OwningMemoryBlock &&Other) {
0147       M = Other.M;
0148       Other.M = MemoryBlock();
0149       return *this;
0150     }
0151     ~OwningMemoryBlock() {
0152       if (M.base())
0153         Memory::releaseMappedMemory(M);
0154     }
0155     void *base() const { return M.base(); }
0156     /// The size as it was allocated. This is always greater or equal to the
0157     /// size that was originally requested.
0158     size_t allocatedSize() const { return M.allocatedSize(); }
0159     MemoryBlock getMemoryBlock() const { return M; }
0160     std::error_code release() {
0161       std::error_code EC;
0162       if (M.base()) {
0163         EC = Memory::releaseMappedMemory(M);
0164         M = MemoryBlock();
0165       }
0166       return EC;
0167     }
0168   private:
0169     MemoryBlock M;
0170   };
0171 
0172 #ifndef NDEBUG
0173   /// Debugging output for Memory::ProtectionFlags.
0174   raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF);
0175 
0176   /// Debugging output for MemoryBlock.
0177   raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB);
0178 #endif // ifndef NDEBUG
0179   }    // end namespace sys
0180   }    // end namespace llvm
0181 
0182 #endif