1//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H
11#define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H
12
13#include "llvm/Support/DataTypes.h"
14#include <string>
15
16namespace llvm {
17
18  class Function;
19  class GlobalValue;
20
21/// JITMemoryManager - This interface is used by the JIT to allocate and manage
22/// memory for the code generated by the JIT.  This can be reimplemented by
23/// clients that have a strong desire to control how the layout of JIT'd memory
24/// works.
25class JITMemoryManager {
26protected:
27  bool HasGOT;
28
29public:
30  JITMemoryManager() : HasGOT(false) {}
31  virtual ~JITMemoryManager();
32
33  /// CreateDefaultMemManager - This is used to create the default
34  /// JIT Memory Manager if the client does not provide one to the JIT.
35  static JITMemoryManager *CreateDefaultMemManager();
36
37  /// setMemoryWritable - When code generation is in progress,
38  /// the code pages may need permissions changed.
39  virtual void setMemoryWritable() = 0;
40
41  /// setMemoryExecutable - When code generation is done and we're ready to
42  /// start execution, the code pages may need permissions changed.
43  virtual void setMemoryExecutable() = 0;
44
45  /// setPoisonMemory - Setting this flag to true makes the memory manager
46  /// garbage values over freed memory.  This is useful for testing and
47  /// debugging, and may be turned on by default in debug mode.
48  virtual void setPoisonMemory(bool poison) = 0;
49
50  /// getPointerToNamedFunction - This method returns the address of the
51  /// specified function. As such it is only useful for resolving library
52  /// symbols, not code generated symbols.
53  ///
54  /// If AbortOnFailure is false and no function with the given name is
55  /// found, this function silently returns a null pointer. Otherwise,
56  /// it prints a message to stderr and aborts.
57  ///
58  virtual void *getPointerToNamedFunction(const std::string &Name,
59                                          bool AbortOnFailure = true) = 0;
60
61  //===--------------------------------------------------------------------===//
62  // Global Offset Table Management
63  //===--------------------------------------------------------------------===//
64
65  /// AllocateGOT - If the current table requires a Global Offset Table, this
66  /// method is invoked to allocate it.  This method is required to set HasGOT
67  /// to true.
68  virtual void AllocateGOT() = 0;
69
70  /// isManagingGOT - Return true if the AllocateGOT method is called.
71  bool isManagingGOT() const {
72    return HasGOT;
73  }
74
75  /// getGOTBase - If this is managing a Global Offset Table, this method should
76  /// return a pointer to its base.
77  virtual uint8_t *getGOTBase() const = 0;
78
79  //===--------------------------------------------------------------------===//
80  // Main Allocation Functions
81  //===--------------------------------------------------------------------===//
82
83  /// startFunctionBody - When we start JITing a function, the JIT calls this
84  /// method to allocate a block of free RWX memory, which returns a pointer to
85  /// it.  If the JIT wants to request a block of memory of at least a certain
86  /// size, it passes that value as ActualSize, and this method returns a block
87  /// with at least that much space.  If the JIT doesn't know ahead of time how
88  /// much space it will need to emit the function, it passes 0 for the
89  /// ActualSize.  In either case, this method is required to pass back the size
90  /// of the allocated block through ActualSize.  The JIT will be careful to
91  /// not write more than the returned ActualSize bytes of memory.
92  virtual uint8_t *startFunctionBody(const Function *F,
93                                     uintptr_t &ActualSize) = 0;
94
95  /// allocateStub - This method is called by the JIT to allocate space for a
96  /// function stub (used to handle limited branch displacements) while it is
97  /// JIT compiling a function.  For example, if foo calls bar, and if bar
98  /// either needs to be lazily compiled or is a native function that exists too
99  /// far away from the call site to work, this method will be used to make a
100  /// thunk for it.  The stub should be "close" to the current function body,
101  /// but should not be included in the 'actualsize' returned by
102  /// startFunctionBody.
103  virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
104                                unsigned Alignment) = 0;
105
106  /// endFunctionBody - This method is called when the JIT is done codegen'ing
107  /// the specified function.  At this point we know the size of the JIT
108  /// compiled function.  This passes in FunctionStart (which was returned by
109  /// the startFunctionBody method) and FunctionEnd which is a pointer to the
110  /// actual end of the function.  This method should mark the space allocated
111  /// and remember where it is in case the client wants to deallocate it.
112  virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
113                               uint8_t *FunctionEnd) = 0;
114
115  /// allocateCodeSection - Allocate a memory block of (at least) the given
116  /// size suitable for executable code. The SectionID is a unique identifier
117  /// assigned by the JIT and passed through to the memory manager for
118  /// the instance class to use if it needs to communicate to the JIT about
119  /// a given section after the fact.
120  virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
121                                       unsigned SectionID) = 0;
122
123  /// allocateDataSection - Allocate a memory block of (at least) the given
124  /// size suitable for data. The SectionID is a unique identifier
125  /// assigned by the JIT and passed through to the memory manager for
126  /// the instance class to use if it needs to communicate to the JIT about
127  /// a given section after the fact.
128  virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
129                                       unsigned SectionID) = 0;
130
131  /// allocateSpace - Allocate a memory block of the given size.  This method
132  /// cannot be called between calls to startFunctionBody and endFunctionBody.
133  virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0;
134
135  /// allocateGlobal - Allocate memory for a global.
136  virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0;
137
138  /// deallocateFunctionBody - Free the specified function body.  The argument
139  /// must be the return value from a call to startFunctionBody() that hasn't
140  /// been deallocated yet.  This is never called when the JIT is currently
141  /// emitting a function.
142  virtual void deallocateFunctionBody(void *Body) = 0;
143
144  /// startExceptionTable - When we finished JITing the function, if exception
145  /// handling is set, we emit the exception table.
146  virtual uint8_t* startExceptionTable(const Function* F,
147                                       uintptr_t &ActualSize) = 0;
148
149  /// endExceptionTable - This method is called when the JIT is done emitting
150  /// the exception table.
151  virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
152                                 uint8_t *TableEnd, uint8_t* FrameRegister) = 0;
153
154  /// deallocateExceptionTable - Free the specified exception table's memory.
155  /// The argument must be the return value from a call to startExceptionTable()
156  /// that hasn't been deallocated yet.  This is never called when the JIT is
157  /// currently emitting an exception table.
158  virtual void deallocateExceptionTable(void *ET) = 0;
159
160  /// CheckInvariants - For testing only.  Return true if all internal
161  /// invariants are preserved, or return false and set ErrorStr to a helpful
162  /// error message.
163  virtual bool CheckInvariants(std::string &) {
164    return true;
165  }
166
167  /// GetDefaultCodeSlabSize - For testing only.  Returns DefaultCodeSlabSize
168  /// from DefaultJITMemoryManager.
169  virtual size_t GetDefaultCodeSlabSize() {
170    return 0;
171  }
172
173  /// GetDefaultDataSlabSize - For testing only.  Returns DefaultCodeSlabSize
174  /// from DefaultJITMemoryManager.
175  virtual size_t GetDefaultDataSlabSize() {
176    return 0;
177  }
178
179  /// GetDefaultStubSlabSize - For testing only.  Returns DefaultCodeSlabSize
180  /// from DefaultJITMemoryManager.
181  virtual size_t GetDefaultStubSlabSize() {
182    return 0;
183  }
184
185  /// GetNumCodeSlabs - For testing only.  Returns the number of MemoryBlocks
186  /// allocated for code.
187  virtual unsigned GetNumCodeSlabs() {
188    return 0;
189  }
190
191  /// GetNumDataSlabs - For testing only.  Returns the number of MemoryBlocks
192  /// allocated for data.
193  virtual unsigned GetNumDataSlabs() {
194    return 0;
195  }
196
197  /// GetNumStubSlabs - For testing only.  Returns the number of MemoryBlocks
198  /// allocated for function stubs.
199  virtual unsigned GetNumStubSlabs() {
200    return 0;
201  }
202};
203
204} // end namespace llvm.
205
206#endif
207