diff options
Diffstat (limited to 'include/llvm/ExecutionEngine')
-rw-r--r-- | include/llvm/ExecutionEngine/ExecutionEngine.h | 197 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/JITEventListener.h | 17 | ||||
-rw-r--r-- | include/llvm/ExecutionEngine/JITMemoryManager.h | 84 |
3 files changed, 256 insertions, 42 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 613adb5..b9da0fc 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -19,6 +19,7 @@ #include <map> #include <string> #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/ValueHandle.h" #include "llvm/System/Mutex.h" #include "llvm/Target/TargetMachine.h" @@ -26,6 +27,7 @@ namespace llvm { struct GenericValue; class Constant; +class ExecutionEngine; class Function; class GlobalVariable; class GlobalValue; @@ -39,38 +41,66 @@ class TargetData; class Type; class ExecutionEngineState { +public: + class MapUpdatingCVH : public CallbackVH { + ExecutionEngineState &EES; + + public: + MapUpdatingCVH(ExecutionEngineState &EES, const GlobalValue *GV); + + operator const GlobalValue*() const { + return cast<GlobalValue>(getValPtr()); + } + + virtual void deleted(); + virtual void allUsesReplacedWith(Value *new_value); + }; + private: + ExecutionEngine &EE; + /// GlobalAddressMap - A mapping between LLVM global values and their /// actualized version... - std::map<const GlobalValue*, void *> GlobalAddressMap; + std::map<MapUpdatingCVH, void *> 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<void *, const GlobalValue*> GlobalAddressReverseMap; + std::map<void *, AssertingVH<const GlobalValue> > GlobalAddressReverseMap; public: - std::map<const GlobalValue*, void *> & + ExecutionEngineState(ExecutionEngine &EE) : EE(EE) {} + + MapUpdatingCVH getVH(const GlobalValue *GV) { + return MapUpdatingCVH(*this, GV); + } + + std::map<MapUpdatingCVH, void *> & getGlobalAddressMap(const MutexGuard &) { return GlobalAddressMap; } - std::map<void*, const GlobalValue*> & + std::map<void*, AssertingVH<const GlobalValue> > & getGlobalAddressReverseMap(const MutexGuard &) { return GlobalAddressReverseMap; } + + // Returns the address ToUnmap was mapped to. + void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); }; class ExecutionEngine { const TargetData *TD; - ExecutionEngineState state; + ExecutionEngineState EEState; bool LazyCompilationDisabled; bool GVCompilationDisabled; 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. @@ -86,9 +116,13 @@ protected: // 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*, - CodeGenOpt::Level OptLevel); - static EECtorFn JITCtor, InterpCtor; + static ExecutionEngine *(*JITCtor)(ModuleProvider *MP, + std::string *ErrorStr, + JITMemoryManager *JMM, + CodeGenOpt::Level OptLevel, + bool GVsWithCode); + static ExecutionEngine *(*InterpCtor)(ModuleProvider *MP, + 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. @@ -118,8 +152,18 @@ public: bool ForceInterpreter = false, std::string *ErrorStr = 0, CodeGenOpt::Level OptLevel = - CodeGenOpt::Default); - + CodeGenOpt::Default, + // 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 compatability, this flag + // should be flipped to false, so that by + // default freeMachineCodeForFunction works. + bool GVsWithCode = true); + /// create - This is the factory method for creating an execution engine which /// is appropriate for the current machine. This takes ownership of the /// module. @@ -128,11 +172,15 @@ public: /// 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. + /// + /// Clients should make sure to initialize targets prior to calling this + /// function. static ExecutionEngine *createJIT(ModuleProvider *MP, std::string *ErrorStr = 0, JITMemoryManager *JMM = 0, CodeGenOpt::Level OptLevel = - CodeGenOpt::Default); + CodeGenOpt::Default, + bool GVsWithCode = true); /// addModuleProvider - Add a ModuleProvider to the list of modules that we /// can JIT from. Note that this takes ownership of the ModuleProvider: when @@ -189,8 +237,8 @@ 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 @@ -214,29 +262,23 @@ public: 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. /// 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 but will not yet free its machine code. Call + /// freeMachineCodeForFunction(F) explicitly to do that. Note that global + /// optimizations can destroy Functions without notifying the ExecutionEngine. /// 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. + /// a stub to implement lazy compilation if available. See + /// getPointerToFunction for the requirements on destroying F. /// virtual void *getPointerToFunctionOrStub(Function *F) { // Default implementation, just codegen the function. @@ -272,8 +314,7 @@ public: /// 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. virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { return getPointerToGlobal((GlobalValue*)GV); } @@ -282,8 +323,8 @@ public: /// 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 *L) {} - virtual void UnregisterJITEventListener(JITEventListener *L) {} + virtual void RegisterJITEventListener(JITEventListener *) {} + virtual void UnregisterJITEventListener(JITEventListener *) {} /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation /// is ever attempted. @@ -357,6 +398,102 @@ protected: const 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: + ModuleProvider *MP; + EngineKind::Kind WhichEngine; + std::string *ErrorStr; + CodeGenOpt::Level OptLevel; + JITMemoryManager *JMM; + bool AllocateGVsWithCode; + + /// InitEngine - Does the common initialization of default options. + /// + void InitEngine() { + WhichEngine = EngineKind::Either; + ErrorStr = NULL; + OptLevel = CodeGenOpt::Default; + JMM = NULL; + AllocateGVsWithCode = false; + } + + public: + /// EngineBuilder - Constructor for EngineBuilder. If create() is called and + /// is successful, the created engine takes ownership of the module + /// provider. + EngineBuilder(ModuleProvider *mp) : MP(mp) { + InitEngine(); + } + + /// EngineBuilder - Overloaded constructor that automatically creates an + /// ExistingModuleProvider for an existing module. + EngineBuilder(Module *m); + + /// 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; + } + + /// setJITMemoryManager - Sets the memory manager to use. This allows + /// clients to customize their memory allocation policies. If create() is + /// called and is successful, the created engine takes ownership of the + /// memory manager. This option defaults to NULL. + EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { + 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; + } + + /// 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; + } + + ExecutionEngine *create(); + +}; + +inline bool operator<(const ExecutionEngineState::MapUpdatingCVH& lhs, + const ExecutionEngineState::MapUpdatingCVH& rhs) { + return static_cast<const GlobalValue*>(lhs) < + static_cast<const GlobalValue*>(rhs); +} + } // End llvm namespace #endif diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index dd76f26..8d3a1d7 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -16,13 +16,28 @@ #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/DebugLoc.h" + +#include <vector> namespace llvm { class Function; +class MachineFunction; /// Empty for now, but this object will contain all details about the /// generated machine code that a Listener might care about. struct JITEvent_EmittedFunctionDetails { + const MachineFunction *MF; + + struct LineStart { + // The address at which the current line changes. + uintptr_t Address; + // The new location information. These can be translated to + // DebugLocTuples using MF->getDebugLocTuple(). + DebugLoc Loc; + }; + // This holds line boundary information sorted by address. + std::vector<LineStart> LineStarts; }; /// JITEventListener - This interface is used by the JIT to notify clients about @@ -52,7 +67,9 @@ public: virtual void NotifyFreeingMachineCode(const Function &F, void *OldPtr) {} }; +// These return NULL if support isn't available. JITEventListener *createMacOSJITEventListener(); +JITEventListener *createOProfileJITEventListener(); } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h index 688a162..21dee55 100644 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ b/include/llvm/ExecutionEngine/JITMemoryManager.h @@ -15,9 +15,12 @@ #define LLVM_EXECUTION_ENGINE_JIT_MEMMANAGER_H #include "llvm/Support/DataTypes.h" +#include <string> namespace llvm { + class Function; + class GlobalValue; /// JITMemoryManager - This interface is used by the JIT to allocate and manage /// memory for the code generated by the JIT. This can be reimplemented by @@ -28,6 +31,7 @@ protected: bool HasGOT; bool SizeRequired; public: + JITMemoryManager() : HasGOT(false), SizeRequired(false) {} virtual ~JITMemoryManager(); @@ -37,11 +41,16 @@ public: /// setMemoryWritable - When code generation is in progress, /// the code pages may need permissions changed. - virtual void setMemoryWritable(void) = 0; + virtual void setMemoryWritable() = 0; /// setMemoryExecutable - When code generation is done and we're ready to /// start execution, the code pages may need permissions changed. - virtual void setMemoryExecutable(void) = 0; + virtual void setMemoryExecutable() = 0; + + /// setPoisonMemory - Setting this flag to true makes the memory manager + /// garbage values over freed memory. This is useful for testing and + /// debugging, and is be turned on by default in debug mode. + virtual void setPoisonMemory(bool poison) = 0; //===--------------------------------------------------------------------===// // Global Offset Table Management @@ -82,16 +91,19 @@ public: //===--------------------------------------------------------------------===// // Main Allocation Functions //===--------------------------------------------------------------------===// - - /// startFunctionBody - When we start JITing a function, the JIT calls this + + /// startFunctionBody - When we start JITing a function, the JIT calls this /// method to allocate a block of free RWX memory, which returns a pointer to - /// it. The JIT doesn't know ahead of time how much space it will need to - /// emit the function, so it doesn't pass in the size. Instead, this method - /// is required to pass back a "valid size". The JIT will be careful to not - /// write more than the returned ActualSize bytes of memory. - virtual uint8_t *startFunctionBody(const Function *F, + /// it. If the JIT wants to request a block of memory of at least a certain + /// size, it passes that value as ActualSize, and this method returns a block + /// with at least that much space. If the JIT doesn't know ahead of time how + /// much space it will need to emit the function, it passes 0 for the + /// ActualSize. In either case, this method is required to pass back the size + /// of the allocated block through ActualSize. The JIT will be careful to + /// not write more than the returned ActualSize bytes of memory. + virtual uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) = 0; - + /// allocateStub - This method is called by the JIT to allocate space for a /// function stub (used to handle limited branch displacements) while it is /// JIT compiling a function. For example, if foo calls bar, and if bar @@ -112,9 +124,14 @@ public: virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, uint8_t *FunctionEnd) = 0; - /// allocateSpace - Allocate a memory block of the given size. + /// allocateSpace - Allocate a memory block of the given size. This method + /// cannot be called between calls to startFunctionBody and endFunctionBody. virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; - + + /// allocateGlobal - Allocate memory for a global. + /// + virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; + /// deallocateMemForFunction - Free JIT memory for the specified function. /// This is never called when the JIT is currently emitting a function. virtual void deallocateMemForFunction(const Function *F) = 0; @@ -128,6 +145,49 @@ public: /// the exception table. virtual void endExceptionTable(const Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister) = 0; + + /// CheckInvariants - For testing only. Return true if all internal + /// invariants are preserved, or return false and set ErrorStr to a helpful + /// error message. + virtual bool CheckInvariants(std::string &ErrorStr) { + return true; + } + + /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultCodeSlabSize() { + return 0; + } + + /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultDataSlabSize() { + return 0; + } + + /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize + /// from DefaultJITMemoryManager. + virtual size_t GetDefaultStubSlabSize() { + return 0; + } + + /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for code. + virtual unsigned GetNumCodeSlabs() { + return 0; + } + + /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for data. + virtual unsigned GetNumDataSlabs() { + return 0; + } + + /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks + /// allocated for function stubs. + virtual unsigned GetNumStubSlabs() { + return 0; + } }; } // end namespace llvm. |