diff --git a/llvm/_core.cpp b/llvm/_core.cpp index b3fb298..8ba56dd 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -1241,6 +1241,32 @@ _wLLVMEngineBuilderCreate(PyObject *self, PyObject *args) LLVMPY_CATCH_ALL } +static PyObject * +_wLLVMEngineBuilderCreateTM(PyObject *self, PyObject *args) +{ + LLVMPY_TRY + PyObject *obj, *tm; + if (!PyArg_ParseTuple(args, "OO", &obj, &tm)) + return NULL; + + const LLVMEngineBuilderRef objref = pycap_get( obj ); + const LLVMTargetMachineRef tmref = pycap_get( tm ); + std::string outmsg; + + const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreateTM(objref, tmref, + outmsg); + + PyObject * ret; + if( !ee ){ // check if error message is set. + ret = PyUnicode_FromString(outmsg.c_str()); + }else{ + ret = pycap_new(ee); + } + + return ret; + LLVMPY_CATCH_ALL +} + /*===----------------------------------------------------------------------===*/ /* Execution Engine */ /*===----------------------------------------------------------------------===*/ @@ -2032,6 +2058,7 @@ static PyMethodDef core_methods[] = { _method( LLVMEngineBuilderSetMCPU ) _method( LLVMEngineBuilderSetMAttrs ) _method( LLVMEngineBuilderCreate ) + _method( LLVMEngineBuilderCreateTM ) /* Execution Engine */ _method( LLVMCreateExecutionEngine ) diff --git a/llvm/ee.py b/llvm/ee.py index 8469138..d522473 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -167,11 +167,21 @@ class EngineBuilder(object): _core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' ')) return self - def create(self): - ret = _core.LLVMEngineBuilderCreate(self.ptr) + def create(self, tm=None): + ''' + tm --- Optional. Provide a TargetMachine. + ''' + if tm: + _util.check_is_unowned(tm) + ret = _core.LLVMEngineBuilderCreateTM(self.ptr, tm.ptr) + else: + ret = _core.LLVMEngineBuilderCreate(self.ptr) if isinstance(ret, str): raise llvm.LLVMException(ret) - return ExecutionEngine(ret, self._module) + engine = ExecutionEngine(ret, self._module) + if tm: + tm._own(owner=engine) + return engine def select_target(self): '''get the corresponding target machine @@ -262,7 +272,7 @@ def get_default_triple(): ''' return _core.LLVMDefaultTargetTriple() -class TargetMachine(object): +class TargetMachine(llvm.Ownable): @staticmethod def new(triple='', cpu='', features='', opt=2): @@ -289,10 +299,7 @@ class TargetMachine(object): return TargetMachine(ptr) def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeTargetMachine(self.ptr) + llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine) def emit_assembly(self, module): '''returns byte string of the module as assembly code of the target machine diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 10d090a..c3f1fc0 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -723,6 +723,22 @@ LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, std::str } } +LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef eb, + LLVMTargetMachineRef tm, + std::string & error) +{ + using namespace llvm; + LLVMExecutionEngineRef ret; + + ret = wrap(unwrap(eb)->setErrorStr(&error).create(unwrap(tm))); + + if ( !error.empty() ) { // error string is set + return NULL; + } else { + return ret; + } +} + int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb) { return llvm::unwrap(pmb)->OptLevel; diff --git a/llvm/extra.h b/llvm/extra.h index 3f2a413..30f1e08 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -338,6 +338,14 @@ void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs); LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, std::string &error); +/* + * Wraps EngineBuilder::create(TargetMachine*) + */ +LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef ebref, + LLVMTargetMachineRef tmref, + std::string & error); + + /* * Wraps PassManagerBuilder::OptLevel */ diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 7757cd1..82c6a81 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -412,6 +412,23 @@ class TestEngineBuilder(unittest.TestCase): self.run_foo(ee, module) + + def test_enginebuilder_with_tm(self): + tm = le.TargetMachine.new() + module = self.make_test_module() + ee = EngineBuilder.new(module).create(tm) + + with self.assertRaises(llvm.LLVMException): + # Ensure the targetmachine is owned. + llvm._util.check_is_unowned(tm) + + + with self.assertRaises(llvm.LLVMException): + # Ensure the module is owned. + llvm._util.check_is_unowned(module) + + self.run_foo(ee, module) + def test_enginebuilder_force_jit(self): module = self.make_test_module() ee = EngineBuilder.new(module).force_jit().create()