Added EngineBuilder.
Added test/enginebuilder.
This commit is contained in:
parent
6a02c36f04
commit
5bb4b8affb
8 changed files with 267 additions and 3 deletions
39
llvm/_core.c
39
llvm/_core.c
|
|
@ -1049,6 +1049,36 @@ _wrap_objobjint2obj(LLVMOffsetOfElement, LLVMTargetDataRef, LLVMTypeRef,
|
|||
llvmwrap_ull)
|
||||
|
||||
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
/* Engine Builder */
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
|
||||
_wrap_obj2obj(LLVMCreateEngineBuilder, LLVMModuleRef, LLVMEngineBuilderRef)
|
||||
_wrap_obj2none(LLVMDisposeEngineBuilder, LLVMEngineBuilderRef)
|
||||
_wrap_obj2none(LLVMEngineBuilderForceJIT, LLVMEngineBuilderRef)
|
||||
_wrap_obj2none(LLVMEngineBuilderForceInterpreter, LLVMEngineBuilderRef)
|
||||
_wrap_objint2none(LLVMEngineBuilderSetOptLevel, LLVMEngineBuilderRef)
|
||||
|
||||
static PyObject *
|
||||
_wLLVMEngineBuilderCreate(PyObject *self, PyObject *args)
|
||||
{
|
||||
LLVMEngineBuilderRef obj;
|
||||
if (!(obj = (LLVMEngineBuilderRef)get_object_arg(args)))
|
||||
return NULL;
|
||||
|
||||
char * outmsg = 0;
|
||||
|
||||
PyObject * ret;
|
||||
ret = LLVMEngineBuilderCreate(obj, &outmsg);
|
||||
|
||||
if( outmsg ){ // check if error message is set.
|
||||
ret = PyBytes_FromString(outmsg);
|
||||
free(outmsg);
|
||||
}
|
||||
|
||||
return ctor_LLVMExecutionEngineRef(ret);
|
||||
}
|
||||
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
/* Execution Engine */
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
|
|
@ -1879,6 +1909,15 @@ static PyMethodDef core_methods[] = {
|
|||
_method( LLVMElementAtOffset )
|
||||
_method( LLVMOffsetOfElement )
|
||||
|
||||
/* Engine Builder */
|
||||
|
||||
_method( LLVMCreateEngineBuilder )
|
||||
_method( LLVMDisposeEngineBuilder )
|
||||
_method( LLVMEngineBuilderForceJIT )
|
||||
_method( LLVMEngineBuilderForceInterpreter )
|
||||
_method( LLVMEngineBuilderSetOptLevel )
|
||||
_method( LLVMEngineBuilderCreate )
|
||||
|
||||
/* Execution Engine */
|
||||
_method( LLVMCreateExecutionEngine )
|
||||
_method( LLVMDisposeExecutionEngine )
|
||||
|
|
|
|||
43
llvm/ee.py
43
llvm/ee.py
|
|
@ -145,7 +145,7 @@ class GenericValue(object):
|
|||
core.check_is_type(ty)
|
||||
ptr = _core.LLVMCreateGenericValueOfPointer(ty.ptr, intval)
|
||||
return GenericValue(ptr)
|
||||
|
||||
|
||||
def __init__(self, ptr):
|
||||
self.ptr = ptr
|
||||
|
||||
|
|
@ -172,6 +172,47 @@ def _unpack_generic_values(objlist):
|
|||
return _util.unpack_gen(objlist, check_is_generic_value)
|
||||
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
# Engine builder
|
||||
#===----------------------------------------------------------------------===
|
||||
|
||||
class EngineBuilder(object):
|
||||
@staticmethod
|
||||
def new(module):
|
||||
core.check_is_module(module)
|
||||
_util.check_is_unowned(module)
|
||||
obj = _core.LLVMCreateEngineBuilder(module.ptr)
|
||||
return EngineBuilder(obj, module)
|
||||
|
||||
def __init__(self, ptr, module):
|
||||
self.ptr = ptr
|
||||
self._module = module
|
||||
|
||||
def __del__(self):
|
||||
_core.LLVMDisposeEngineBuilder(self.ptr)
|
||||
|
||||
def force_jit(self):
|
||||
_core.LLVMEngineBuilderForceJIT(self.ptr)
|
||||
return self
|
||||
|
||||
def force_interpreter(self):
|
||||
_core.LLVMEngineBuilderForceInterpreter(self.ptr)
|
||||
return self
|
||||
|
||||
def opt(self, level):
|
||||
'''
|
||||
level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive]
|
||||
'''
|
||||
assert level in range(4)
|
||||
_core.LLVMEngineBuilderSetOptLevel(self.ptr, level)
|
||||
return self
|
||||
|
||||
def create(self):
|
||||
ret = _core.LLVMEngineBuilderCreate(self.ptr)
|
||||
if isinstance(ret, basestring):
|
||||
raise llvm.LLVMException(ret)
|
||||
return ExecutionEngine(ret, self._module)
|
||||
|
||||
#===----------------------------------------------------------------------===
|
||||
# Execution engine
|
||||
#===----------------------------------------------------------------------===
|
||||
|
|
|
|||
|
|
@ -69,13 +69,20 @@
|
|||
#include "llvm/Linker.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
|
||||
|
||||
|
||||
// LLVM-C includes
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
|
||||
// our includes
|
||||
#include "extra.h"
|
||||
#include "llvm_c_extra.h"
|
||||
|
||||
|
||||
namespace llvm{
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef)
|
||||
}
|
||||
/*
|
||||
* For use in LLVMDumpPasses to dump passes.
|
||||
*/
|
||||
|
|
@ -104,6 +111,58 @@ char *do_print(W obj)
|
|||
return strdup(buf.str().c_str());
|
||||
}
|
||||
|
||||
LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod)
|
||||
{
|
||||
using namespace llvm;
|
||||
return wrap(new EngineBuilder(unwrap(mod)));
|
||||
}
|
||||
|
||||
void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb)
|
||||
{
|
||||
delete llvm::unwrap(eb);
|
||||
}
|
||||
|
||||
void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb)
|
||||
{
|
||||
using namespace llvm;
|
||||
unwrap(eb)->setEngineKind(EngineKind::JIT);
|
||||
}
|
||||
|
||||
void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb)
|
||||
{
|
||||
using namespace llvm;
|
||||
unwrap(eb)->setEngineKind(EngineKind::Interpreter);
|
||||
}
|
||||
|
||||
void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level)
|
||||
{
|
||||
using namespace llvm;
|
||||
const CodeGenOpt::Level level_map[] = {
|
||||
CodeGenOpt::None,
|
||||
CodeGenOpt::Less,
|
||||
CodeGenOpt::Default,
|
||||
CodeGenOpt::Aggressive,
|
||||
};
|
||||
|
||||
unwrap(eb)->setOptLevel(level_map[level]);
|
||||
}
|
||||
|
||||
|
||||
LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, char **err)
|
||||
{
|
||||
using namespace llvm;
|
||||
std::string errstring;
|
||||
LLVMExecutionEngineRef ret;
|
||||
|
||||
ret = wrap(unwrap(eb)->setErrorStr(&errstring).create());
|
||||
|
||||
if ( !errstring.empty() ) {
|
||||
*err = strdup(errstring.c_str());
|
||||
return 0;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb)
|
||||
{
|
||||
|
|
@ -189,7 +248,8 @@ LLVMTypeRef LLVMStructTypeIdentified(const char * name)
|
|||
return wrap(StructType::create(getGlobalContext(), name));
|
||||
}
|
||||
|
||||
void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed)
|
||||
void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys,
|
||||
unsigned elemct, int is_packed)
|
||||
{
|
||||
using namespace llvm;
|
||||
ArrayRef<Type*> elemtys_aryref(unwrap(elemtys), elemct);
|
||||
|
|
|
|||
34
llvm/extra.h
34
llvm/extra.h
|
|
@ -39,10 +39,44 @@
|
|||
|
||||
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
||||
|
||||
#include "llvm_c_extra.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Wraps new EngineBuilder
|
||||
*/
|
||||
LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod);
|
||||
|
||||
/*
|
||||
* Wraps delete EngineBuilder
|
||||
*/
|
||||
void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb);
|
||||
|
||||
|
||||
/*
|
||||
* Wraps EngineBuilder::setEngineKind(EngineKind::JIT)
|
||||
*/
|
||||
void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb);
|
||||
|
||||
/*
|
||||
* Wraps EngineBuilder::setEngineKind(EngineKind::Interpreter)
|
||||
*/
|
||||
void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb);
|
||||
|
||||
|
||||
/*
|
||||
* Wraps EngineBuilder::setOptLevel
|
||||
*/
|
||||
void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level);
|
||||
|
||||
/*
|
||||
* Wraps EngineBuilder::setErrorStr and EngineBuilder::create
|
||||
*/
|
||||
LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, char **err);
|
||||
|
||||
/*
|
||||
* Wraps PassManagerBuilder::OptLevel
|
||||
*/
|
||||
|
|
|
|||
29
llvm/llvm_c_extra.h
Normal file
29
llvm/llvm_c_extra.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef LLVM_C_EXTRA_H_
|
||||
#define LLVM_C_EXTRA_H_
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Resurrect from llvm-c/Core.h
|
||||
#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \
|
||||
inline ty *unwrap(ref P) { \
|
||||
return reinterpret_cast<ty*>(P); \
|
||||
} \
|
||||
\
|
||||
inline ref wrap(const ty *P) { \
|
||||
return reinterpret_cast<ref>(const_cast<ty*>(P)); \
|
||||
}
|
||||
|
||||
typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //LLVM_C_EXTRA_H_
|
||||
|
||||
|
|
@ -77,6 +77,7 @@ _define_std_ctor(LLVMTargetDataRef)
|
|||
_define_std_ctor(LLVMGenericValueRef)
|
||||
|
||||
_define_std_ctor(LLVMPassManagerBuilderRef)
|
||||
_define_std_ctor(LLVMEngineBuilderRef)
|
||||
|
||||
PyObject *ctor_int(int i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,11 +45,14 @@
|
|||
#include "llvm-c/Analysis.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm-c/Target.h"
|
||||
|
||||
// workaround missing bool type
|
||||
#define bool int
|
||||
#include "llvm-c/Transforms/PassManagerBuilder.h"
|
||||
#undef bool
|
||||
|
||||
#include "llvm_c_extra.h"
|
||||
|
||||
/* Project-wide setting */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define LLVM_PY_USE_PYCAPSULE
|
||||
|
|
@ -88,8 +91,9 @@ _declare_std_ctor(LLVMExecutionEngineRef)
|
|||
_declare_std_ctor(LLVMTargetDataRef)
|
||||
_declare_std_ctor(LLVMGenericValueRef)
|
||||
|
||||
// extra LLVM class not defined in LLVM-C
|
||||
// extra LLVM classes
|
||||
_declare_std_ctor(LLVMPassManagerBuilderRef)
|
||||
_declare_std_ctor(LLVMEngineBuilderRef)
|
||||
|
||||
/* standard types */
|
||||
_declare_std_ctor(int)
|
||||
|
|
|
|||
56
test/enginebuilder.py
Normal file
56
test/enginebuilder.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
from llvm.ee import *
|
||||
from llvm.core import *
|
||||
from llvm import _util, LLVMException
|
||||
|
||||
from ctypes import *
|
||||
|
||||
import unittest, logging
|
||||
|
||||
class TestEngineBuilder(unittest.TestCase):
|
||||
|
||||
def make_test_module(self):
|
||||
module = Module.new("testmodule")
|
||||
fnty = Type.function(Type.int(), [])
|
||||
function = module.add_function(fnty, 'foo')
|
||||
bb_entry = function.append_basic_block('entry')
|
||||
builder = Builder.new(bb_entry)
|
||||
builder.ret(Constant.int(Type.int(), 0xcafe))
|
||||
module.verify()
|
||||
return module
|
||||
|
||||
def run_foo(self, ee, module):
|
||||
function = module.get_function_named('foo')
|
||||
retval = ee.run_function(function, [])
|
||||
self.assertEqual(retval.as_int(), 0xcafe)
|
||||
|
||||
|
||||
def test_enginebuilder_basic(self):
|
||||
module = self.make_test_module()
|
||||
ee = EngineBuilder.new(module).create()
|
||||
|
||||
with self.assertRaises(LLVMException):
|
||||
# Ensure the module is owned.
|
||||
_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()
|
||||
|
||||
self.run_foo(ee, module)
|
||||
|
||||
def test_enginebuilder_force_interpreter(self):
|
||||
module = self.make_test_module()
|
||||
ee = EngineBuilder.new(module).force_interpreter().create()
|
||||
|
||||
self.run_foo(ee, module)
|
||||
|
||||
def test_enginebuilder_opt(self):
|
||||
module = self.make_test_module()
|
||||
ee = EngineBuilder.new(module).opt(3).create()
|
||||
|
||||
self.run_foo(ee, module)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue