//===- ExecutionEngine.h - Abstract Execution Engine Interface --*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the abstract interface that implements execution support // for LLVM. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTION_ENGINE_H #define LLVM_EXECUTION_ENGINE_H #include #include #include #include "llvm/System/Mutex.h" #include "llvm/ADT/SmallVector.h" namespace llvm { struct GenericValue; class Constant; class Function; class GlobalVariable; class GlobalValue; class Module; class ModuleProvider; class TargetData; class Type; class MutexGuard; class JITMemoryManager; class ExecutionEngineState { private: /// GlobalAddressMap - A mapping between LLVM global values and their /// actualized version... std::map GlobalAddressMap; /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, /// used to convert raw addresses into the LLVM global value that is emitted /// at the address. This map is not computed unless getGlobalValueAtAddress /// is called at some point. std::map GlobalAddressReverseMap; public: std::map & getGlobalAddressMap(const MutexGuard &) { return GlobalAddressMap; } std::map & getGlobalAddressReverseMap(const MutexGuard &) { return GlobalAddressReverseMap; } }; class ExecutionEngine { const TargetData *TD; ExecutionEngineState state; bool LazyCompilationDisabled; bool GVCompilationDisabled; bool SymbolSearchingDisabled; bool DlsymStubsEnabled; protected: /// Modules - This is a list of ModuleProvider's that we are JIT'ing from. We /// use a smallvector to optimize for the case where there is only one module. SmallVector Modules; void setTargetData(const TargetData *td) { TD = td; } /// getMemoryforGV - Allocate memory for a global variable. virtual char* getMemoryForGV(const GlobalVariable* GV); // To avoid having libexecutionengine depend on the JIT and interpreter // libraries, the JIT and Interpreter set these functions to ctor pointers // at startup time if they are linked in. typedef ExecutionEngine *(*EECtorFn)(ModuleProvider*, std::string*, bool Fast); static EECtorFn JITCtor, InterpCtor; /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will abort. void* (*LazyFunctionCreator)(const std::string &); /// ExceptionTableRegister - If Exception Handling is set, the JIT will /// register dwarf tables with this function typedef void (*EERegisterFn)(void*); static EERegisterFn ExceptionTableRegister; public: /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and /// JITEmitter classes. It must be held while changing the internal state of /// any of those classes. sys::Mutex lock; // Used to make this class and subclasses thread-safe //===--------------------------------------------------------------------===// // ExecutionEngine Startup //===--------------------------------------------------------------------===// virtual ~ExecutionEngine(); /// create - This is the factory method for creating an execution engine which /// is appropriate for the current machine. This takes ownership of the /// module provider. static ExecutionEngine *create(ModuleProvider *MP, bool ForceInterpreter = false, std::string *ErrorStr = 0, bool Fast = false); /// create - This is the factory method for creating an execution engine which /// is appropriate for the current machine. This takes ownership of the /// module. static ExecutionEngine *create(Module *M); /// createJIT - This is the factory method for creating a JIT for the current /// machine, it does not fall back to the interpreter. This takes ownership /// of the ModuleProvider and JITMemoryManager if successful. static ExecutionEngine *createJIT(ModuleProvider *MP, std::string *ErrorStr = 0, JITMemoryManager *JMM = 0, bool Fast = false); /// addModuleProvider - Add a ModuleProvider to the list of modules that we /// can JIT from. Note that this takes ownership of the ModuleProvider: when /// the ExecutionEngine is destroyed, it destroys the MP as well. virtual void addModuleProvider(ModuleProvider *P) { Modules.push_back(P); } //===----------------------------------------------------------------------===// const TargetData *getTargetData() const { return TD; } /// removeModuleProvider - Remove a ModuleProvider from the list of modules. /// Relases the Module from the ModuleProvider, materializing it in the /// process, and returns the materialized Module. virtual Module* removeModuleProvider(ModuleProvider *P, std::string *ErrInfo = 0); /// deleteModuleProvider - Remove a ModuleProvider from the list of modules, /// and deletes the ModuleProvider and owned Module. Avoids materializing /// the underlying module. virtual void deleteModuleProvider(ModuleProvider *P,std::string *ErrInfo = 0); /// FindFunctionNamed - Search all of the active modules to find the one that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. Function *FindFunctionNamed(const char *FnName); /// runFunction - Execute the specified function with the specified arguments, /// and return the result. /// virtual GenericValue runFunction(Function *F, const std::vector &ArgValues) = 0; /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a program, depending on the /// value of isDtors. void runStaticConstructorsDestructors(bool isDtors); /// runStaticConstructorsDestructors - This method is used to execute all of /// the static constructors or destructors for a module, depending on the /// value of isDtors. void runStaticConstructorsDestructors(Module *module, bool isDtors); /// runFunctionAsMain - This is a helper function which wraps runFunction to /// handle the common task of starting up main with the specified argc, argv, /// and envp parameters. int runFunctionAsMain(Function *Fn, const std::vector &argv, const char * const * envp); /// addGlobalMapping - Tell the execution engine that the specified global is /// at the specified location. This is used internally as functions are JIT'd /// and as global variables are laid out in memory. It can and should also be /// used by clients of the EE that want to have an LLVM global overlay /// existing data in memory. After adding a mapping for GV, you must not /// destroy it until you've removed the mapping. void addGlobalMapping(const GlobalValue *GV, void *Addr); /// clearAllGlobalMappings - Clear all global mappings and start over again /// use in dynamic compilation scenarios when you want to move globals void clearAllGlobalMappings(); /// clearGlobalMappingsFromModule - Clear all global mappings that came from a /// particular module, because it has been removed from the JIT. void clearGlobalMappingsFromModule(Module *M); /// updateGlobalMapping - Replace an existing mapping for GV with a new /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. This returns the old /// value of the pointer, or null if it was not in the map. void *updateGlobalMapping(const GlobalValue *GV, void *Addr); /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. /// void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global /// value. This may involve code generation if it's a function. After /// getting a pointer to GV, it and all globals it transitively refers to have /// been passed to addGlobalMapping. You must clear the mapping for each /// referred-to global before destroying it. If a referred-to global RTG is a /// function and this ExecutionEngine is a JIT compiler, calling /// updateGlobalMapping(RTG, 0) will leak the function's machine code, so you /// should call freeMachineCodeForFunction(RTG) instead. Note that /// optimizations can move and delete non-external GlobalValues without /// notifying the ExecutionEngine. /// void *getPointerToGlobal(const GlobalValue *GV); /// getPointerToFunction - The different EE's represent function bodies in /// different ways. They should each implement this to say what a function /// pointer should look like. See getPointerToGlobal for the requirements on /// destroying F and any GlobalValues it refers to. /// virtual void *getPointerToFunction(Function *F) = 0; /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See getPointerToGlobal /// for the requirements on destroying F and any GlobalValues it refers to. /// virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } /// getGlobalValueAtAddress - Return the LLVM global value object that starts /// at the specified address. /// const GlobalValue *getGlobalValueAtAddress(void *Addr); void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, const Type *Ty); void InitializeMemory(const Constant *Init, void *Addr); /// recompileAndRelinkFunction - This method is used to force a function /// which has already been compiled to be compiled again, possibly /// after it has been modified. Then the entry to the old copy is overwritten /// with a branch to the new copy. If there was no old copy, this acts /// just like VM::getPointerToFunction(). /// virtual void *recompileAndRelinkFunction(Function *F) = 0; /// freeMachineCodeForFunction - Release memory in the ExecutionEngine /// corresponding to the machine code emitted to execute this function, useful /// for garbage-collecting generated code. /// virtual void freeMachineCodeForFunction(Function *F) = 0; /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. See getPointerToGlobal for the requirements on destroying GV and /// any GlobalValues it refers to. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((GlobalValue*)GV); } /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation /// is ever attempted. void DisableLazyCompilation(bool Disabled = true) { LazyCompilationDisabled = Disabled; } bool isLazyCompilationDisabled() const { return LazyCompilationDisabled; } /// DisableGVCompilation - If called, the JIT will abort if it's asked to /// allocate space and populate a GlobalVariable that is not internal to /// the module. void DisableGVCompilation(bool Disabled = true) { GVCompilationDisabled = Disabled; } bool isGVCompilationDisabled() const { return GVCompilationDisabled; } /// DisableSymbolSearching - If called, the JIT will not try to lookup unknown /// symbols with dlsym. A client can still use InstallLazyFunctionCreator to /// resolve symbols in a custom way. void DisableSymbolSearching(bool Disabled = true) { SymbolSearchingDisabled = Disabled; } bool isSymbolSearchingDisabled() const { return SymbolSearchingDisabled; } /// EnableDlsymStubs - void EnableDlsymStubs(bool Enabled = true) { DlsymStubsEnabled = Enabled; } bool areDlsymStubsEnabled() const { return DlsymStubsEnabled; } /// InstallLazyFunctionCreator - If an unknown function is needed, the /// specified function pointer is invoked to create it. If it returns null, /// the JIT will abort. void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { LazyFunctionCreator = P; } /// InstallExceptionTableRegister - The JIT will use the given function /// to register the exception tables it generates. static void InstallExceptionTableRegister(void (*F)(void*)) { ExceptionTableRegister = F; } /// RegisterTable - Registers the given pointer as an exception table. It uses /// the ExceptionTableRegister function. static void RegisterTable(void* res) { if (ExceptionTableRegister) ExceptionTableRegister(res); } protected: explicit ExecutionEngine(ModuleProvider *P); void emitGlobals(); // EmitGlobalVariable - This method emits the specified global variable to the // address specified in GlobalAddresses, or allocates new memory if it's not // already in the map. void EmitGlobalVariable(const GlobalVariable *GV); GenericValue getConstantValue(const Constant *C); void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, const Type *Ty); }; } // End llvm namespace #endif