aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bindings/ocaml/executionengine/llvm_executionengine.mli8
-rw-r--r--docs/CMake.html2
-rw-r--r--docs/tutorial/LangImpl4.html4
-rw-r--r--docs/tutorial/LangImpl5.html2
-rw-r--r--docs/tutorial/LangImpl6.html2
-rw-r--r--docs/tutorial/LangImpl7.html2
-rw-r--r--examples/BrainF/BrainFDriver.cpp3
-rw-r--r--examples/Fibonacci/fibonacci.cpp3
-rw-r--r--examples/HowToUseJIT/HowToUseJIT.cpp3
-rw-r--r--examples/Kaleidoscope/toy.cpp3
-rw-r--r--examples/ParallelJIT/ParallelJIT.cpp3
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h103
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp65
-rw-r--r--lib/ExecutionEngine/ExecutionEngineBindings.cpp19
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.cpp4
-rw-r--r--lib/ExecutionEngine/Interpreter/Interpreter.h4
-rw-r--r--lib/ExecutionEngine/JIT/JIT.cpp29
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h24
-rw-r--r--lib/ExecutionEngine/JIT/TargetSelect.cpp19
-rw-r--r--tools/lli/lli.cpp11
-rw-r--r--unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp6
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp23
22 files changed, 249 insertions, 93 deletions
diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli
index 17da1df..32e2fdf 100644
--- a/bindings/ocaml/executionengine/llvm_executionengine.mli
+++ b/bindings/ocaml/executionengine/llvm_executionengine.mli
@@ -89,14 +89,14 @@ module ExecutionEngine: sig
module provider [mp] if successful. Creates a JIT if possible, else falls
back to an interpreter. Raises [Error msg] if an error occurrs. The
execution engine is not garbage collected and must be destroyed with
- [dispose ee]. See the function [llvm::ExecutionEngine::create]. *)
+ [dispose ee]. See the function [llvm::EngineBuilder::create]. *)
val create: Llvm.llmoduleprovider -> t
(** [create_interpreter mp] creates a new interpreter, taking ownership of the
module provider [mp] if successful. Raises [Error msg] if an error
occurrs. The execution engine is not garbage collected and must be
destroyed with [dispose ee].
- See the function [llvm::ExecutionEngine::create]. *)
+ See the function [llvm::EngineBuilder::create]. *)
val create_interpreter: Llvm.llmoduleprovider -> t
(** [create_jit mp] creates a new JIT (just-in-time compiler), taking
@@ -104,7 +104,7 @@ module ExecutionEngine: sig
a JIT which favors code quality over compilation speed. Raises [Error msg]
if an error occurrs. The execution engine is not garbage collected and
must be destroyed with [dispose ee].
- See the function [llvm::ExecutionEngine::create]. *)
+ See the function [llvm::EngineBuilder::create]. *)
val create_jit: Llvm.llmoduleprovider -> t
(** [create_fast_jit mp] creates a new JIT (just-in-time compiler) which
@@ -112,7 +112,7 @@ module ExecutionEngine: sig
module provider [mp] if successful. Raises [Error msg] if an error
occurrs. The execution engine is not garbage collected and must be
destroyed with [dispose ee].
- See the function [llvm::ExecutionEngine::create]. *)
+ See the function [llvm::EngineBuilder::create]. *)
val create_fast_jit: Llvm.llmoduleprovider -> t
(** [dispose ee] releases the memory used by the execution engine and must be
diff --git a/docs/CMake.html b/docs/CMake.html
index 1f50d39..2d4f4ef 100644
--- a/docs/CMake.html
+++ b/docs/CMake.html
@@ -352,7 +352,7 @@
<p>to your linker options. This is required for adding the relevant
LLVM object code to the executable. Not doing this will result on
- some methods returning NULL (<i>ExecutionEngine::create</i>, for
+ some methods returning NULL (<i>EngineBuilder::create</i>, for
instance).</p>
</div>
diff --git a/docs/tutorial/LangImpl4.html b/docs/tutorial/LangImpl4.html
index ca59682..41f3a2c 100644
--- a/docs/tutorial/LangImpl4.html
+++ b/docs/tutorial/LangImpl4.html
@@ -299,7 +299,7 @@ by adding a global variable and a call in <tt>main</tt>:</p>
int main() {
..
<b>// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);</b>
+ TheExecutionEngine = EngineBuilder(TheModule).create();</b>
..
}
</pre>
@@ -1078,7 +1078,7 @@ int main() {
TheModule = new Module("my cool jit", getGlobalContext());
// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);
+ TheExecutionEngine = EngineBuilder(TheModule).create();
{
ExistingModuleProvider OurModuleProvider(TheModule);
diff --git a/docs/tutorial/LangImpl5.html b/docs/tutorial/LangImpl5.html
index cad05f7..5f50cb2 100644
--- a/docs/tutorial/LangImpl5.html
+++ b/docs/tutorial/LangImpl5.html
@@ -1712,7 +1712,7 @@ int main() {
TheModule = new Module("my cool jit", getGlobalContext());
// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);
+ TheExecutionEngine = EngineBuilder(TheModule).create();
{
ExistingModuleProvider OurModuleProvider(TheModule);
diff --git a/docs/tutorial/LangImpl6.html b/docs/tutorial/LangImpl6.html
index b10a15f..9fffb53 100644
--- a/docs/tutorial/LangImpl6.html
+++ b/docs/tutorial/LangImpl6.html
@@ -1751,7 +1751,7 @@ int main() {
TheModule = new Module("my cool jit", getGlobalContext());
// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);
+ TheExecutionEngine = EngineBuilder(TheModule).create();
{
ExistingModuleProvider OurModuleProvider(TheModule);
diff --git a/docs/tutorial/LangImpl7.html b/docs/tutorial/LangImpl7.html
index 9424223..27a30f7 100644
--- a/docs/tutorial/LangImpl7.html
+++ b/docs/tutorial/LangImpl7.html
@@ -2103,7 +2103,7 @@ int main() {
TheModule = new Module("my cool jit", getGlobalContext());
// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);
+ TheExecutionEngine = EngineBuilder(TheModule).create();
{
ExistingModuleProvider OurModuleProvider(TheModule);
diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp
index 021b951..fba79cf 100644
--- a/examples/BrainF/BrainFDriver.cpp
+++ b/examples/BrainF/BrainFDriver.cpp
@@ -141,8 +141,7 @@ int main(int argc, char **argv) {
InitializeNativeTarget();
std::cout << "------- Running JIT -------\n";
- ExistingModuleProvider *mp = new ExistingModuleProvider(mod);
- ExecutionEngine *ee = ExecutionEngine::create(mp, false);
+ ExecutionEngine *ee = EngineBuilder(mod).create();
std::vector<GenericValue> args;
Function *brainf_func = mod->getFunction("brainf");
GenericValue gv = ee->runFunction(brainf_func, args);
diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp
index d637d4d..c5c8f0d 100644
--- a/examples/Fibonacci/fibonacci.cpp
+++ b/examples/Fibonacci/fibonacci.cpp
@@ -100,8 +100,7 @@ int main(int argc, char **argv) {
Function *FibF = CreateFibFunction(M, Context);
// Now we going to create JIT
- ExistingModuleProvider *MP = new ExistingModuleProvider(M);
- ExecutionEngine *EE = ExecutionEngine::create(MP, false);
+ ExecutionEngine *EE = EngineBuilder(M).create();
errs() << "verifying... ";
if (verifyModule(*M)) {
diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp
index 6d43cb4..8a78849 100644
--- a/examples/HowToUseJIT/HowToUseJIT.cpp
+++ b/examples/HowToUseJIT/HowToUseJIT.cpp
@@ -104,8 +104,7 @@ int main() {
ReturnInst::Create(Add1CallRes, BB);
// Now we create the JIT.
- ExistingModuleProvider* MP = new ExistingModuleProvider(M);
- ExecutionEngine* EE = ExecutionEngine::create(MP, false);
+ ExecutionEngine* EE = EngineBuilder(M).create();
outs() << "We just constructed this LLVM module:\n\n" << *M;
outs() << "\n\nRunning foo: ";
diff --git a/examples/Kaleidoscope/toy.cpp b/examples/Kaleidoscope/toy.cpp
index 4fd80a9..abcd412 100644
--- a/examples/Kaleidoscope/toy.cpp
+++ b/examples/Kaleidoscope/toy.cpp
@@ -1103,7 +1103,7 @@ int main() {
TheModule = new Module("my cool jit", Context);
// Create the JIT.
- TheExecutionEngine = ExecutionEngine::create(TheModule);
+ TheExecutionEngine = EngineBuilder(TheModule).create();
{
ExistingModuleProvider OurModuleProvider(TheModule);
@@ -1138,4 +1138,3 @@ int main() {
return 0;
}
-
diff --git a/examples/ParallelJIT/ParallelJIT.cpp b/examples/ParallelJIT/ParallelJIT.cpp
index d82a6be..464bd22 100644
--- a/examples/ParallelJIT/ParallelJIT.cpp
+++ b/examples/ParallelJIT/ParallelJIT.cpp
@@ -242,8 +242,7 @@ int main() {
Function* fibF = CreateFibFunction( M );
// Now we create the JIT.
- ExistingModuleProvider* MP = new ExistingModuleProvider(M);
- ExecutionEngine* EE = ExecutionEngine::create(MP, false);
+ ExecutionEngine* EE = EngineBuilder(M).create();
//~ std::cout << "We just constructed this LLVM module:\n\n" << *M;
//~ std::cout << "\n\nRunning foo: " << std::flush;
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index cb24d91..1dc9d1d 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -71,6 +71,8 @@ class ExecutionEngine {
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,10 +88,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,
- bool GVsWithCode);
- 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.
@@ -372,6 +377,96 @@ 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();
+
+};
+
} // End llvm namespace
#endif
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index 9f27338..ee4b0b2 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -35,8 +35,13 @@ using namespace llvm;
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
STATISTIC(NumGlobals , "Number of global vars initialized");
-ExecutionEngine::EECtorFn ExecutionEngine::JITCtor = 0;
-ExecutionEngine::EECtorFn ExecutionEngine::InterpCtor = 0;
+ExecutionEngine *(*ExecutionEngine::JITCtor)(ModuleProvider *MP,
+ std::string *ErrorStr,
+ JITMemoryManager *JMM,
+ CodeGenOpt::Level OptLevel,
+ bool GVsWithCode) = 0;
+ExecutionEngine *(*ExecutionEngine::InterpCtor)(ModuleProvider *MP,
+ std::string *ErrorStr) = 0;
ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
@@ -382,26 +387,60 @@ ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP,
std::string *ErrorStr,
CodeGenOpt::Level OptLevel,
bool GVsWithCode) {
- ExecutionEngine *EE = 0;
+ return EngineBuilder(MP)
+ .setEngineKind(ForceInterpreter
+ ? EngineKind::Interpreter
+ : EngineKind::JIT)
+ .setErrorStr(ErrorStr)
+ .setOptLevel(OptLevel)
+ .setAllocateGVsWithCode(GVsWithCode)
+ .create();
+}
+
+ExecutionEngine *ExecutionEngine::create(Module *M) {
+ return EngineBuilder(M).create();
+}
+/// EngineBuilder - Overloaded constructor that automatically creates an
+/// ExistingModuleProvider for an existing module.
+EngineBuilder::EngineBuilder(Module *m) : MP(new ExistingModuleProvider(m)) {
+ InitEngine();
+}
+
+ExecutionEngine *EngineBuilder::create() {
// Make sure we can resolve symbols in the program as well. The zero arg
// to the function tells DynamicLibrary to load the program, not a library.
if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr))
return 0;
- // Unless the interpreter was explicitly selected, try making a JIT.
- if (!ForceInterpreter && JITCtor)
- EE = JITCtor(MP, ErrorStr, OptLevel, GVsWithCode);
+ // If the user specified a memory manager but didn't specify which engine to
+ // create, we assume they only want the JIT, and we fail if they only want
+ // the interpreter.
+ if (JMM) {
+ if (WhichEngine & EngineKind::JIT) {
+ WhichEngine = EngineKind::JIT;
+ } else {
+ *ErrorStr = "Cannot create an interpreter with a memory manager.";
+ }
+ }
- // If we can't make a JIT, make an interpreter instead.
- if (EE == 0 && InterpCtor)
- EE = InterpCtor(MP, ErrorStr, OptLevel, GVsWithCode);
+ ExecutionEngine *EE = 0;
- return EE;
-}
+ // Unless the interpreter was explicitly selected or the JIT is not linked,
+ // try making a JIT.
+ if (WhichEngine & EngineKind::JIT && ExecutionEngine::JITCtor) {
+ EE = ExecutionEngine::JITCtor(MP, ErrorStr, JMM, OptLevel,
+ AllocateGVsWithCode);
+ }
-ExecutionEngine *ExecutionEngine::create(Module *M) {
- return create(new ExistingModuleProvider(M));
+ // If we can't make a JIT and we didn't request one specifically, try making
+ // an interpreter instead.
+ if (WhichEngine & EngineKind::Interpreter && EE == 0 &&
+ ExecutionEngine::InterpCtor) {
+ EE = ExecutionEngine::InterpCtor(MP, ErrorStr);
+ }
+
+ return EE;
}
/// getPointerToGlobal - This returns the address of the specified global
diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
index 4ee2622..5901cd7 100644
--- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
@@ -91,7 +91,10 @@ int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE,
LLVMModuleProviderRef MP,
char **OutError) {
std::string Error;
- if (ExecutionEngine *EE = ExecutionEngine::create(unwrap(MP), false, &Error)){
+ EngineBuilder builder(unwrap(MP));
+ builder.setEngineKind(EngineKind::Either)
+ .setErrorStr(&Error);
+ if (ExecutionEngine *EE = builder.create()){
*OutEE = wrap(EE);
return 0;
}
@@ -103,8 +106,10 @@ int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp,
LLVMModuleProviderRef MP,
char **OutError) {
std::string Error;
- if (ExecutionEngine *Interp =
- ExecutionEngine::create(unwrap(MP), true, &Error)) {
+ EngineBuilder builder(unwrap(MP));
+ builder.setEngineKind(EngineKind::Interpreter)
+ .setErrorStr(&Error);
+ if (ExecutionEngine *Interp = builder.create()) {
*OutInterp = wrap(Interp);
return 0;
}
@@ -117,9 +122,11 @@ int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT,
unsigned OptLevel,
char **OutError) {
std::string Error;
- if (ExecutionEngine *JIT =
- ExecutionEngine::create(unwrap(MP), false, &Error,
- (CodeGenOpt::Level)OptLevel)) {
+ EngineBuilder builder(unwrap(MP));
+ builder.setEngineKind(EngineKind::JIT)
+ .setErrorStr(&Error)
+ .setOptLevel((CodeGenOpt::Level)OptLevel);
+ if (ExecutionEngine *JIT = builder.create()) {
*OutJIT = wrap(JIT);
return 0;
}
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.cpp b/lib/ExecutionEngine/Interpreter/Interpreter.cpp
index 902f676..9be6a92 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.cpp
+++ b/lib/ExecutionEngine/Interpreter/Interpreter.cpp
@@ -33,9 +33,7 @@ extern "C" void LLVMLinkInInterpreter() { }
/// create - Create a new interpreter object. This can never fail.
///
-ExecutionEngine *Interpreter::create(ModuleProvider *MP, std::string* ErrStr,
- CodeGenOpt::Level OptLevel, /*unused*/
- bool GVsWithCode /* unused */) {
+ExecutionEngine *Interpreter::create(ModuleProvider *MP, std::string* ErrStr) {
// Tell this ModuleProvide to materialize and release the module
if (!MP->materializeModule(ErrStr))
// We got an error, just return 0
diff --git a/lib/ExecutionEngine/Interpreter/Interpreter.h b/lib/ExecutionEngine/Interpreter/Interpreter.h
index 01771cf..10e53e9 100644
--- a/lib/ExecutionEngine/Interpreter/Interpreter.h
+++ b/lib/ExecutionEngine/Interpreter/Interpreter.h
@@ -108,9 +108,7 @@ public:
/// create - Create an interpreter ExecutionEngine. This can never fail.
///
- static ExecutionEngine *create(ModuleProvider *M, std::string *ErrorStr = 0,
- CodeGenOpt::Level = CodeGenOpt::Default,
- bool GVsWithCode = true);
+ static ExecutionEngine *create(ModuleProvider *M, std::string *ErrorStr = 0);
/// run - Start execution with the specified function and arguments.
///
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp
index 58ff71b..81be38b 100644
--- a/lib/ExecutionEngine/JIT/JIT.cpp
+++ b/lib/ExecutionEngine/JIT/JIT.cpp
@@ -199,14 +199,31 @@ ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
JITMemoryManager *JMM,
CodeGenOpt::Level OptLevel,
bool GVsWithCode) {
- ExecutionEngine *EE = JIT::createJIT(MP, ErrorStr, JMM, OptLevel,
- GVsWithCode);
- if (!EE) return 0;
-
+ return JIT::createJIT(MP, ErrorStr, JMM, OptLevel, GVsWithCode);
+}
+
+ExecutionEngine *JIT::createJIT(ModuleProvider *MP,
+ std::string *ErrorStr,
+ JITMemoryManager *JMM,
+ CodeGenOpt::Level OptLevel,
+ bool GVsWithCode) {
// Make sure we can resolve symbols in the program as well. The zero arg
// to the function tells DynamicLibrary to load the program, not a library.
- sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr);
- return EE;
+ if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr))
+ return 0;
+
+ // Pick a target either via -march or by guessing the native arch.
+ TargetMachine *TM = JIT::selectTarget(MP, ErrorStr);
+ if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0;
+
+ // If the target supports JIT code generation, create a the JIT.
+ if (TargetJITInfo *TJ = TM->getJITInfo()) {
+ return new JIT(MP, *TM, *TJ, JMM, OptLevel, GVsWithCode);
+ } else {
+ if (ErrorStr)
+ *ErrorStr = "target does not support JIT code generation";
+ return 0;
+ }
}
JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h
index 1ad54f3..e3ab9e2 100644
--- a/lib/ExecutionEngine/JIT/JIT.h
+++ b/lib/ExecutionEngine/JIT/JIT.h
@@ -79,11 +79,13 @@ public:
/// create - Create an return a new JIT compiler if there is one available
/// for the current target. Otherwise, return null.
///
- static ExecutionEngine *create(ModuleProvider *MP, std::string *Err,
+ static ExecutionEngine *create(ModuleProvider *MP,
+ std::string *Err,
+ JITMemoryManager *JMM,
CodeGenOpt::Level OptLevel =
CodeGenOpt::Default,
- bool AllocateGVsWithCode = true) {
- return createJIT(MP, Err, 0, OptLevel, AllocateGVsWithCode);
+ bool GVsWithCode = true) {
+ return ExecutionEngine::createJIT(MP, Err, JMM, OptLevel, GVsWithCode);
}
virtual void addModuleProvider(ModuleProvider *MP);
@@ -152,18 +154,22 @@ public:
/// addPendingFunction - while jitting non-lazily, a called but non-codegen'd
/// function was encountered. Add it to a pending list to be processed after
/// the current function.
- ///
+ ///
void addPendingFunction(Function *F);
-
+
/// getCodeEmitter - Return the code emitter this JIT is emitting into.
+ ///
JITCodeEmitter *getCodeEmitter() const { return JCE; }
-
+
+ /// selectTarget - Pick a target either via -march or by guessing the native
+ /// arch. Add any CPU features specified via -mcpu or -mattr.
+ static TargetMachine *selectTarget(ModuleProvider *MP, std::string *Err);
+
static ExecutionEngine *createJIT(ModuleProvider *MP,
- std::string *Err,
+ std::string *ErrorStr,
JITMemoryManager *JMM,
CodeGenOpt::Level OptLevel,
- bool AllocateGVsWithCode);
-
+ bool GVsWithCode);
// Run the JIT on F and return information about the generated code
void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0);
diff --git a/lib/ExecutionEngine/JIT/TargetSelect.cpp b/lib/ExecutionEngine/JIT/TargetSelect.cpp
index 598b867..2b80e7e 100644
--- a/lib/ExecutionEngine/JIT/TargetSelect.cpp
+++ b/lib/ExecutionEngine/JIT/TargetSelect.cpp
@@ -38,13 +38,9 @@ MAttrs("mattr",
cl::desc("Target specific attributes (-mattr=help for details)"),
cl::value_desc("a1,+a2,-a3,..."));
-/// createInternal - Create an return a new JIT compiler if there is one
-/// available for the current target. Otherwise, return null.
-///
-ExecutionEngine *JIT::createJIT(ModuleProvider *MP, std::string *ErrorStr,
- JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
- bool AllocateGVsWithCode) {
+/// selectTarget - Pick a target either via -march or by guessing the native
+/// arch. Add any CPU features specified via -mcpu or -mattr.
+TargetMachine *JIT::selectTarget(ModuleProvider *MP, std::string *ErrorStr) {
const Target *TheTarget = 0;
if (MArch.empty()) {
std::string Error;
@@ -90,12 +86,5 @@ ExecutionEngine *JIT::createJIT(ModuleProvider *MP, std::string *ErrorStr,
TargetMachine *Target =
TheTarget->createTargetMachine(*MP->getModule(), FeaturesStr);
assert(Target && "Could not allocate target machine!");
-
- // If the target supports JIT code generation, return a new JIT now.
- if (TargetJITInfo *TJ = Target->getJITInfo())
- return new JIT(MP, *Target, *TJ, JMM, OptLevel, AllocateGVsWithCode);
-
- if (ErrorStr)
- *ErrorStr = "target does not support JIT code generation";
- return 0;
+ return Target;
}
diff --git a/tools/lli/lli.cpp b/tools/lli/lli.cpp
index 8afdbca..12f9155 100644
--- a/tools/lli/lli.cpp
+++ b/tools/lli/lli.cpp
@@ -131,6 +131,12 @@ int main(int argc, char **argv, char * const *envp) {
exit(1);
}
+ EngineBuilder builder(MP);
+ builder.setErrorStr(&ErrorMsg)
+ .setEngineKind(ForceInterpreter
+ ? EngineKind::Interpreter
+ : EngineKind::JIT);
+
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
Mod->setTargetTriple(TargetTriple);
@@ -146,8 +152,9 @@ int main(int argc, char **argv, char * const *envp) {
case '2': OLvl = CodeGenOpt::Default; break;
case '3': OLvl = CodeGenOpt::Aggressive; break;
}
-
- EE = ExecutionEngine::create(MP, ForceInterpreter, &ErrorMsg, OLvl);
+ builder.setOptLevel(OLvl);
+
+ EE = builder.create();
if (!EE) {
if (!ErrorMsg.empty())
errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
index 8fa5c4c..7e2104e 100644
--- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
@@ -66,7 +66,9 @@ class JITEventListenerTest : public testing::Test {
protected:
JITEventListenerTest()
: M(new Module("module", getGlobalContext())),
- EE(ExecutionEngine::createJIT(new ExistingModuleProvider(M))) {
+ EE(EngineBuilder(M)
+ .setEngineToCreate(EngineBuilder::ENG_JIT)
+ .create()) {
}
Module *M;
@@ -232,7 +234,7 @@ TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
class JITEnvironment : public testing::Environment {
virtual void SetUp() {
- // Required for ExecutionEngine::createJIT to create a JIT.
+ // Required to create a JIT.
InitializeNativeTarget();
}
};
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index 211b6ad..b46ff8a 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -1,4 +1,4 @@
-//===- JITEmitter.cpp - Unit tests for the JIT code emitter ---------------===//
+//===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,6 +18,7 @@
#include "llvm/Function.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
@@ -60,12 +61,13 @@ TEST(JIT, GlobalInFunction) {
// memory is more easily tested.
MemMgr->setPoisonMemory(true);
std::string Error;
- OwningPtr<ExecutionEngine> JIT(ExecutionEngine::createJIT(
- MP,
- &Error,
- MemMgr,
- CodeGenOpt::Default,
- false)); // This last argument enables the fix.
+ OwningPtr<ExecutionEngine> JIT(EngineBuilder(MP)
+ .setEnginePreference(EngineBuilder::JITONLY)
+ .setErrorStr(&Error)
+ .setJITMemoryManager(MemMgr)
+ // The next line enables the fix:
+ .setAllocateGVsWithCode(false)
+ .create());
ASSERT_EQ(Error, "");
// Create a global variable.
@@ -115,11 +117,12 @@ TEST(JIT, GlobalInFunction) {
EXPECT_EQ(3, *GPtr);
}
-// TODO(rnk): This seems to only run once for both tests, which is unexpected.
-// That works just fine, but we shouldn't duplicate the code.
+// This code is copied from JITEventListenerTest, but it only runs once for all
+// the tests in this directory. Everything seems fine, but that's strange
+// behavior.
class JITEnvironment : public testing::Environment {
virtual void SetUp() {
- // Required for ExecutionEngine::createJIT to create a JIT.
+ // Required to create a JIT.
InitializeNativeTarget();
}
};