Execution engine and passes work. Documentation and tests updated.

git-svn-id: http://llvm-py.googlecode.com/svn/trunk@4 8d1e9007-1d4e-0410-b67e-1979fd6579aa
This commit is contained in:
mdevan.foobar 2008-06-07 13:44:25 +00:00
commit 2255a7e5dd
15 changed files with 559 additions and 396 deletions

View file

@ -12,3 +12,28 @@ class LLVMException(Exception):
Exception.__init__(self, msg)
#===----------------------------------------------------------------------===
# Ownables
#===----------------------------------------------------------------------===
class Ownable(object):
def __init__(self, ptr, del_fn):
self.ptr = ptr
self.owner = None
self.del_fn = del_fn
def _own(self, owner):
if self.owner:
raise LLVMException, "object already owned"
self.owner = owner
def _disown(self):
if not self.owner:
raise LLVMException, "not owned"
self.owner = None
def __del__(self):
if not self.owner:
self.del_fn(self.ptr)

View file

@ -6,6 +6,7 @@
/* LLVM includes */
#include "llvm-c/Analysis.h"
#include "llvm-c/Transforms/Scalar.h"
#include "llvm-c/ExecutionEngine.h"
/* libc includes */
#include <stdarg.h> /* for malloc(), free() */
@ -617,6 +618,97 @@ _wrap_obj2none(LLVMAddGVNPass, LLVMPassManagerRef)
_wrap_obj2none(LLVMAddCFGSimplificationPass, LLVMPassManagerRef)
/*===----------------------------------------------------------------------===*/
/* Target Data */
/*===----------------------------------------------------------------------===*/
_wrap_str2obj(LLVMCreateTargetData, LLVMTargetDataRef)
_wrap_obj2none(LLVMDisposeTargetData, LLVMTargetDataRef)
static PyObject *
_wLLVMTargetDataAsString(PyObject *self, PyObject *args)
{
PyObject *obj;
LLVMTargetDataRef td;
char *tdrep = 0;
PyObject *ret;
if (!PyArg_ParseTuple(args, "O", &obj))
return NULL;
td = (LLVMTargetDataRef) PyCObject_AsVoidPtr(obj);
tdrep = LLVMCopyStringRepOfTargetData(td);
ret = PyString_FromString(tdrep);
LLVMDisposeMessage(tdrep);
return ret;
}
_wrap_objobj2none(LLVMAddTargetData, LLVMTargetDataRef, LLVMPassManagerRef)
/*===----------------------------------------------------------------------===*/
/* Execution Engine */
/*===----------------------------------------------------------------------===*/
static PyObject *
_wLLVMCreateExecutionEngine(PyObject *self, PyObject *args)
{
LLVMModuleProviderRef mp;
PyObject *obj;
int force_interpreter;
LLVMExecutionEngineRef ee;
char *outmsg;
PyObject *ret;
int error;
if (!PyArg_ParseTuple(args, "Oi", &obj, &force_interpreter))
return NULL;
mp = (LLVMModuleProviderRef) PyCObject_AsVoidPtr(obj);
if (force_interpreter)
error = LLVMCreateInterpreter(&ee, mp, &outmsg);
else
error = LLVMCreateJITCompiler(&ee, mp, &outmsg);
if (error) {
ret = PyString_FromString(outmsg);
LLVMDisposeMessage(outmsg);
} else {
ret = ctor_LLVMExecutionEngineRef(ee);
}
return ret;
}
_wrap_obj2none(LLVMDisposeExecutionEngine, LLVMExecutionEngineRef)
static PyObject *
_wLLVMRunFunction(PyObject *self, PyObject *args)
{
PyObject *obj1, *obj2, *obj3;
LLVMExecutionEngineRef ee;
LLVMValueRef fn;
if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3))
return NULL;
/* obj3 is a list of args to the function, ignored currently */
ee = (LLVMExecutionEngineRef) PyCObject_AsVoidPtr(obj1);
fn = (LLVMValueRef) PyCObject_AsVoidPtr(obj2);
LLVMRunFunction(ee, fn, 0, NULL);
/* fn return value ignore currently */
Py_RETURN_NONE;
}
_wrap_obj2obj(LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef,
LLVMTargetDataRef)
/*===----------------------------------------------------------------------===*/
/* Python member method table */
/*===----------------------------------------------------------------------===*/
@ -948,6 +1040,18 @@ static PyMethodDef core_methods[] = {
_method( LLVMAddGVNPass )
_method( LLVMAddCFGSimplificationPass )
/* Target Data */
_method( LLVMCreateTargetData )
_method( LLVMDisposeTargetData )
_method( LLVMTargetDataAsString )
_method( LLVMAddTargetData )
/* Execution Engine */
_method( LLVMCreateExecutionEngine )
_method( LLVMDisposeExecutionEngine )
_method( LLVMRunFunction )
_method( LLVMGetExecutionEngineTargetData )
{ NULL }
};

View file

@ -1,12 +1,19 @@
"""Utility functions and classes.
Not for public use!"""
Used only in other modules, not for public use."""
import core
import llvm
#===----------------------------------------------------------------------===
# A set of helpers to check various things. Raises exceptions on
# failures.
#===----------------------------------------------------------------------===
def _check_gen(obj, type):
if not isinstance(obj, type):
msg = "argument must be an instance of llvm.core.%s (or of a class derived from it)" % type_str
msg = "argument not an instance of llvm.core.%s" % type_str
raise TypeError, msg
def check_is_type(obj): _check_gen(obj, core.Type)
@ -15,25 +22,54 @@ def check_is_pointer(obj): _check_gen(obj, core.Pointer)
def check_is_constant(obj): _check_gen(obj, core.Constant)
def check_is_function(obj): _check_gen(obj, core.Function)
def check_is_basic_block(obj): _check_gen(obj, core.BasicBlock)
def check_is_module(obj): _check_gen(obj, core.Module)
def check_is_module_provider(obj): _check_gen(obj, core.ModuleProvider)
def unpack_gen(objlist, check_fn):
def check_is_unowned(ownable):
if ownable.owner:
raise llvm.LLVMException, "object is already owned"
#===----------------------------------------------------------------------===
# A set of helpers to unpack a list of Python wrapper objects
# into a list of PyCObject wrapped objects, checking types along
# the way.
#===----------------------------------------------------------------------===
def _unpack_gen(objlist, check_fn):
for obj in objlist: check_fn(obj)
return [ obj.ptr for obj in objlist ]
def unpack_types(objlist): return unpack_gen(objlist, check_is_type)
def unpack_values(objlist): return unpack_gen(objlist, check_is_value)
def unpack_constants(objlist): return unpack_gen(objlist, check_is_constant)
def unpack_types(objlist): return _unpack_gen(objlist, check_is_type)
def unpack_values(objlist): return _unpack_gen(objlist, check_is_value)
def unpack_constants(objlist): return _unpack_gen(objlist, check_is_constant)
#===----------------------------------------------------------------------===
# Helper to wrap over iterables (LLVMFirstXXX, LLVMNextXXX). This used
# to be a generator, but that loses subscriptability of the result, so
# we now return a list.
#===----------------------------------------------------------------------===
def wrapiter(first, next, container, wrapper):
# ptr = first(container)
# while ptr:
# yield wrapper(ptr)
# ptr = next(ptr)
ret = []
ptr = first(container)
while ptr:
yield wrapper(ptr)
ret.append(wrapper(ptr))
ptr = next(ptr)
return ret
#===----------------------------------------------------------------------===
# Dummy owner, will not delete ownee. Be careful.
#===----------------------------------------------------------------------===
class dummy_owner(object):
def __init__(self, ownee):
ownee._own(self)

File diff suppressed because it is too large Load diff

View file

@ -2,50 +2,61 @@
"""
import llvm, core
from _util import *
import _core
import llvm # top-level, for common stuff
import core # module provider, function etc.
import _core # C wrappers
from _util import * # utility functions
#===----------------------------------------------------------------------===
# Target data
#===----------------------------------------------------------------------===
class TargetData(llvm.Ownable):
@staticmethod
def new(strrep):
return TargetData(_core.LLVMCreateTargetData(strrep))
def __init__(self, ptr):
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetData)
def __del__(self):
llvm.Ownable.__del__(self)
def __str__(self):
return _core.LLVMTargetDataAsString(self.ptr)
#===----------------------------------------------------------------------===
# Execution engine
#===----------------------------------------------------------------------===
class ExecutionEngine(object):
@staticmethod
def new(mp, force_interpreter=False):
check_is_module_provider(mp)
ret = _core.LLVMCreateExecutionEngine(mp.ptr, int(create_interpreter))
check_is_unowned(mp)
ret = _core.LLVMCreateExecutionEngine(mp.ptr, int(force_interpreter))
if isinstance(ret, str):
raise llvm.LLVMException, str
return ExecutionEngine(ret)
raise llvm.LLVMException, ret
return ExecutionEngine(ret, mp)
def __init__(self, ptr):
def __init__(self, ptr, mp):
self.ptr = ptr
mp._own(self)
def __del__(self):
_core.LLVMDisposeExecutionEngine(self.ptr)
def run_static_constructors(self):
_core.LLVMRunStaticConstructors(self.ptr)
def run_static_destructors(self):
_core.LLVMRunStaticDestructors(self.ptr)
def run_function_as_main(self, fn, argv, envp):
check_is_function(fn)
_core.LLVMRunFunctionAsMain(self.ptr, fn.ptr, argv, envp)
def run_function(self, fn, args):
check_is_function(fn)
return _core.LLVMRunFunction(self.ptr, fn.ptr, args)
def free_machine_code_for_function(self, fn):
check_is_function(fn)
_core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr)
def add_module_provider(self, mp):
pass
def remove_module_provider(self):
pass
@property
def target_data(self):
return TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr))
td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr))
td._own(self)
return td

View file

@ -1,6 +1,11 @@
"""Pass managers and passes.
"""
import ee # target data
import _core # C wrappers
from _util import * # utility functions
from _util import *
import _core
# passes
PASS_CONSTANT_PROPAGATION = 1
@ -43,9 +48,19 @@ class PassManager(object):
def __del__(self):
_core.LLVMDisposePassManager(self.ptr)
def add(self, pass_id):
assert pass_id in _pass_creator, 'Invalid pass_id ("' + str(pass_id) + '")'
cfn = _pass_creator[pass_id] # KeyError => pass_id is invalid
def add(self, tgt_data_or_pass_id):
if isinstance(tgt_data_or_pass_id, ee.TargetData):
self._add_target_data(tgt_data_or_pass_id)
elif tgt_data_or_pass_id in _pass_creator:
self._add_pass(tgt_data_or_pass_id)
else:
raise LLVMException, "invalid pass_id"
def _add_target_data(self, tgt):
_core.LLVMAddTargetData(tgt.ptr, self.ptr)
def _add_pass(self, pass_id):
cfn = _pass_creator[pass_id]
cfn(self.ptr)
def run(self, module):
@ -70,8 +85,8 @@ class FunctionPassManager(PassManager):
_core.LLVMInitializeFunctionPassManager(self.ptr)
def run(self, fn):
_check_is_function(fn)
return _core.LLVMRunFunctionPassManager(fn.ptr)
check_is_function(fn)
return _core.LLVMRunFunctionPassManager(self.ptr, fn.ptr)
def finalize(self):
_core.LLVMFinalizeFunctionPassManager(self.ptr)

View file

@ -74,6 +74,9 @@ PyObject *ctor_int(int i)
return PyInt_FromLong(i);
}
_define_std_ctor(LLVMExecutionEngineRef)
_define_std_ctor(LLVMTargetDataRef)
/*===----------------------------------------------------------------------===*/
/* Helper functions */

View file

@ -13,6 +13,8 @@
/* llvm includes */
#include "llvm-c/Core.h"
#include "llvm-c/Analysis.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm-c/Target.h"
/*===----------------------------------------------------------------------===*/
@ -56,6 +58,20 @@ PyObject *ctor_LLVMPassManagerRef(LLVMPassManagerRef p);
/* standard types */
PyObject *ctor_int(int i);
#define _declare_std_ctor(typ) \
PyObject * ctor_ ## typ ( typ p);
#define _define_std_ctor(typ) \
PyObject * ctor_ ## typ ( typ p) \
{ \
if (p) \
return PyCObject_FromVoidPtr(p, NULL); \
Py_RETURN_NONE; \
}
_declare_std_ctor(LLVMExecutionEngineRef)
_declare_std_ctor(LLVMTargetDataRef)
/*===----------------------------------------------------------------------===*/
/* Helper methods */
@ -257,6 +273,22 @@ _w ## func (PyObject *self, PyObject *args) \
return ctor_ ## outtype ( func (arg1, arg2, arg3)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(const char *s)
*/
#define _wrap_str2obj(func, outtype) \
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
const char *arg1; \
\
if (!PyArg_ParseTuple(args, "s", &arg1)) \
return NULL; \
\
return ctor_ ## outtype ( func (arg1)); \
}
/**
* Wrap LLVM functions of the type
* outtype func()