forked from OSchip/llvm-project
Add EngineBuilder to ExecutionEngine in favor of the five optional argument EE::create().
Also a test commit. llvm-svn: 76276
This commit is contained in:
parent
91ff94d6d9
commit
fc8a2d5a83
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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: ";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,28 +387,62 @@ 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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
ExecutionEngine *ExecutionEngine::create(Module *M) {
|
||||
return create(new ExistingModuleProvider(M));
|
||||
}
|
||||
|
||||
/// getPointerToGlobal - This returns the address of the specified global
|
||||
/// value. This may involve code generation if it's a function.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue