Add EngineBuilder to ExecutionEngine in favor of the five optional argument EE::create().
authorReid Kleckner <reid@kleckner.net>
Sat, 18 Jul 2009 00:42:18 +0000 (00:42 +0000)
committerReid Kleckner <reid@kleckner.net>
Sat, 18 Jul 2009 00:42:18 +0000 (00:42 +0000)
Also a test commit.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76276 91177308-0d34-0410-b5e6-96231b3b80d8

22 files changed:
bindings/ocaml/executionengine/llvm_executionengine.mli
docs/CMake.html
docs/tutorial/LangImpl4.html
docs/tutorial/LangImpl5.html
docs/tutorial/LangImpl6.html
docs/tutorial/LangImpl7.html
examples/BrainF/BrainFDriver.cpp
examples/Fibonacci/fibonacci.cpp
examples/HowToUseJIT/HowToUseJIT.cpp
examples/Kaleidoscope/toy.cpp
examples/ParallelJIT/ParallelJIT.cpp
include/llvm/ExecutionEngine/ExecutionEngine.h
lib/ExecutionEngine/ExecutionEngine.cpp
lib/ExecutionEngine/ExecutionEngineBindings.cpp
lib/ExecutionEngine/Interpreter/Interpreter.cpp
lib/ExecutionEngine/Interpreter/Interpreter.h
lib/ExecutionEngine/JIT/JIT.cpp
lib/ExecutionEngine/JIT/JIT.h
lib/ExecutionEngine/JIT/TargetSelect.cpp
tools/lli/lli.cpp
unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp
unittests/ExecutionEngine/JIT/JITTest.cpp

index 17da1dffe556b2f91a5feb6967319871869681e7..32e2fdf65451e717eae42608540e6271c14a768f 100644 (file)
@@ -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
       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].
   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
   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].
       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
   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].
       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
   val create_fast_jit: Llvm.llmoduleprovider -> t
   
   (** [dispose ee] releases the memory used by the execution engine and must be
index 1f50d397f006d628c3fea68ceae058b3131a8d17..2d4f4ef8c883ab0681c1dc0f10d2f2ec2ae0547b 100644 (file)
 
   <p>to your linker options. This is required for adding the relevant
     LLVM object code to the executable. Not doing this will result on
 
   <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>
     instance).</p>
 
 </div>
index ca5968273e14492ec8e5fba14d3c63c82ab672c5..41f3a2cd85ea95a7f1dd8657495cd94fc97545d7 100644 (file)
@@ -299,7 +299,7 @@ by adding a global variable and a call in <tt>main</tt>:</p>
 int main() {
   ..
   <b>// Create the JIT.
 int main() {
   ..
   <b>// Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);</b>
+    TheExecutionEngine = EngineBuilder(TheModule).create();</b>
   ..
 }
 </pre>
   ..
 }
 </pre>
@@ -1078,7 +1078,7 @@ int main() {
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);
+  TheExecutionEngine = EngineBuilder(TheModule).create();
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
index cad05f7045401da909365794c18329978d88528f..5f50cb28c5b222146aec16b50eb34d64a0c5bad1 100644 (file)
@@ -1712,7 +1712,7 @@ int main() {
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);
+  TheExecutionEngine = EngineBuilder(TheModule).create();
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
index b10a15f6353b7ba298585f7dbe9033f63b314076..9fffb53398b45b9a01c2d92f34b6a1d71db7bd38 100644 (file)
@@ -1751,7 +1751,7 @@ int main() {
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);
+  TheExecutionEngine = EngineBuilder(TheModule).create();
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
index 9424223fd777e19231b5cf69ff9a3146a83e458c..27a30f734393b5a09dd54032fa38e30145f00194 100644 (file)
@@ -2103,7 +2103,7 @@ int main() {
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
   TheModule = new Module("my cool jit", getGlobalContext());
   
   // Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);
+  TheExecutionEngine = EngineBuilder(TheModule).create();
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
index 021b9510ce406b75ea6cd4dfad6e35e93d69f163..fba79cfbd55fb8488c604143ad0d573fe560dbb5 100644 (file)
@@ -141,8 +141,7 @@ int main(int argc, char **argv) {
     InitializeNativeTarget();
 
     std::cout << "------- Running JIT -------\n";
     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);
     std::vector<GenericValue> args;
     Function *brainf_func = mod->getFunction("brainf");
     GenericValue gv = ee->runFunction(brainf_func, args);
index d637d4dea1733b717d32775a9e3556ca6011e349..c5c8f0de89e058712f5939e608e50abc8fe217dd 100644 (file)
@@ -100,8 +100,7 @@ int main(int argc, char **argv) {
   Function *FibF = CreateFibFunction(M, Context);
 
   // Now we going to create JIT
   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)) {
 
   errs() << "verifying... ";
   if (verifyModule(*M)) {
index 6d43cb47ced5485b0fcee1ea70972f23e60062f1..8a788491fd1abfdbece2f4a15b5ffa9b706c9a1e 100644 (file)
@@ -104,8 +104,7 @@ int main() {
   ReturnInst::Create(Add1CallRes, BB);
 
   // Now we create the JIT.
   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: ";
 
   outs() << "We just constructed this LLVM module:\n\n" << *M;
   outs() << "\n\nRunning foo: ";
index 4fd80a936343c7e33e75ae8430424ff4a873b45c..abcd412f077a8060eb8562dc42812611ed8dd051 100644 (file)
@@ -1103,7 +1103,7 @@ int main() {
   TheModule = new Module("my cool jit", Context);
   
   // Create the JIT.
   TheModule = new Module("my cool jit", Context);
   
   // Create the JIT.
-  TheExecutionEngine = ExecutionEngine::create(TheModule);
+  TheExecutionEngine = EngineBuilder(TheModule).create();
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
 
   {
     ExistingModuleProvider OurModuleProvider(TheModule);
@@ -1138,4 +1138,3 @@ int main() {
   
   return 0;
 }
   
   return 0;
 }
-
index d82a6be81db0d6d1a7293abc20417f4d487fa85c..464bd22e8ff0436ef95efa8ae6630b8a91f09b8a 100644 (file)
@@ -242,8 +242,7 @@ int main() {
   Function* fibF = CreateFibFunction( M );
 
   // Now we create the JIT.
   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;
 
   //~ std::cout << "We just constructed this LLVM module:\n\n" << *M;
   //~ std::cout << "\n\nRunning foo: " << std::flush;
index cb24d916fc0bcc1f91ad2784d7bf2eca5727626c..1dc9d1dee5e1beb60067d4b1ede153214ff5c59a 100644 (file)
@@ -71,6 +71,8 @@ class ExecutionEngine {
   bool SymbolSearchingDisabled;
   bool DlsymStubsEnabled;
 
   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.
 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.
   // 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.
 
   /// 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);
 };
 
                            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
 } // End llvm namespace
 
 #endif
index 9f27338195a44a285b24ac1968e5f148d0b9a7fa..ee4b0b232f59f2fee7ef0965fd7df0dbfedb4fa9 100644 (file)
@@ -35,8 +35,13 @@ using namespace llvm;
 STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
 STATISTIC(NumGlobals  , "Number of global vars initialized");
 
 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;
 
 
 ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
 
 
@@ -382,26 +387,60 @@ ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP,
                                          std::string *ErrorStr,
                                          CodeGenOpt::Level OptLevel,
                                          bool GVsWithCode) {
                                          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;
 
   // 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
 }
 
 /// getPointerToGlobal - This returns the address of the specified global
index 4ee26229420c18cfafdc24743fa9e3a035105bf9..5901cd757dc1f191b48458f6bd12d2ee60f54638 100644 (file)
@@ -91,7 +91,10 @@ int LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE,
                               LLVMModuleProviderRef MP,
                               char **OutError) {
   std::string Error;
                               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;
   }
     *OutEE = wrap(EE);
     return 0;
   }
@@ -103,8 +106,10 @@ int LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp,
                           LLVMModuleProviderRef MP,
                           char **OutError) {
   std::string Error;
                           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;
   }
     *OutInterp = wrap(Interp);
     return 0;
   }
@@ -117,9 +122,11 @@ int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT,
                           unsigned OptLevel,
                           char **OutError) {
   std::string Error;
                           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;
   }
     *OutJIT = wrap(JIT);
     return 0;
   }
index 902f6768dc8ab7c906bd1fd755c2f094765ccd2b..9be6a9265d613a1954af2ea2d7ba0fb4ff527d99 100644 (file)
@@ -33,9 +33,7 @@ extern "C" void LLVMLinkInInterpreter() { }
 
 /// create - Create a new interpreter object.  This can never fail.
 ///
 
 /// 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
   // Tell this ModuleProvide to materialize and release the module
   if (!MP->materializeModule(ErrStr))
     // We got an error, just return 0
index 01771cfe9eb5e937755dda592bf7c5ac4df5d7be..10e53e9a143ee0f4a37829fee5e067b5216a3a75 100644 (file)
@@ -108,9 +108,7 @@ public:
   
   /// create - Create an interpreter ExecutionEngine. This can never fail.
   ///
   
   /// 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.
   ///
 
   /// run - Start execution with the specified function and arguments.
   ///
index 58ff71b8460437cd09f3084728ca066a397aff64..81be38bce51089ba4db40db7bb43e254624f74b6 100644 (file)
@@ -199,14 +199,31 @@ ExecutionEngine *ExecutionEngine::createJIT(ModuleProvider *MP,
                                             JITMemoryManager *JMM,
                                             CodeGenOpt::Level OptLevel,
                                             bool GVsWithCode) {
                                             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.
   // 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,
 }
 
 JIT::JIT(ModuleProvider *MP, TargetMachine &tm, TargetJITInfo &tji,
index 1ad54f37807cf8a6fe22c368e7e9805f47f96587..e3ab9e21c9ec48f41cafd185cb26e61d57e4da8e 100644 (file)
@@ -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.
   ///
   /// 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,
                                  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);
   }
 
   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.
   /// 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);
   void addPendingFunction(Function *F);
-  
+
   /// getCodeEmitter - Return the code emitter this JIT is emitting into.
   /// getCodeEmitter - Return the code emitter this JIT is emitting into.
+  ///
   JITCodeEmitter *getCodeEmitter() const { return JCE; }
   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,
   static ExecutionEngine *createJIT(ModuleProvider *MP,
-                                    std::string *Err,
+                                    std::string *ErrorStr,
                                     JITMemoryManager *JMM,
                                     CodeGenOpt::Level OptLevel,
                                     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);
 
   // Run the JIT on F and return information about the generated code
   void runJITOnFunction(Function *F, MachineCodeInfo *MCI = 0);
index 598b867a3f942967c6a83228eb427e8f00410033..2b80e7e2bd16d36d6eb14041c7e6cb45acf01ef2 100644 (file)
@@ -38,13 +38,9 @@ MAttrs("mattr",
   cl::desc("Target specific attributes (-mattr=help for details)"),
   cl::value_desc("a1,+a2,-a3,..."));
 
   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;
   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!");
   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;
 }
 }
index 8afdbcad95b259cca86d6ba9d7af2a8e23433ac0..12f91558247f3f9ffbd090ca60b38e75e5c84915 100644 (file)
@@ -131,6 +131,12 @@ int main(int argc, char **argv, char * const *envp) {
     exit(1);
   }
 
     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);
   // 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;
   }
   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";
   if (!EE) {
     if (!ErrorMsg.empty())
       errs() << argv[0] << ": error creating EE: " << ErrorMsg << "\n";
index 8fa5c4c107d5a63ebc9dc67d478ec7c55af3a502..7e2104ef8e0103fe27d109257bc0e669de129acf 100644 (file)
@@ -66,7 +66,9 @@ class JITEventListenerTest : public testing::Test {
  protected:
   JITEventListenerTest()
       : M(new Module("module", getGlobalContext())),
  protected:
   JITEventListenerTest()
       : M(new Module("module", getGlobalContext())),
-        EE(ExecutionEngine::createJIT(new ExistingModuleProvider(M))) {
+        EE(EngineBuilder(M)
+           .setEngineToCreate(EngineBuilder::ENG_JIT)
+           .create()) {
   }
 
   Module *M;
   }
 
   Module *M;
@@ -232,7 +234,7 @@ TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
 
 class JITEnvironment : public testing::Environment {
   virtual void SetUp() {
 
 class JITEnvironment : public testing::Environment {
   virtual void SetUp() {
-    // Required for ExecutionEngine::createJIT to create a JIT.
+    // Required to create a JIT.
     InitializeNativeTarget();
   }
 };
     InitializeNativeTarget();
   }
 };
index 211b6adf47d27c7a0b48f09cd079f6bec59af19e..b46ff8adf6362d6b4d161e0b702ce820520c76d3 100644 (file)
@@ -1,4 +1,4 @@
-//===- JITEmitter.cpp - Unit tests for the JIT code emitter ---------------===//
+//===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -18,6 +18,7 @@
 #include "llvm/Function.h"
 #include "llvm/GlobalValue.h"
 #include "llvm/GlobalVariable.h"
 #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"
 #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;
   // 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.
   ASSERT_EQ(Error, "");
 
   // Create a global variable.
@@ -115,11 +117,12 @@ TEST(JIT, GlobalInFunction) {
   EXPECT_EQ(3, *GPtr);
 }
 
   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() {
 class JITEnvironment : public testing::Environment {
   virtual void SetUp() {
-    // Required for ExecutionEngine::createJIT to create a JIT.
+    // Required to create a JIT.
     InitializeNativeTarget();
   }
 };
     InitializeNativeTarget();
   }
 };