diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:17:27 +0000 |
commit | 67c32a98315f785a9ec9d531c1f571a0196c7463 (patch) | |
tree | 4abb9cbeecc7901726dd0b4a37369596c852e9ef /lib/ExecutionEngine/Interpreter | |
parent | 9f61947910e6ab40de38e6b4034751ef1513200f (diff) |
Diffstat (limited to 'lib/ExecutionEngine/Interpreter')
-rw-r--r-- | lib/ExecutionEngine/Interpreter/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp | 35 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.cpp | 13 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Interpreter.h | 84 |
4 files changed, 69 insertions, 65 deletions
diff --git a/lib/ExecutionEngine/Interpreter/CMakeLists.txt b/lib/ExecutionEngine/Interpreter/CMakeLists.txt index 74df8f0f37a5..1aac3ac7fdc9 100644 --- a/lib/ExecutionEngine/Interpreter/CMakeLists.txt +++ b/lib/ExecutionEngine/Interpreter/CMakeLists.txt @@ -13,7 +13,7 @@ add_llvm_library(LLVMInterpreter ) if( LLVM_ENABLE_FFI ) - target_link_libraries( LLVMInterpreter ${FFI_LIBRARY_PATH} ) + target_link_libraries( LLVMInterpreter ${cmake_2_8_12_PRIVATE} ${FFI_LIBRARY_PATH} ) endif() add_dependencies(LLVMInterpreter intrinsics_gen) diff --git a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp index 671bbeea8d0d..b0221019b559 100644 --- a/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp +++ b/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp @@ -28,6 +28,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/UniqueLock.h" #include <cmath> #include <csignal> #include <cstdio> @@ -51,7 +52,7 @@ static ManagedStatic<sys::Mutex> FunctionsLock; typedef GenericValue (*ExFunc)(FunctionType *, const std::vector<GenericValue> &); static ManagedStatic<std::map<const Function *, ExFunc> > ExportedFunctions; -static std::map<std::string, ExFunc> FuncNames; +static ManagedStatic<std::map<std::string, ExFunc> > FuncNames; #ifdef USE_LIBFFI typedef void (*RawFunc)(); @@ -97,9 +98,9 @@ static ExFunc lookupFunction(const Function *F) { ExtName += "_" + F->getName().str(); sys::ScopedLock Writer(*FunctionsLock); - ExFunc FnPtr = FuncNames[ExtName]; + ExFunc FnPtr = (*FuncNames)[ExtName]; if (!FnPtr) - FnPtr = FuncNames["lle_X_" + F->getName().str()]; + FnPtr = (*FuncNames)["lle_X_" + F->getName().str()]; if (!FnPtr) // Try calling a generic function... if it exists... FnPtr = (ExFunc)(intptr_t) sys::DynamicLibrary::SearchForAddressOfSymbol("lle_X_" + @@ -248,14 +249,14 @@ GenericValue Interpreter::callExternalFunction(Function *F, const std::vector<GenericValue> &ArgVals) { TheInterpreter = this; - FunctionsLock->acquire(); + unique_lock<sys::Mutex> Guard(*FunctionsLock); // Do a lookup to see if the function is in our cache... this should just be a // deferred annotation! std::map<const Function *, ExFunc>::iterator FI = ExportedFunctions->find(F); if (ExFunc Fn = (FI == ExportedFunctions->end()) ? lookupFunction(F) : FI->second) { - FunctionsLock->release(); + Guard.unlock(); return Fn(F->getFunctionType(), ArgVals); } @@ -273,7 +274,7 @@ GenericValue Interpreter::callExternalFunction(Function *F, RawFn = RF->second; } - FunctionsLock->release(); + Guard.unlock(); GenericValue Result; if (RawFn != 0 && ffiInvoke(RawFn, F, ArgVals, getDataLayout(), Result)) @@ -497,15 +498,15 @@ static GenericValue lle_X_memcpy(FunctionType *FT, void Interpreter::initializeExternalFunctions() { sys::ScopedLock Writer(*FunctionsLock); - FuncNames["lle_X_atexit"] = lle_X_atexit; - FuncNames["lle_X_exit"] = lle_X_exit; - FuncNames["lle_X_abort"] = lle_X_abort; - - FuncNames["lle_X_printf"] = lle_X_printf; - FuncNames["lle_X_sprintf"] = lle_X_sprintf; - FuncNames["lle_X_sscanf"] = lle_X_sscanf; - FuncNames["lle_X_scanf"] = lle_X_scanf; - FuncNames["lle_X_fprintf"] = lle_X_fprintf; - FuncNames["lle_X_memset"] = lle_X_memset; - FuncNames["lle_X_memcpy"] = lle_X_memcpy; + (*FuncNames)["lle_X_atexit"] = lle_X_atexit; + (*FuncNames)["lle_X_exit"] = lle_X_exit; + (*FuncNames)["lle_X_abort"] = lle_X_abort; + + (*FuncNames)["lle_X_printf"] = lle_X_printf; + (*FuncNames)["lle_X_sprintf"] = lle_X_sprintf; + (*FuncNames)["lle_X_sscanf"] = lle_X_sscanf; + (*FuncNames)["lle_X_scanf"] = lle_X_scanf; + (*FuncNames)["lle_X_fprintf"] = lle_X_fprintf; + (*FuncNames)["lle_X_memset"] = lle_X_memset; + (*FuncNames)["lle_X_memcpy"] = lle_X_memcpy; } diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/lib/ExecutionEngine/Interpreter/Interpreter.cpp index 814efcc27fcb..8562981b629a 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.cpp +++ b/lib/ExecutionEngine/Interpreter/Interpreter.cpp @@ -30,9 +30,10 @@ static struct RegisterInterp { extern "C" void LLVMLinkInInterpreter() { } -/// create - Create a new interpreter object. This can never fail. +/// Create a new interpreter object. /// -ExecutionEngine *Interpreter::create(Module *M, std::string* ErrStr) { +ExecutionEngine *Interpreter::create(std::unique_ptr<Module> M, + std::string *ErrStr) { // Tell this Module to materialize everything and release the GVMaterializer. if (std::error_code EC = M->materializeAllPermanently()) { if (ErrStr) @@ -41,15 +42,15 @@ ExecutionEngine *Interpreter::create(Module *M, std::string* ErrStr) { return nullptr; } - return new Interpreter(M); + return new Interpreter(std::move(M)); } //===----------------------------------------------------------------------===// // Interpreter ctor - Initialize stuff // -Interpreter::Interpreter(Module *M) - : ExecutionEngine(M), TD(M) { - +Interpreter::Interpreter(std::unique_ptr<Module> M) + : ExecutionEngine(std::move(M)), TD(Modules.back().get()) { + memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); setDataLayout(&TD); // Initialize the "backend" diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h index 2145cde05fbf..2be9c5979d80 100644 --- a/lib/ExecutionEngine/Interpreter/Interpreter.h +++ b/lib/ExecutionEngine/Interpreter/Interpreter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLI_INTERPRETER_H -#define LLI_INTERPRETER_H +#ifndef LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H +#define LLVM_LIB_EXECUTIONENGINE_INTERPRETER_INTERPRETER_H #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" @@ -37,29 +37,24 @@ typedef generic_gep_type_iterator<User::const_op_iterator> gep_type_iterator; // stack, which causes the dtor to be run, which frees all the alloca'd memory. // class AllocaHolder { - friend class AllocaHolderHandle; - std::vector<void*> Allocations; - unsigned RefCnt; + std::vector<void *> Allocations; + public: - AllocaHolder() : RefCnt(0) {} - void add(void *mem) { Allocations.push_back(mem); } - ~AllocaHolder() { - for (unsigned i = 0; i < Allocations.size(); ++i) - free(Allocations[i]); + AllocaHolder() {} + + // Make this type move-only. Define explicit move special members for MSVC. + AllocaHolder(AllocaHolder &&RHS) : Allocations(std::move(RHS.Allocations)) {} + AllocaHolder &operator=(AllocaHolder &&RHS) { + Allocations = std::move(RHS.Allocations); + return *this; } -}; -// AllocaHolderHandle gives AllocaHolder value semantics so we can stick it into -// a vector... -// -class AllocaHolderHandle { - AllocaHolder *H; -public: - AllocaHolderHandle() : H(new AllocaHolder()) { H->RefCnt++; } - AllocaHolderHandle(const AllocaHolderHandle &AH) : H(AH.H) { H->RefCnt++; } - ~AllocaHolderHandle() { if (--H->RefCnt == 0) delete H; } + ~AllocaHolder() { + for (void *Allocation : Allocations) + free(Allocation); + } - void add(void *mem) { H->add(mem); } + void add(void *Mem) { Allocations.push_back(Mem); } }; typedef std::vector<GenericValue> ValuePlaneTy; @@ -71,11 +66,29 @@ struct ExecutionContext { Function *CurFunction;// The currently executing function BasicBlock *CurBB; // The currently executing BB BasicBlock::iterator CurInst; // The next instruction to execute - std::map<Value *, GenericValue> Values; // LLVM values used in this invocation - std::vector<GenericValue> VarArgs; // Values passed through an ellipsis CallSite Caller; // Holds the call that called subframes. // NULL if main func or debugger invoked fn - AllocaHolderHandle Allocas; // Track memory allocated by alloca + std::map<Value *, GenericValue> Values; // LLVM values used in this invocation + std::vector<GenericValue> VarArgs; // Values passed through an ellipsis + AllocaHolder Allocas; // Track memory allocated by alloca + + ExecutionContext() : CurFunction(nullptr), CurBB(nullptr), CurInst(nullptr) {} + + ExecutionContext(ExecutionContext &&O) + : CurFunction(O.CurFunction), CurBB(O.CurBB), CurInst(O.CurInst), + Caller(O.Caller), Values(std::move(O.Values)), + VarArgs(std::move(O.VarArgs)), Allocas(std::move(O.Allocas)) {} + + ExecutionContext &operator=(ExecutionContext &&O) { + CurFunction = O.CurFunction; + CurBB = O.CurBB; + CurInst = O.CurInst; + Caller = O.Caller; + Values = std::move(O.Values); + VarArgs = std::move(O.VarArgs); + Allocas = std::move(O.Allocas); + return *this; + } }; // Interpreter - This class represents the entirety of the interpreter. @@ -94,7 +107,7 @@ class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { std::vector<Function*> AtExitHandlers; public: - explicit Interpreter(Module *M); + explicit Interpreter(std::unique_ptr<Module> M); ~Interpreter(); /// runAtExitHandlers - Run any functions registered by the program's calls to @@ -105,33 +118,23 @@ public: static void Register() { InterpCtor = create; } - - /// create - Create an interpreter ExecutionEngine. This can never fail. + + /// Create an interpreter ExecutionEngine. /// - static ExecutionEngine *create(Module *M, std::string *ErrorStr = nullptr); + static ExecutionEngine *create(std::unique_ptr<Module> M, + std::string *ErrorStr = nullptr); /// run - Start execution with the specified function and arguments. /// GenericValue runFunction(Function *F, const std::vector<GenericValue> &ArgValues) override; - void *getPointerToNamedFunction(const std::string &Name, + void *getPointerToNamedFunction(StringRef Name, bool AbortOnFailure = true) override { // FIXME: not implemented. return nullptr; } - /// recompileAndRelinkFunction - For the interpreter, functions are always - /// up-to-date. - /// - void *recompileAndRelinkFunction(Function *F) override { - return getPointerToFunction(F); - } - - /// freeMachineCodeForFunction - The interpreter does not generate any code. - /// - void freeMachineCodeForFunction(Function *F) override { } - // Methods used to execute code: // Place a call on the stack void callFunction(Function *F, const std::vector<GenericValue> &ArgVals); @@ -213,7 +216,6 @@ private: // Helper functions void SwitchToNewBasicBlock(BasicBlock *Dest, ExecutionContext &SF); void *getPointerToFunction(Function *F) override { return (void*)F; } - void *getPointerToBasicBlock(BasicBlock *BB) override { return (void*)BB; } void initializeExecutionEngine() { } void initializeExternalFunctions(); |