Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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
      if (M.base())
152
        Memory::releaseMappedMemory(M);
153
    }
154
    void *base() const { return M.base(); }
155
    /// The size as it was allocated. This is always greater or equal to the
156
    /// size that was originally requested.
157
    size_t allocatedSize() const { return M.allocatedSize(); }
158
    MemoryBlock getMemoryBlock() const { return M; }
159
    std::error_code release() {
160
      std::error_code EC;
161
      if (M.base()) {
162
        EC = Memory::releaseMappedMemory(M);
163
        M = MemoryBlock();
164
      }
165
      return EC;
166
    }
167
  private:
168
    MemoryBlock M;
169
  };
170
 
171
#ifndef NDEBUG
172
  /// Debugging output for Memory::ProtectionFlags.
173
  raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF);
174
 
175
  /// Debugging output for MemoryBlock.
176
  raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB);
177
#endif // ifndef NDEBUG
178
  }    // end namespace sys
179
  }    // end namespace llvm
180
 
181
#endif