Added EngineBuilder.

Added test/enginebuilder.
This commit is contained in:
Siu Kwan Lam 2012-07-25 15:31:18 -07:00
commit 5bb4b8affb
8 changed files with 267 additions and 3 deletions

View file

@ -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 )

View file

@ -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
#===----------------------------------------------------------------------===

View file

@ -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);

View file

@ -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
View 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_

View file

@ -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)
{

View file

@ -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
View 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()