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:
parent
6ee3298bd2
commit
2255a7e5dd
15 changed files with 559 additions and 396 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
104
llvm/_core.c
104
llvm/_core.c
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
498
llvm/core.py
498
llvm/core.py
File diff suppressed because it is too large
Load diff
67
llvm/ee.py
67
llvm/ee.py
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,9 @@ PyObject *ctor_int(int i)
|
|||
return PyInt_FromLong(i);
|
||||
}
|
||||
|
||||
_define_std_ctor(LLVMExecutionEngineRef)
|
||||
_define_std_ctor(LLVMTargetDataRef)
|
||||
|
||||
|
||||
/*===----------------------------------------------------------------------===*/
|
||||
/* Helper functions */
|
||||
|
|
|
|||
32
llvm/wrap.h
32
llvm/wrap.h
|
|
@ -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()
|
||||
|
|
|
|||
10
setup.py
10
setup.py
|
|
@ -17,7 +17,8 @@ def get_libs_and_objs(llvm_config, components):
|
|||
libs.append(part[2:])
|
||||
else:
|
||||
assert part.endswith('.o')
|
||||
objs.append(part[:-2])
|
||||
# objs.append(part[:-2])
|
||||
objs.append(part) # eh, looks like we need the .o after all
|
||||
return (libs, objs)
|
||||
|
||||
|
||||
|
|
@ -42,8 +43,11 @@ def get_llvm_config():
|
|||
def call_setup(llvm_config):
|
||||
|
||||
incdir = _run(llvm_config + ' --includedir')
|
||||
libdir = _run(llvm_config + ' --libdir')
|
||||
ldflags = _run(llvm_config + ' --ldflags')
|
||||
libs_core, objs_core = get_libs_and_objs(llvm_config, ['core', 'analysis', 'scalaropts'])
|
||||
libs_core, objs_core = get_libs_and_objs(llvm_config,
|
||||
['core', 'analysis', 'scalaropts', 'executionengine',
|
||||
'jit', 'native'])
|
||||
|
||||
std_libs = [ 'pthread', 'dl', 'm' ]
|
||||
|
||||
|
|
@ -54,7 +58,7 @@ def call_setup(llvm_config):
|
|||
('__STDC_LIMIT_MACROS', None),
|
||||
('_GNU_SOURCE', None)],
|
||||
include_dirs = [incdir],
|
||||
library_dirs = [ '/home/mdevan/llvm/Release/lib' ],
|
||||
library_dirs = [libdir],
|
||||
libraries = std_libs + libs_core,
|
||||
extra_objects = objs_core)
|
||||
|
||||
|
|
|
|||
|
|
@ -26,18 +26,18 @@ entry = func.append_basic_block("entry")
|
|||
builder = Builder.new()
|
||||
builder.position_at_end(entry)
|
||||
|
||||
# add two args into temp1
|
||||
temp1 = builder.add(func.args[0], func.args[1], "temp1")
|
||||
# add two args into tmp1
|
||||
tmp1 = builder.add(func.args[0], func.args[1], "tmp1")
|
||||
|
||||
# sub `1' from that
|
||||
one = Constant.real( ty_double, 1.0 )
|
||||
temp2 = builder.sub(temp1, one, "temp2")
|
||||
tmp2 = builder.sub(tmp1, one, "tmp2")
|
||||
|
||||
# convert to integer
|
||||
temp3 = builder.fptoui(temp2, ty_int, "temp3")
|
||||
tmp3 = builder.fptoui(tmp2, ty_int, "tmp3")
|
||||
|
||||
# return it
|
||||
builder.ret(temp3)
|
||||
builder.ret(tmp3)
|
||||
|
||||
# dump the module to see the bc
|
||||
module.dump()
|
||||
# dump the module to see the llvm "assembly" code
|
||||
print module
|
||||
|
|
|
|||
26
test/test.py
26
test/test.py
|
|
@ -5,6 +5,7 @@ import gc
|
|||
|
||||
import unittest, sys
|
||||
|
||||
from llvm import *
|
||||
from llvm.core import *
|
||||
|
||||
class TestModule(unittest.TestCase):
|
||||
|
|
@ -23,6 +24,7 @@ class TestModule(unittest.TestCase):
|
|||
m = Module.new("temp_m")
|
||||
return ModuleProvider.new(m)
|
||||
|
||||
# check basic ownership and deletion
|
||||
m = Module.new("test1.1")
|
||||
self.assertEqual(m.owner, None)
|
||||
mp = ModuleProvider.new(m)
|
||||
|
|
@ -34,14 +36,19 @@ class TestModule(unittest.TestCase):
|
|||
m = None
|
||||
self.assertEqual(gc.garbage, [])
|
||||
|
||||
# delete a module which was owned by a module provider that has
|
||||
# gone out of scope
|
||||
m2 = Module.new("test1.2")
|
||||
temp_mp(m2)
|
||||
del m2
|
||||
self.assertEqual(gc.garbage, [])
|
||||
|
||||
# delete a module provider object which owned a module that has
|
||||
# gone out of scope
|
||||
mp3 = temp_m()
|
||||
mp3 = None
|
||||
|
||||
# check ref counts
|
||||
m4 = Module.new("test1.4")
|
||||
self.assertEqual(sys.getrefcount(m4), 1+1)
|
||||
mp4 = ModuleProvider.new(m4)
|
||||
|
|
@ -51,14 +58,16 @@ class TestModule(unittest.TestCase):
|
|||
self.assertEqual(sys.getrefcount(mp4), 1+1)
|
||||
mp4 = None
|
||||
|
||||
own_works = False
|
||||
# cannot create a second module provider object for the same
|
||||
# module
|
||||
works = False
|
||||
m5 = Module.new("test1.5")
|
||||
mp5 = ModuleProvider.new(m5)
|
||||
try:
|
||||
m5._own(None)
|
||||
except AssertionError:
|
||||
own_works = True
|
||||
self.assertEqual(own_works, True)
|
||||
mp5_2 = ModuleProvider.new(m5)
|
||||
except LLVMException:
|
||||
works = True
|
||||
self.assertEqual(works, True)
|
||||
|
||||
|
||||
def testdata_layout(self):
|
||||
|
|
@ -70,6 +79,7 @@ class TestModule(unittest.TestCase):
|
|||
reqd = '; ModuleID = \'test2.1\'\ntarget datalayout = "some_value"\n'
|
||||
self.assertEqual(str(m), reqd)
|
||||
|
||||
|
||||
def testtarget(self):
|
||||
"""Target property."""
|
||||
m = Module.new("test3.1")
|
||||
|
|
@ -79,6 +89,7 @@ class TestModule(unittest.TestCase):
|
|||
reqd = '; ModuleID = \'test3.1\'\ntarget triple = "some_value"\n'
|
||||
self.assertEqual(str(m), reqd)
|
||||
|
||||
|
||||
def testtype_name(self):
|
||||
"""Type names."""
|
||||
m = Module.new("test4.1")
|
||||
|
|
@ -95,15 +106,16 @@ class TestModule(unittest.TestCase):
|
|||
reqd = "; ModuleID = 'test4.1'\n"
|
||||
self.assertEqual(str(m), reqd)
|
||||
|
||||
|
||||
def testglobal_variable(self):
|
||||
"""Global variables."""
|
||||
m = Module.new("test5.1")
|
||||
t = Type.int()
|
||||
gv = m.add_global_variable(t, "gv")
|
||||
print m
|
||||
self.assertNotEqual(gv, None)
|
||||
self.assertEqual(gv.name, "gv")
|
||||
self.assertEqual(gv.type, t)
|
||||
self.assertEqual(gv.type, Type.pointer(t))
|
||||
|
||||
|
||||
def main():
|
||||
gc.set_debug(gc.DEBUG_LEAK)
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ About
|
|||
[NOTE]
|
||||
._llvm-py_ Mission Statement
|
||||
=======================================================================
|
||||
Provide a simple, consistent and well-documented suite of APIs
|
||||
that exposes just enough of LLVM to write a compiler/interpreter/VM
|
||||
in Python.
|
||||
Provide a simple, consistent and well-documented suite of APIs that
|
||||
exposes just enough of LLVM to write a compiler/VM in Python.
|
||||
=======================================================================
|
||||
|
||||
_llvm-py_ is developed by Mahadevan R, in his spare time, without being
|
||||
paid for it. He can be reached at _mdevan.foobar .at. gmail.com_, on the
|
||||
llvm-dev mailing list and irc.oftc.net#llvm (mdevan).
|
||||
|
||||
These web pages were generated using the nifty tool
|
||||
http://www.methods.co.nz/asciidoc/[asciidoc].
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ grow up. Please contribute! All patches are welcome.
|
|||
|
||||
The _llvm-py_ code is hosted on a google code project by the same name,
|
||||
http://code.google.com/p/llvm-py/[here]. It provides the SVN repository
|
||||
and a http://code.google.com/p/llvm-py/issues/list[bug tracker].
|
||||
|
||||
The latest code can be checked out from SVN like so:
|
||||
and a http://code.google.com/p/llvm-py/issues/list[bug tracker]. The
|
||||
latest code can be checked out from SVN like so:
|
||||
|
||||
----
|
||||
$ svn checkout http://llvm-py.googlecode.com/svn/trunk/ llvm-py
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
Download and Setup
|
||||
==================
|
||||
|
||||
The latest release is 0.2, released xx-Jun-2008 (full link:changelog[Changelog]
|
||||
The latest release is 0.2, released xx-Jun-2008 (full link:#changelog[Changelog]
|
||||
below).
|
||||
|
||||
Download it here:
|
||||
|
|
@ -10,8 +10,8 @@ Download it here:
|
|||
````~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Release,Date,Package,Mirror
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
0.2,xx-xxx-2008,http://link1/[llvm-py-0.2.tar.bz2],http://link1/[llvm-py-0.2.tar.bz2]
|
||||
0.1,xx-xxx-2008,http://link1/[llvm-py-0.1.tar.bz2],http://link1/[llvm-py-0.1.tar.bz2]
|
||||
0.2,xx-May-2008,http://llvm-py.googlecode.com/files/llvm-py-0.2.tar.bz2[llvm-py-0.2.tar.bz2],link:llvm-py-0.2.tar.bz2[llvm-py-0.2.tar.bz2]
|
||||
0.1,20-May-2008,http://llvm-py.googlecode.com/files/llvm-py-0.1.tar.bz2[llvm-py-0.1.tar.bz2],link:llvm-py-0.1.tar.bz2[llvm-py-0.1.tar.bz2]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
|
@ -32,6 +32,7 @@ Setting Up
|
|||
|
||||
Follow these steps to get _llvm-py_ up and running:
|
||||
|
||||
* link:#uninstall[Uninstall] any previous version of _llvm-py_.
|
||||
* Get and build LLVM.
|
||||
* Optionally, install it.
|
||||
* Get the latest release (see above) of _llvm-py_ and untar it:
|
||||
|
|
@ -54,11 +55,28 @@ $ sudo python setup.py install --llvm-config=/path/to/llvm-config
|
|||
|
||||
That's it!
|
||||
|
||||
NOTE: _setup.py_ is a standard Python distutils script. See the Python
|
||||
documentation regarding http://docs.python.org/inst/inst.html[Installing
|
||||
Python Modules] and http://docs.python.org/dist/dist.html[Distributing
|
||||
Python Modules] for more information on such scripts.
|
||||
.Notes:
|
||||
- _setup.py_ is a standard Python distutils script. See the Python
|
||||
documentation regarding
|
||||
http://docs.python.org/inst/inst.html[Installing Python Modules] and
|
||||
http://docs.python.org/dist/dist.html[Distributing Python Modules] for
|
||||
more information on such scripts.
|
||||
|
||||
- To build the debug version, build with the +-g+ flag and the debug
|
||||
version of llvm-config:
|
||||
+
|
||||
----
|
||||
$ python setup.py build -g --llvm-config=/path/to/Debug/bin/llvm-config
|
||||
$ sudo python setup.py install
|
||||
----
|
||||
|
||||
- Debug binaries are _huge_! (65 MB+)
|
||||
|
||||
- If +++--llvm-config+++ is not specified, +setup.py+ looks for
|
||||
+llvm-config+ in the +PATH+, which will succeed if LLVM is installed.
|
||||
|
||||
|
||||
[[uninstall]]
|
||||
Uninstall
|
||||
---------
|
||||
|
||||
|
|
@ -69,8 +87,9 @@ To get rid of llvm-py completely, if you wish to do so:
|
|||
# rm -f /usr/lib/python2.5/site-packages/llvm_py-0.1.egg-info
|
||||
----
|
||||
|
||||
You'll need to be root to do this. Paths are for debian-based systems,
|
||||
in other distros it might be different.
|
||||
- You need to be root to do this.
|
||||
- Paths are for debian-based systems, in other distros it might be different.
|
||||
- Note that there is a version number in the egg file name.
|
||||
|
||||
|
||||
[[changelog]]
|
||||
|
|
@ -78,5 +97,5 @@ Changelog
|
|||
----------
|
||||
|
||||
----
|
||||
include::changelog[]
|
||||
include::../../CHANGELOG[]
|
||||
----
|
||||
|
|
|
|||
|
|
@ -5,49 +5,7 @@ Here's an example:
|
|||
|
||||
[python]
|
||||
source~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#!/usr/bin/env python
|
||||
|
||||
from llvm.core import *
|
||||
|
||||
## create a module
|
||||
module = Module.new("my_module")
|
||||
|
||||
## create a function type taking two doubles and returning a (32-bit) integer
|
||||
ty_double = Type.double()
|
||||
ty_int = Type.int()
|
||||
ty_func = Type.function( ty_int, [ ty_double, ty_double ] )
|
||||
|
||||
## create a function of this type
|
||||
func = Function.new( module, ty_func, "foobar" )
|
||||
|
||||
# name function args
|
||||
func.args[0].name = "arg1"
|
||||
func.args[1].name = "arg2"
|
||||
|
||||
## implement the function
|
||||
|
||||
# add a basic block
|
||||
entry = func.append_basic_block("entry")
|
||||
|
||||
# create an llvm::IRBuilder
|
||||
builder = Builder.new()
|
||||
builder.position_at_end(entry)
|
||||
|
||||
# add two args into temp1
|
||||
temp1 = builder.add(func.args[0], func.args[1], "temp1")
|
||||
|
||||
# sub `1' from that
|
||||
one = Constant.real( ty_double, 1.0 )
|
||||
temp2 = builder.sub(temp1, one, "temp2")
|
||||
|
||||
# convert to integer
|
||||
temp3 = builder.fptoui(temp2, ty_int, "temp3")
|
||||
|
||||
# return it
|
||||
builder.ret(temp3)
|
||||
|
||||
# dump the module to see the bc
|
||||
module.dump()
|
||||
include::../../test/example.py[]
|
||||
source~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
which gives this output:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue