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 /// 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. isManagingGOT()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. CheckInvariants(std::string &)163 virtual bool CheckInvariants(std::string &) { 164 return true; 165 } 166 167 /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize 168 /// from DefaultJITMemoryManager. GetDefaultCodeSlabSize()169 virtual size_t GetDefaultCodeSlabSize() { 170 return 0; 171 } 172 173 /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize 174 /// from DefaultJITMemoryManager. GetDefaultDataSlabSize()175 virtual size_t GetDefaultDataSlabSize() { 176 return 0; 177 } 178 179 /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize 180 /// from DefaultJITMemoryManager. GetDefaultStubSlabSize()181 virtual size_t GetDefaultStubSlabSize() { 182 return 0; 183 } 184 185 /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks 186 /// allocated for code. GetNumCodeSlabs()187 virtual unsigned GetNumCodeSlabs() { 188 return 0; 189 } 190 191 /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks 192 /// allocated for data. GetNumDataSlabs()193 virtual unsigned GetNumDataSlabs() { 194 return 0; 195 } 196 197 /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks 198 /// allocated for function stubs. GetNumStubSlabs()199 virtual unsigned GetNumStubSlabs() { 200 return 0; 201 } 202 }; 203 204 } // end namespace llvm. 205 206 #endif 207