Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Support/Memory.h
Line
Count
Source (jump to first uncovered line)
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 <string>
18
#include <system_error>
19
20
namespace llvm {
21
22
// Forward declare raw_ostream: it is used for debug dumping below.
23
class raw_ostream;
24
25
namespace sys {
26
27
  /// This class encapsulates the notion of a memory block which has an address
28
  /// and a size. It is used by the Memory class (a friend) as the result of
29
  /// various memory allocation operations.
30
  /// @see Memory
31
  /// Memory block abstraction.
32
  class MemoryBlock {
33
  public:
34
    MemoryBlock() : Address(nullptr), AllocatedSize(0) {}
35
    MemoryBlock(void *addr, size_t allocatedSize)
36
        : Address(addr), AllocatedSize(allocatedSize) {}
37
    void *base() const { return Address; }
38
    /// The size as it was allocated. This is always greater or equal to the
39
    /// size that was originally requested.
40
    size_t allocatedSize() const { return AllocatedSize; }
41
  
42
  private:
43
    void *Address;    ///< Address of first byte of memory area
44
    size_t AllocatedSize; ///< Size, in bytes of the memory area
45
    unsigned Flags = 0;
46
    friend class Memory;
47
  };
48
49
  /// This class provides various memory handling functions that manipulate
50
  /// MemoryBlock instances.
51
  /// @since 1.4
52
  /// An abstraction for memory operations.
53
  class Memory {
54
  public:
55
    enum ProtectionFlags {
56
      MF_READ = 0x1000000,
57
      MF_WRITE = 0x2000000,
58
      MF_EXEC = 0x4000000,
59
      MF_RWE_MASK = 0x7000000,
60
      MF_HUGE_HINT = 0x0000001
61
    };
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
92
    /// This method releases a block of memory that was allocated with the
93
    /// allocateMappedMemory method. It should not be used to release any
94
    /// memory block allocated any other way.
95
    /// \p Block describes the memory to be released.
96
    ///
97
    /// \r error_success if the function was successful, or an error_code
98
    /// describing the failure if an error occurred.
99
    ///
100
    /// Release mapped memory.
101
    static std::error_code releaseMappedMemory(MemoryBlock &Block);
102
103
    /// This method sets the protection flags for a block of memory to the
104
    /// state specified by /p Flags.  The behavior is not specified if the
105
    /// memory was not allocated using the allocateMappedMemory method.
106
    /// \p Block describes the memory block to be protected.
107
    /// \p Flags specifies the new protection state to be assigned to the block.
108
    /// \p ErrMsg [out] returns a string describing any error that occurred.
109
    ///
110
    /// If \p Flags is MF_WRITE, the actual behavior varies
111
    /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
112
    /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
113
    ///
114
    /// \r error_success if the function was successful, or an error_code
115
    /// describing the failure if an error occurred.
116
    ///
117
    /// Set memory protection state.
118
    static std::error_code protectMappedMemory(const MemoryBlock &Block,
119
                                               unsigned Flags);
120
121
    /// InvalidateInstructionCache - Before the JIT can run a block of code
122
    /// that has been emitted it must invalidate the instruction cache on some
123
    /// platforms.
124
    static void InvalidateInstructionCache(const void *Addr, size_t Len);
125
  };
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
      Memory::releaseMappedMemory(M);
143
    }
144
    void *base() const { return M.base(); }
145
    /// The size as it was allocated. This is always greater or equal to the
146
    /// size that was originally requested.
147
0
    size_t allocatedSize() const { return M.allocatedSize(); }
148
    MemoryBlock getMemoryBlock() const { return M; }
149
  private:
150
    MemoryBlock M;
151
  };
152
153
#ifndef NDEBUG
154
  /// Debugging output for Memory::ProtectionFlags.
155
  raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF);
156
157
  /// Debugging output for MemoryBlock.
158
  raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB);
159
#endif // ifndef NDEBUG
160
  }    // end namespace sys
161
  }    // end namespace llvm
162
163
#endif