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 16 namespace 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. 25 class JITMemoryManager { 26 protected: 27 bool HasGOT; 28 29 public: JITMemoryManager()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 //===--------------------------------------------------------------------===// 51 // Global Offset Table Management 52 //===--------------------------------------------------------------------===// 53 54 /// AllocateGOT - If the current table requires a Global Offset Table, this 55 /// method is invoked to allocate it. This method is required to set HasGOT 56 /// to true. 57 virtual void AllocateGOT() = 0; 58 59 /// isManagingGOT - Return true if the AllocateGOT method is called. isManagingGOT()60 bool isManagingGOT() const { 61 return HasGOT; 62 } 63 64 /// getGOTBase - If this is managing a Global Offset Table, this method should 65 /// return a pointer to its base. 66 virtual uint8_t *getGOTBase() const = 0; 67 68 //===--------------------------------------------------------------------===// 69 // Main Allocation Functions 70 //===--------------------------------------------------------------------===// 71 72 /// startFunctionBody - When we start JITing a function, the JIT calls this 73 /// method to allocate a block of free RWX memory, which returns a pointer to 74 /// it. If the JIT wants to request a block of memory of at least a certain 75 /// size, it passes that value as ActualSize, and this method returns a block 76 /// with at least that much space. If the JIT doesn't know ahead of time how 77 /// much space it will need to emit the function, it passes 0 for the 78 /// ActualSize. In either case, this method is required to pass back the size 79 /// of the allocated block through ActualSize. The JIT will be careful to 80 /// not write more than the returned ActualSize bytes of memory. 81 virtual uint8_t *startFunctionBody(const Function *F, 82 uintptr_t &ActualSize) = 0; 83 84 /// allocateStub - This method is called by the JIT to allocate space for a 85 /// function stub (used to handle limited branch displacements) while it is 86 /// JIT compiling a function. For example, if foo calls bar, and if bar 87 /// either needs to be lazily compiled or is a native function that exists too 88 /// far away from the call site to work, this method will be used to make a 89 /// thunk for it. The stub should be "close" to the current function body, 90 /// but should not be included in the 'actualsize' returned by 91 /// startFunctionBody. 92 virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, 93 unsigned Alignment) = 0; 94 95 /// endFunctionBody - This method is called when the JIT is done codegen'ing 96 /// the specified function. At this point we know the size of the JIT 97 /// compiled function. This passes in FunctionStart (which was returned by 98 /// the startFunctionBody method) and FunctionEnd which is a pointer to the 99 /// actual end of the function. This method should mark the space allocated 100 /// and remember where it is in case the client wants to deallocate it. 101 virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, 102 uint8_t *FunctionEnd) = 0; 103 104 /// allocateSpace - Allocate a memory block of the given size. This method 105 /// cannot be called between calls to startFunctionBody and endFunctionBody. 106 virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; 107 108 /// allocateGlobal - Allocate memory for a global. 109 virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; 110 111 /// deallocateFunctionBody - Free the specified function body. The argument 112 /// must be the return value from a call to startFunctionBody() that hasn't 113 /// been deallocated yet. This is never called when the JIT is currently 114 /// emitting a function. 115 virtual void deallocateFunctionBody(void *Body) = 0; 116 117 /// startExceptionTable - When we finished JITing the function, if exception 118 /// handling is set, we emit the exception table. 119 virtual uint8_t* startExceptionTable(const Function* F, 120 uintptr_t &ActualSize) = 0; 121 122 /// endExceptionTable - This method is called when the JIT is done emitting 123 /// the exception table. 124 virtual void endExceptionTable(const Function *F, uint8_t *TableStart, 125 uint8_t *TableEnd, uint8_t* FrameRegister) = 0; 126 127 /// deallocateExceptionTable - Free the specified exception table's memory. 128 /// The argument must be the return value from a call to startExceptionTable() 129 /// that hasn't been deallocated yet. This is never called when the JIT is 130 /// currently emitting an exception table. 131 virtual void deallocateExceptionTable(void *ET) = 0; 132 133 /// CheckInvariants - For testing only. Return true if all internal 134 /// invariants are preserved, or return false and set ErrorStr to a helpful 135 /// error message. CheckInvariants(std::string &)136 virtual bool CheckInvariants(std::string &) { 137 return true; 138 } 139 140 /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize 141 /// from DefaultJITMemoryManager. GetDefaultCodeSlabSize()142 virtual size_t GetDefaultCodeSlabSize() { 143 return 0; 144 } 145 146 /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize 147 /// from DefaultJITMemoryManager. GetDefaultDataSlabSize()148 virtual size_t GetDefaultDataSlabSize() { 149 return 0; 150 } 151 152 /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize 153 /// from DefaultJITMemoryManager. GetDefaultStubSlabSize()154 virtual size_t GetDefaultStubSlabSize() { 155 return 0; 156 } 157 158 /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks 159 /// allocated for code. GetNumCodeSlabs()160 virtual unsigned GetNumCodeSlabs() { 161 return 0; 162 } 163 164 /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks 165 /// allocated for data. GetNumDataSlabs()166 virtual unsigned GetNumDataSlabs() { 167 return 0; 168 } 169 170 /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks 171 /// allocated for function stubs. GetNumStubSlabs()172 virtual unsigned GetNumStubSlabs() { 173 return 0; 174 } 175 }; 176 177 } // end namespace llvm. 178 179 #endif 180