]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- MCJIT.h - Class definition for the MCJIT ----------------*- 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 | ||
1a4d82fc JJ |
10 | #ifndef LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H |
11 | #define LLVM_LIB_EXECUTIONENGINE_MCJIT_MCJIT_H | |
223e47cc | 12 | |
85aaf69f | 13 | #include "ObjectBuffer.h" |
1a4d82fc JJ |
14 | #include "llvm/ADT/DenseMap.h" |
15 | #include "llvm/ADT/SmallPtrSet.h" | |
970d7e83 | 16 | #include "llvm/ADT/SmallVector.h" |
223e47cc | 17 | #include "llvm/ExecutionEngine/ExecutionEngine.h" |
1a4d82fc | 18 | #include "llvm/ExecutionEngine/ObjectCache.h" |
223e47cc | 19 | #include "llvm/ExecutionEngine/RuntimeDyld.h" |
1a4d82fc | 20 | #include "llvm/IR/Module.h" |
223e47cc LB |
21 | |
22 | namespace llvm { | |
1a4d82fc | 23 | class MCJIT; |
223e47cc | 24 | |
1a4d82fc JJ |
25 | // This is a helper class that the MCJIT execution engine uses for linking |
26 | // functions across modules that it owns. It aggregates the memory manager | |
27 | // that is passed in to the MCJIT constructor and defers most functionality | |
28 | // to that object. | |
29 | class LinkingMemoryManager : public RTDyldMemoryManager { | |
30 | public: | |
85aaf69f SL |
31 | LinkingMemoryManager(MCJIT *Parent, |
32 | std::unique_ptr<RTDyldMemoryManager> MM) | |
33 | : ParentEngine(Parent), ClientMM(std::move(MM)) {} | |
1a4d82fc JJ |
34 | |
35 | uint64_t getSymbolAddress(const std::string &Name) override; | |
36 | ||
37 | // Functions deferred to client memory manager | |
38 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, | |
39 | unsigned SectionID, | |
40 | StringRef SectionName) override { | |
41 | return ClientMM->allocateCodeSection(Size, Alignment, SectionID, SectionName); | |
42 | } | |
43 | ||
44 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, | |
45 | unsigned SectionID, StringRef SectionName, | |
46 | bool IsReadOnly) override { | |
47 | return ClientMM->allocateDataSection(Size, Alignment, | |
48 | SectionID, SectionName, IsReadOnly); | |
49 | } | |
50 | ||
51 | void reserveAllocationSpace(uintptr_t CodeSize, uintptr_t DataSizeRO, | |
52 | uintptr_t DataSizeRW) override { | |
53 | return ClientMM->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); | |
54 | } | |
55 | ||
56 | bool needsToReserveAllocationSpace() override { | |
57 | return ClientMM->needsToReserveAllocationSpace(); | |
58 | } | |
59 | ||
60 | void notifyObjectLoaded(ExecutionEngine *EE, | |
85aaf69f | 61 | const object::ObjectFile &Obj) override { |
1a4d82fc JJ |
62 | ClientMM->notifyObjectLoaded(EE, Obj); |
63 | } | |
64 | ||
65 | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, | |
66 | size_t Size) override { | |
67 | ClientMM->registerEHFrames(Addr, LoadAddr, Size); | |
68 | } | |
970d7e83 | 69 | |
1a4d82fc JJ |
70 | void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, |
71 | size_t Size) override { | |
72 | ClientMM->deregisterEHFrames(Addr, LoadAddr, Size); | |
73 | } | |
74 | ||
75 | bool finalizeMemory(std::string *ErrMsg = nullptr) override { | |
76 | return ClientMM->finalizeMemory(ErrMsg); | |
77 | } | |
78 | ||
79 | private: | |
80 | MCJIT *ParentEngine; | |
81 | std::unique_ptr<RTDyldMemoryManager> ClientMM; | |
82 | }; | |
83 | ||
84 | // About Module states: added->loaded->finalized. | |
85 | // | |
86 | // The purpose of the "added" state is having modules in standby. (added=known | |
87 | // but not compiled). The idea is that you can add a module to provide function | |
88 | // definitions but if nothing in that module is referenced by a module in which | |
89 | // a function is executed (note the wording here because it's not exactly the | |
90 | // ideal case) then the module never gets compiled. This is sort of lazy | |
91 | // compilation. | |
92 | // | |
93 | // The purpose of the "loaded" state (loaded=compiled and required sections | |
94 | // copied into local memory but not yet ready for execution) is to have an | |
95 | // intermediate state wherein clients can remap the addresses of sections, using | |
96 | // MCJIT::mapSectionAddress, (in preparation for later copying to a new location | |
97 | // or an external process) before relocations and page permissions are applied. | |
98 | // | |
99 | // It might not be obvious at first glance, but the "remote-mcjit" case in the | |
100 | // lli tool does this. In that case, the intermediate action is taken by the | |
101 | // RemoteMemoryManager in response to the notifyObjectLoaded function being | |
102 | // called. | |
223e47cc LB |
103 | |
104 | class MCJIT : public ExecutionEngine { | |
1a4d82fc | 105 | MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, |
85aaf69f | 106 | std::unique_ptr<RTDyldMemoryManager> MemMgr); |
1a4d82fc JJ |
107 | |
108 | typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet; | |
109 | ||
110 | class OwningModuleContainer { | |
111 | public: | |
112 | OwningModuleContainer() { | |
113 | } | |
114 | ~OwningModuleContainer() { | |
115 | freeModulePtrSet(AddedModules); | |
116 | freeModulePtrSet(LoadedModules); | |
117 | freeModulePtrSet(FinalizedModules); | |
118 | } | |
119 | ||
120 | ModulePtrSet::iterator begin_added() { return AddedModules.begin(); } | |
121 | ModulePtrSet::iterator end_added() { return AddedModules.end(); } | |
122 | iterator_range<ModulePtrSet::iterator> added() { | |
123 | return iterator_range<ModulePtrSet::iterator>(begin_added(), end_added()); | |
124 | } | |
125 | ||
126 | ModulePtrSet::iterator begin_loaded() { return LoadedModules.begin(); } | |
127 | ModulePtrSet::iterator end_loaded() { return LoadedModules.end(); } | |
128 | ||
129 | ModulePtrSet::iterator begin_finalized() { return FinalizedModules.begin(); } | |
130 | ModulePtrSet::iterator end_finalized() { return FinalizedModules.end(); } | |
223e47cc | 131 | |
1a4d82fc JJ |
132 | void addModule(std::unique_ptr<Module> M) { |
133 | AddedModules.insert(M.release()); | |
134 | } | |
135 | ||
136 | bool removeModule(Module *M) { | |
137 | return AddedModules.erase(M) || LoadedModules.erase(M) || | |
138 | FinalizedModules.erase(M); | |
139 | } | |
140 | ||
141 | bool hasModuleBeenAddedButNotLoaded(Module *M) { | |
142 | return AddedModules.count(M) != 0; | |
143 | } | |
144 | ||
145 | bool hasModuleBeenLoaded(Module *M) { | |
146 | // If the module is in either the "loaded" or "finalized" sections it | |
147 | // has been loaded. | |
148 | return (LoadedModules.count(M) != 0 ) || (FinalizedModules.count(M) != 0); | |
149 | } | |
150 | ||
151 | bool hasModuleBeenFinalized(Module *M) { | |
152 | return FinalizedModules.count(M) != 0; | |
153 | } | |
154 | ||
155 | bool ownsModule(Module* M) { | |
156 | return (AddedModules.count(M) != 0) || (LoadedModules.count(M) != 0) || | |
157 | (FinalizedModules.count(M) != 0); | |
158 | } | |
159 | ||
160 | void markModuleAsLoaded(Module *M) { | |
161 | // This checks against logic errors in the MCJIT implementation. | |
162 | // This function should never be called with either a Module that MCJIT | |
163 | // does not own or a Module that has already been loaded and/or finalized. | |
164 | assert(AddedModules.count(M) && | |
165 | "markModuleAsLoaded: Module not found in AddedModules"); | |
166 | ||
167 | // Remove the module from the "Added" set. | |
168 | AddedModules.erase(M); | |
169 | ||
170 | // Add the Module to the "Loaded" set. | |
171 | LoadedModules.insert(M); | |
172 | } | |
173 | ||
174 | void markModuleAsFinalized(Module *M) { | |
175 | // This checks against logic errors in the MCJIT implementation. | |
176 | // This function should never be called with either a Module that MCJIT | |
177 | // does not own, a Module that has not been loaded or a Module that has | |
178 | // already been finalized. | |
179 | assert(LoadedModules.count(M) && | |
180 | "markModuleAsFinalized: Module not found in LoadedModules"); | |
181 | ||
182 | // Remove the module from the "Loaded" section of the list. | |
183 | LoadedModules.erase(M); | |
184 | ||
185 | // Add the Module to the "Finalized" section of the list by inserting it | |
186 | // before the 'end' iterator. | |
187 | FinalizedModules.insert(M); | |
188 | } | |
189 | ||
190 | void markAllLoadedModulesAsFinalized() { | |
191 | for (ModulePtrSet::iterator I = LoadedModules.begin(), | |
192 | E = LoadedModules.end(); | |
193 | I != E; ++I) { | |
194 | Module *M = *I; | |
195 | FinalizedModules.insert(M); | |
196 | } | |
197 | LoadedModules.clear(); | |
198 | } | |
199 | ||
200 | private: | |
201 | ModulePtrSet AddedModules; | |
202 | ModulePtrSet LoadedModules; | |
203 | ModulePtrSet FinalizedModules; | |
204 | ||
205 | void freeModulePtrSet(ModulePtrSet& MPS) { | |
206 | // Go through the module set and delete everything. | |
207 | for (ModulePtrSet::iterator I = MPS.begin(), E = MPS.end(); I != E; ++I) { | |
208 | Module *M = *I; | |
209 | delete M; | |
210 | } | |
211 | MPS.clear(); | |
212 | } | |
213 | }; | |
214 | ||
215 | std::unique_ptr<TargetMachine> TM; | |
223e47cc | 216 | MCContext *Ctx; |
1a4d82fc | 217 | LinkingMemoryManager MemMgr; |
223e47cc | 218 | RuntimeDyld Dyld; |
1a4d82fc JJ |
219 | std::vector<JITEventListener*> EventListeners; |
220 | ||
221 | OwningModuleContainer OwnedModules; | |
222 | ||
223 | SmallVector<object::OwningBinary<object::Archive>, 2> Archives; | |
224 | SmallVector<std::unique_ptr<MemoryBuffer>, 2> Buffers; | |
225 | ||
85aaf69f | 226 | SmallVector<std::unique_ptr<object::ObjectFile>, 2> LoadedObjects; |
223e47cc | 227 | |
1a4d82fc JJ |
228 | // An optional ObjectCache to be notified of compiled objects and used to |
229 | // perform lookup of pre-compiled code to avoid re-compilation. | |
230 | ObjectCache *ObjCache; | |
231 | ||
232 | Function *FindFunctionNamedInModulePtrSet(const char *FnName, | |
233 | ModulePtrSet::iterator I, | |
234 | ModulePtrSet::iterator E); | |
235 | ||
236 | void runStaticConstructorsDestructorsInModulePtrSet(bool isDtors, | |
237 | ModulePtrSet::iterator I, | |
238 | ModulePtrSet::iterator E); | |
223e47cc LB |
239 | |
240 | public: | |
241 | ~MCJIT(); | |
242 | ||
243 | /// @name ExecutionEngine interface implementation | |
244 | /// @{ | |
1a4d82fc JJ |
245 | void addModule(std::unique_ptr<Module> M) override; |
246 | void addObjectFile(std::unique_ptr<object::ObjectFile> O) override; | |
247 | void addObjectFile(object::OwningBinary<object::ObjectFile> O) override; | |
248 | void addArchive(object::OwningBinary<object::Archive> O) override; | |
249 | bool removeModule(Module *M) override; | |
250 | ||
251 | /// FindFunctionNamed - Search all of the active modules to find the one that | |
252 | /// defines FnName. This is very slow operation and shouldn't be used for | |
253 | /// general code. | |
254 | Function *FindFunctionNamed(const char *FnName) override; | |
223e47cc | 255 | |
1a4d82fc JJ |
256 | /// Sets the object manager that MCJIT should use to avoid compilation. |
257 | void setObjectCache(ObjectCache *manager) override; | |
970d7e83 | 258 | |
1a4d82fc JJ |
259 | void setProcessAllSections(bool ProcessAllSections) override { |
260 | Dyld.setProcessAllSections(ProcessAllSections); | |
261 | } | |
262 | ||
263 | void generateCodeForModule(Module *M) override; | |
223e47cc | 264 | |
1a4d82fc JJ |
265 | /// finalizeObject - ensure the module is fully processed and is usable. |
266 | /// | |
267 | /// It is the user-level function for completing the process of making the | |
268 | /// object usable for execution. It should be called after sections within an | |
269 | /// object have been relocated using mapSectionAddress. When this method is | |
270 | /// called the MCJIT execution engine will reapply relocations for a loaded | |
271 | /// object. | |
272 | /// Is it OK to finalize a set of modules, add modules and finalize again. | |
273 | // FIXME: Do we really need both of these? | |
274 | void finalizeObject() override; | |
275 | virtual void finalizeModule(Module *); | |
276 | void finalizeLoadedModules(); | |
223e47cc | 277 | |
1a4d82fc JJ |
278 | /// runStaticConstructorsDestructors - This method is used to execute all of |
279 | /// the static constructors or destructors for a program. | |
280 | /// | |
281 | /// \param isDtors - Run the destructors instead of constructors. | |
282 | void runStaticConstructorsDestructors(bool isDtors) override; | |
223e47cc | 283 | |
1a4d82fc | 284 | void *getPointerToFunction(Function *F) override; |
223e47cc | 285 | |
1a4d82fc JJ |
286 | GenericValue runFunction(Function *F, |
287 | const std::vector<GenericValue> &ArgValues) override; | |
223e47cc LB |
288 | |
289 | /// getPointerToNamedFunction - This method returns the address of the | |
290 | /// specified function by using the dlsym function call. As such it is only | |
291 | /// useful for resolving library symbols, not code generated symbols. | |
292 | /// | |
293 | /// If AbortOnFailure is false and no function with the given name is | |
294 | /// found, this function silently returns a null pointer. Otherwise, | |
295 | /// it prints a message to stderr and aborts. | |
296 | /// | |
1a4d82fc JJ |
297 | void *getPointerToNamedFunction(StringRef Name, |
298 | bool AbortOnFailure = true) override; | |
223e47cc LB |
299 | |
300 | /// mapSectionAddress - map a section to its target address space value. | |
301 | /// Map the address of a JIT section as returned from the memory manager | |
302 | /// to the address in the target process as the running code will see it. | |
303 | /// This is the address which will be used for relocation resolution. | |
1a4d82fc JJ |
304 | void mapSectionAddress(const void *LocalAddress, |
305 | uint64_t TargetAddress) override { | |
223e47cc LB |
306 | Dyld.mapSectionAddress(LocalAddress, TargetAddress); |
307 | } | |
1a4d82fc JJ |
308 | void RegisterJITEventListener(JITEventListener *L) override; |
309 | void UnregisterJITEventListener(JITEventListener *L) override; | |
223e47cc | 310 | |
1a4d82fc JJ |
311 | // If successful, these function will implicitly finalize all loaded objects. |
312 | // To get a function address within MCJIT without causing a finalize, use | |
313 | // getSymbolAddress. | |
314 | uint64_t getGlobalValueAddress(const std::string &Name) override; | |
315 | uint64_t getFunctionAddress(const std::string &Name) override; | |
316 | ||
317 | TargetMachine *getTargetMachine() override { return TM.get(); } | |
970d7e83 | 318 | |
223e47cc LB |
319 | /// @} |
320 | /// @name (Private) Registration Interfaces | |
321 | /// @{ | |
322 | ||
323 | static void Register() { | |
324 | MCJITCtor = createJIT; | |
325 | } | |
326 | ||
1a4d82fc | 327 | static ExecutionEngine *createJIT(std::unique_ptr<Module> M, |
223e47cc | 328 | std::string *ErrorStr, |
85aaf69f | 329 | std::unique_ptr<RTDyldMemoryManager> MemMgr, |
1a4d82fc | 330 | std::unique_ptr<TargetMachine> TM); |
223e47cc LB |
331 | |
332 | // @} | |
333 | ||
1a4d82fc JJ |
334 | // This is not directly exposed via the ExecutionEngine API, but it is |
335 | // used by the LinkingMemoryManager. | |
336 | uint64_t getSymbolAddress(const std::string &Name, | |
337 | bool CheckFunctionsOnly); | |
338 | ||
223e47cc LB |
339 | protected: |
340 | /// emitObject -- Generate a JITed object in memory from the specified module | |
341 | /// Currently, MCJIT only supports a single module and the module passed to | |
342 | /// this function call is expected to be the contained module. The module | |
1a4d82fc | 343 | /// is passed as a parameter here to prepare for multiple module support in |
223e47cc | 344 | /// the future. |
85aaf69f | 345 | std::unique_ptr<MemoryBuffer> emitObject(Module *M); |
970d7e83 | 346 | |
85aaf69f SL |
347 | void NotifyObjectEmitted(const object::ObjectFile& Obj, |
348 | const RuntimeDyld::LoadedObjectInfo &L); | |
349 | void NotifyFreeingObject(const object::ObjectFile& Obj); | |
1a4d82fc JJ |
350 | |
351 | uint64_t getExistingSymbolAddress(const std::string &Name); | |
352 | Module *findModuleForSymbol(const std::string &Name, | |
353 | bool CheckFunctionsOnly); | |
223e47cc LB |
354 | }; |
355 | ||
356 | } // End llvm namespace | |
357 | ||
358 | #endif |