X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FExecutionEngine%2FExecutionEngine.h;h=5bd34e8556094b8e50d63f268dec6ffe35c760d2;hb=0b6cb7104b15504cd41f48cc2babcbcee70775f3;hp=014473adaeb95bbec168307f4bf854b8f9a822cf;hpb=5e5cb7985de2508ecd707568afbcbb39e8a688fc;p=oota-llvm.git diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 014473adaeb..5bd34e85560 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -12,95 +12,156 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTION_ENGINE_H -#define LLVM_EXECUTION_ENGINE_H +#ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H -#include +#include "llvm-c/ExecutionEngine.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" +#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include #include -#include "llvm/System/Mutex.h" -#include "llvm/ADT/SmallVector.h" +#include namespace llvm { struct GenericValue; class Constant; +class DataLayout; +class ExecutionEngine; class Function; class GlobalVariable; class GlobalValue; +class JITEventListener; +class JITMemoryManager; +class MachineCodeInfo; class Module; -class ModuleProvider; -class TargetData; -class Type; class MutexGuard; -class JITMemoryManager; +class ObjectCache; +class RTDyldMemoryManager; +class Triple; +class Type; + +namespace object { + class Archive; + class ObjectFile; +} +/// \brief Helper class for helping synchronize access to the global address map +/// table. class ExecutionEngineState { +public: + struct AddressMapConfig : public ValueMapConfig { + typedef ExecutionEngineState *ExtraData; + static sys::Mutex *getMutex(ExecutionEngineState *EES); + static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old); + static void onRAUW(ExecutionEngineState *, const GlobalValue *, + const GlobalValue *); + }; + + typedef ValueMap + GlobalAddressMapTy; + private: + ExecutionEngine ⅇ + /// GlobalAddressMap - A mapping between LLVM global values and their /// actualized version... - std::map GlobalAddressMap; + GlobalAddressMapTy 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; + std::map > GlobalAddressReverseMap; public: - std::map & - getGlobalAddressMap(const MutexGuard &) { + ExecutionEngineState(ExecutionEngine &EE); + + GlobalAddressMapTy &getGlobalAddressMap(const MutexGuard &) { return GlobalAddressMap; } - std::map & + std::map > & getGlobalAddressReverseMap(const MutexGuard &) { return GlobalAddressReverseMap; } -}; + /// \brief Erase an entry from the mapping table. + /// + /// \returns The address that \p ToUnmap was happed to. + void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); +}; +/// \brief Abstract interface for implementation execution of LLVM modules, +/// designed to support both interpreter and just-in-time (JIT) compiler +/// implementations. class ExecutionEngine { - const TargetData *TD; - ExecutionEngineState state; - bool LazyCompilationDisabled; + /// The state object holding the global address mapping, which must be + /// accessed synchronously. + // + // FIXME: There is no particular need the entire map needs to be + // synchronized. Wouldn't a reader-writer design be better here? + ExecutionEngineState EEState; + + /// The target data for the platform for which execution is being performed. + const DataLayout *DL; + + /// Whether lazy JIT compilation is enabled. + bool CompilingLazily; + + /// Whether JIT compilation of external global variables is allowed. bool GVCompilationDisabled; + + /// Whether the JIT should perform lookups of external symbols (e.g., + /// using dlsym). bool SymbolSearchingDisabled; - bool DlsymStubsEnabled; + + friend class EngineBuilder; // To allow access to JITCtor and InterpCtor. 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; - } - + /// The list of Modules that we are JIT'ing from. We use a SmallVector to + /// optimize for the case where there is only one module. + SmallVector Modules; + + void setDataLayout(const DataLayout *Val) { DL = Val; } + /// getMemoryforGV - Allocate memory for a global variable. - virtual char* getMemoryForGV(const GlobalVariable* GV); + 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*, - unsigned OptLevel); - static EECtorFn JITCtor, InterpCtor; + // libraries, the execution engine implementations set these functions to ctor + // pointers at startup time if they are linked in. + static ExecutionEngine *(*JITCtor)( + Module *M, + std::string *ErrorStr, + JITMemoryManager *JMM, + bool GVsWithCode, + TargetMachine *TM); + static ExecutionEngine *(*MCJITCtor)( + Module *M, + std::string *ErrorStr, + RTDyldMemoryManager *MCJMM, + bool GVsWithCode, + TargetMachine *TM); + static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); /// 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; + /// pointer is invoked to create it. If this returns null, the JIT will + /// abort. + void *(*LazyFunctionCreator)(const std::string &); public: - /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and + /// lock - This lock protects the ExecutionEngine, MCJIT, 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 + sys::Mutex lock; //===--------------------------------------------------------------------===// // ExecutionEngine Startup @@ -108,73 +169,156 @@ public: 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, - unsigned OptLevel = 3); - /// 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); + /// + /// \param GVsWithCode - Allocating globals with code breaks + /// freeMachineCodeForFunction and is probably unsafe and bad for performance. + /// However, we have clients who depend on this behavior, so we must support + /// it. Eventually, when we're willing to break some backwards compatibility, + /// this flag should be flipped to false, so that by default + /// freeMachineCodeForFunction works. + static ExecutionEngine *create(Module *M, + bool ForceInterpreter = false, + std::string *ErrorStr = nullptr, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true); /// 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, - unsigned OptLevel = 3); - - - - /// 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); + /// of the Module and JITMemoryManager if successful. + /// + /// Clients should make sure to initialize targets prior to calling this + /// function. + static ExecutionEngine *createJIT(Module *M, + std::string *ErrorStr = nullptr, + JITMemoryManager *JMM = nullptr, + CodeGenOpt::Level OptLevel = + CodeGenOpt::Default, + bool GVsWithCode = true, + Reloc::Model RM = Reloc::Default, + CodeModel::Model CMM = + CodeModel::JITDefault); + + /// addModule - Add a Module to the list of modules that we can JIT from. + /// Note that this takes ownership of the Module: when the ExecutionEngine is + /// destroyed, it destroys the Module as well. + virtual void addModule(Module *M) { + Modules.push_back(M); + } + + /// addObjectFile - Add an ObjectFile to the execution engine. + /// + /// This method is only supported by MCJIT. MCJIT will immediately load the + /// object into memory and adds its symbols to the list used to resolve + /// external symbols while preparing other objects for execution. + /// + /// Objects added using this function will not be made executable until + /// needed by another object. + /// + /// MCJIT will take ownership of the ObjectFile. + virtual void addObjectFile(object::ObjectFile *O) { + llvm_unreachable( + "ExecutionEngine subclass doesn't implement addObjectFile."); + } + + /// addArchive - Add an Archive to the execution engine. + /// + /// This method is only supported by MCJIT. MCJIT will use the archive to + /// resolve external symbols in objects it is loading. If a symbol is found + /// in the Archive the contained object file will be extracted (in memory) + /// and loaded for possible execution. + /// + /// MCJIT will take ownership of the Archive. + virtual void addArchive(object::Archive *A) { + llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive."); + } + + //===--------------------------------------------------------------------===// + + const DataLayout *getDataLayout() const { return DL; } + + /// removeModule - Remove a Module from the list of modules. Returns true if + /// M is found. + virtual bool removeModule(Module *M); /// 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); - + virtual 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; + /// getPointerToNamedFunction - This method returns the address of the + /// specified function by using the dlsym function call. As such it is only + /// useful for resolving library symbols, not code generated symbols. + /// + /// If AbortOnFailure is false and no function with the given name is + /// found, this function silently returns a null pointer. Otherwise, + /// it prints a message to stderr and aborts. + /// + /// This function is deprecated for the MCJIT execution engine. + /// + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// again, if possible. + /// + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) = 0; + + /// mapSectionAddress - map a section to its target address space value. + /// Map the address of a JIT section as returned from the memory manager + /// to the address in the target process as the running code will see it. + /// This is the address which will be used for relocation resolution. + virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { + llvm_unreachable("Re-mapping of section addresses not supported with this " + "EE!"); + } + + /// generateCodeForModule - Run code generationen for the specified module and + /// load it into memory. + /// + /// When this function has completed, all code and data for the specified + /// module, and any module on which this module depends, will be generated + /// and loaded into memory, but relocations will not yet have been applied + /// and all memory will be readable and writable but not executable. + /// + /// This function is primarily useful when generating code for an external + /// target, allowing the client an opportunity to remap section addresses + /// before relocations are applied. Clients that intend to execute code + /// locally can use the getFunctionAddress call, which will generate code + /// and apply final preparations all in one step. + /// + /// This method has no effect for the legacy JIT engine or the interpeter. + virtual void generateCodeForModule(Module *M) {} + + /// finalizeObject - ensure the module is fully processed and is usable. + /// + /// It is the user-level function for completing the process of making the + /// object usable for execution. It should be called after sections within an + /// object have been relocated using mapSectionAddress. When this method is + /// called the MCJIT execution engine will reapply relocations for a loaded + /// object. This method has no effect for the legacy JIT engine or the + /// interpeter. + virtual void finalizeObject() {} + /// 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); + /// the static constructors or destructors for a program. + /// + /// \param isDtors - Run the destructors instead of constructors. + virtual 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. + /// the static constructors or destructors for a particular module. + /// + /// \param isDtors - Run the destructors instead of constructors. 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. @@ -186,99 +330,179 @@ public: /// 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. + /// existing data in memory. Mappings are automatically removed when their + /// GlobalValue is destroyed. 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 + + /// clearAllGlobalMappings - Clear all global mappings and start over again, + /// for use in dynamic compilation scenarios 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. /// + /// This function is deprecated for the MCJIT execution engine. It doesn't + /// seem to be needed in that case, but an equivalent can be added if it is. 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. + /// value. This may involve code generation if it's a function. /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. 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. + /// pointer should look like. When F is destroyed, the ExecutionEngine will + /// remove its global mapping and free any machine code. Be sure no threads + /// are running inside F when that happens. /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; + /// getPointerToBasicBlock - The different EE's represent basic blocks in + /// different ways. Return the representation for a blockaddress of the + /// specified block. + /// + /// This function will not be implemented for the MCJIT execution engine. + virtual void *getPointerToBasicBlock(BasicBlock *BB) = 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. + /// a stub to implement lazy compilation if available. See + /// getPointerToFunction for the requirements on destroying F. /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getFunctionAddress instead. virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. return getPointerToFunction(F); } + /// getGlobalValueAddress - Return the address of the specified global + /// value. This may involve code generation. + /// + /// This function should not be called with the JIT or interpreter engines. + virtual uint64_t getGlobalValueAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToGlobal instead. + return 0; + } + + /// getFunctionAddress - Return the address of the specified function. + /// This may involve code generation. + virtual uint64_t getFunctionAddress(const std::string &Name) { + // Default implementation for JIT and interpreter. MCJIT will override this. + // JIT and interpreter clients should use getPointerToFunction instead. + return 0; + } + + // The JIT overrides a version that actually does this. + virtual void runJITOnFunction(Function *, MachineCodeInfo * = nullptr) { } + /// getGlobalValueAtAddress - Return the LLVM global value object that starts /// at the specified address. /// const GlobalValue *getGlobalValueAtAddress(void *Addr); - + /// StoreValueToMemory - Stores the data in Val of type Ty at address Ptr. + /// Ptr is the address of the memory at which to store Val, cast to + /// GenericValue *. It is not a pointer to a GenericValue containing the + /// address at which to store Val. void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, - const Type *Ty); + 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(). - /// + /// 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. + /// Emitter. + /// + /// This function is deprecated for the MCJIT execution engine. Use + /// getGlobalValueAddress instead. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { - return getPointerToGlobal((GlobalValue*)GV); + return getPointerToGlobal((const GlobalValue *)GV); } - - /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation - /// is ever attempted. + + /// Registers a listener to be called back on various events within + /// the JIT. See JITEventListener.h for more details. Does not + /// take ownership of the argument. The argument may be NULL, in + /// which case these functions do nothing. + virtual void RegisterJITEventListener(JITEventListener *) {} + virtual void UnregisterJITEventListener(JITEventListener *) {} + + /// Sets the pre-compiled object cache. The ownership of the ObjectCache is + /// not changed. Supported by MCJIT but not JIT. + virtual void setObjectCache(ObjectCache *) { + llvm_unreachable("No support for an object cache"); + } + + /// setProcessAllSections (MCJIT Only): By default, only sections that are + /// "required for execution" are passed to the RTDyldMemoryManager, and other + /// sections are discarded. Passing 'true' to this method will cause + /// RuntimeDyld to pass all sections to its RTDyldMemoryManager regardless + /// of whether they are "required to execute" in the usual sense. + /// + /// Rationale: Some MCJIT clients want to be able to inspect metadata + /// sections (e.g. Dwarf, Stack-maps) to enable functionality or analyze + /// performance. Passing these sections to the memory manager allows the + /// client to make policy about the relevant sections, rather than having + /// MCJIT do it. + virtual void setProcessAllSections(bool ProcessAllSections) { + llvm_unreachable("No support for ProcessAllSections option"); + } + + /// Return the target machine (if available). + virtual TargetMachine *getTargetMachine() { return nullptr; } + + /// DisableLazyCompilation - When lazy compilation is off (the default), the + /// JIT will eagerly compile every function reachable from the argument to + /// getPointerToFunction. If lazy compilation is turned on, the JIT will only + /// compile the one function and emit stubs to compile the rest when they're + /// first called. If lazy compilation is turned off again while some lazy + /// stubs are still around, and one of those stubs is called, the program will + /// abort. + /// + /// In order to safely compile lazily in a threaded program, the user must + /// ensure that 1) only one thread at a time can call any particular lazy + /// stub, and 2) any thread modifying LLVM IR must hold the JIT's lock + /// (ExecutionEngine::lock) or otherwise ensure that no other thread calls a + /// lazy stub. See http://llvm.org/PR5184 for details. void DisableLazyCompilation(bool Disabled = true) { - LazyCompilationDisabled = Disabled; + CompilingLazily = !Disabled; } + bool isCompilingLazily() const { + return CompilingLazily; + } + // Deprecated in favor of isCompilingLazily (to reduce double-negatives). + // Remove this in LLVM 2.8. bool isLazyCompilationDisabled() const { - return LazyCompilationDisabled; + return !CompilingLazily; } /// DisableGVCompilation - If called, the JIT will abort if it's asked to @@ -300,50 +524,203 @@ public: 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); + explicit ExecutionEngine(Module *M); 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); + void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, + Type *Ty); +}; + +namespace EngineKind { + // These are actually bitmasks that get or-ed together. + enum Kind { + JIT = 0x1, + Interpreter = 0x2 + }; + const static Kind Either = (Kind)(JIT | Interpreter); +} + +/// EngineBuilder - Builder class for ExecutionEngines. Use this by +/// stack-allocating a builder, chaining the various set* methods, and +/// terminating it with a .create() call. +class EngineBuilder { +private: + Module *M; + EngineKind::Kind WhichEngine; + std::string *ErrorStr; + CodeGenOpt::Level OptLevel; + RTDyldMemoryManager *MCJMM; + JITMemoryManager *JMM; + bool AllocateGVsWithCode; + TargetOptions Options; + Reloc::Model RelocModel; + CodeModel::Model CMModel; + std::string MArch; + std::string MCPU; + SmallVector MAttrs; + bool UseMCJIT; + + /// InitEngine - Does the common initialization of default options. + void InitEngine() { + WhichEngine = EngineKind::Either; + ErrorStr = nullptr; + OptLevel = CodeGenOpt::Default; + MCJMM = nullptr; + JMM = nullptr; + Options = TargetOptions(); + AllocateGVsWithCode = false; + RelocModel = Reloc::Default; + CMModel = CodeModel::JITDefault; + UseMCJIT = false; + } + +public: + /// EngineBuilder - Constructor for EngineBuilder. If create() is called and + /// is successful, the created engine takes ownership of the module. + EngineBuilder(Module *m) : M(m) { + InitEngine(); + } + + /// setEngineKind - Controls whether the user wants the interpreter, the JIT, + /// or whichever engine works. This option defaults to EngineKind::Either. + EngineBuilder &setEngineKind(EngineKind::Kind w) { + WhichEngine = w; + return *this; + } + + /// setMCJITMemoryManager - Sets the MCJIT memory manager to use. This allows + /// clients to customize their memory allocation policies for the MCJIT. This + /// is only appropriate for the MCJIT; setting this and configuring the builder + /// to create anything other than MCJIT will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. Using this option nullifies + /// the setJITMemoryManager() option. + EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { + MCJMM = mcjmm; + JMM = nullptr; + return *this; + } + + /// setJITMemoryManager - Sets the JIT memory manager to use. This allows + /// clients to customize their memory allocation policies. This is only + /// appropriate for either JIT or MCJIT; setting this and configuring the + /// builder to create an interpreter will cause a runtime error. If create() + /// is called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. This option overrides + /// setMCJITMemoryManager() as well. + EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + MCJMM = nullptr; + JMM = jmm; + return *this; + } + + /// setErrorStr - Set the error string to write to on error. This option + /// defaults to NULL. + EngineBuilder &setErrorStr(std::string *e) { + ErrorStr = e; + return *this; + } + + /// setOptLevel - Set the optimization level for the JIT. This option + /// defaults to CodeGenOpt::Default. + EngineBuilder &setOptLevel(CodeGenOpt::Level l) { + OptLevel = l; + return *this; + } + + /// setTargetOptions - Set the target options that the ExecutionEngine + /// target is using. Defaults to TargetOptions(). + EngineBuilder &setTargetOptions(const TargetOptions &Opts) { + Options = Opts; + return *this; + } + + /// setRelocationModel - Set the relocation model that the ExecutionEngine + /// target is using. Defaults to target specific default "Reloc::Default". + EngineBuilder &setRelocationModel(Reloc::Model RM) { + RelocModel = RM; + return *this; + } + + /// setCodeModel - Set the CodeModel that the ExecutionEngine target + /// data is using. Defaults to target specific default + /// "CodeModel::JITDefault". + EngineBuilder &setCodeModel(CodeModel::Model M) { + CMModel = M; + return *this; + } + + /// setAllocateGVsWithCode - Sets whether global values should be allocated + /// into the same buffer as code. For most applications this should be set + /// to false. Allocating globals with code breaks freeMachineCodeForFunction + /// and is probably unsafe and bad for performance. However, we have clients + /// who depend on this behavior, so we must support it. This option defaults + /// to false so that users of the new API can safely use the new memory + /// manager and free machine code. + EngineBuilder &setAllocateGVsWithCode(bool a) { + AllocateGVsWithCode = a; + return *this; + } + + /// setMArch - Override the architecture set by the Module's triple. + EngineBuilder &setMArch(StringRef march) { + MArch.assign(march.begin(), march.end()); + return *this; + } + + /// setMCPU - Target a specific cpu type. + EngineBuilder &setMCPU(StringRef mcpu) { + MCPU.assign(mcpu.begin(), mcpu.end()); + return *this; + } + + /// setUseMCJIT - Set whether the MC-JIT implementation should be used + /// (experimental). + EngineBuilder &setUseMCJIT(bool Value) { + UseMCJIT = Value; + return *this; + } + + /// setMAttrs - Set cpu-specific attributes. + template + EngineBuilder &setMAttrs(const StringSequence &mattrs) { + MAttrs.clear(); + MAttrs.append(mattrs.begin(), mattrs.end()); + return *this; + } + + TargetMachine *selectTarget(); + + /// selectTarget - Pick a target either via -march or by guessing the native + /// arch. Add any CPU features specified via -mcpu or -mattr. + TargetMachine *selectTarget(const Triple &TargetTriple, + StringRef MArch, + StringRef MCPU, + const SmallVectorImpl& MAttrs); + + ExecutionEngine *create() { + return create(selectTarget()); + } + + ExecutionEngine *create(TargetMachine *TM); }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) + } // End llvm namespace #endif