New tests. Code cleanup.

git-svn-id: http://llvm-py.googlecode.com/svn/trunk@11 8d1e9007-1d4e-0410-b67e-1979fd6579aa
This commit is contained in:
mdevan.foobar 2008-06-14 19:05:45 +00:00
commit 274f0f9ec4
16 changed files with 638 additions and 113 deletions

View file

@ -12,6 +12,7 @@
* Python doc string documentation added (still incomplete)
* Many minor style/cosmetic changes and bug fixes
* Added documentation as on website into SVN
* Lots of cleanup
0.1, 10-May-2008:

15
README
View file

@ -2,28 +2,23 @@
llvm-py: Python Bindings for LLVM
---------------------------------
llvm-py provides Python bindings for LLVM.
Home page:
----------
http://mdevan.nfshost.com/llvm-py.html
http://code.google.com/p/llvm-py/
http://mdevan.nfshost.com/llvm-py/
Quickstart:
----------
1. Get 2.3svn version of LLVM, build it. 2.2 or earlier will *not* work.
LLVM need not be installed.
1. Get 2.3 version of LLVM, build it. 2.2 or earlier will *not* work.
2. Unpack llvm-py, build and install:
$ tar jxvf llvm-py-0.2.tar.bz2
$ cd llvm-py-0.2
# if you've installed LLVM, and llvm-config is in the path
$ sudo python setup.py install
# if you've just built LLVM and not installed it, locate llvm-config,
# usually under ../llvm/Release/bin
# Locate llvm-config, usually under <llvm>/Release/bin
$ sudo python setup.py install --llvm-config=/path/to/llvm-config
3. See examples under 'test' directory.

View file

@ -355,7 +355,20 @@ _wrap_obj2obj(LLVMGetFunctionCallConv, LLVMValueRef, int)
_wrap_objint2none(LLVMSetFunctionCallConv, LLVMValueRef)
_wrap_obj2str(LLVMGetCollector, LLVMValueRef)
_wrap_objstr2none(LLVMSetCollector, LLVMValueRef)
_wrap_objint2obj(LLVMVerifyFunction, LLVMValueRef, int)
static PyObject *
_wLLVMVerifyFunction(PyObject *self, PyObject *args)
{
PyObject *obj;
LLVMValueRef fn;
if (!PyArg_ParseTuple(args, "O", &obj))
return NULL;
fn = (LLVMValueRef) PyCObject_AsVoidPtr(obj);
return ctor_int(LLVMVerifyFunction(fn, LLVMReturnStatusAction));
}
/*===-- Arguments --------------------------------------------------------===*/
@ -407,27 +420,6 @@ _wrap_objint2obj(LLVMGetIncomingBlock, LLVMValueRef, LLVMBasicBlockRef)
/*===-- Instruction builders ----------------------------------------------===*/
_wrap_none2obj(LLVMCreateBuilder, LLVMBuilderRef)
static PyObject *
_wLLVMPositionBuilder(PyObject *self, PyObject *args)
{
PyObject *obj1, *obj2, *obj3 = 0;
LLVMBuilderRef builder;
LLVMBasicBlockRef block;
LLVMValueRef instr = NULL;
if (!PyArg_ParseTuple(args, "OO|O", &obj1, &obj2, &obj3))
return NULL;
builder = (LLVMBuilderRef) (PyCObject_AsVoidPtr(obj1));
block = (LLVMBasicBlockRef)(PyCObject_AsVoidPtr(obj2));
if (obj3) /* optional */
instr = (LLVMValueRef)(PyCObject_AsVoidPtr(obj3));
LLVMPositionBuilder(builder, block, instr);
Py_RETURN_NONE;
}
_wrap_objobj2none(LLVMPositionBuilderBefore, LLVMBuilderRef, LLVMValueRef)
_wrap_objobj2none(LLVMPositionBuilderAtEnd, LLVMBuilderRef, LLVMBasicBlockRef)
_wrap_obj2obj(LLVMGetInsertBlock, LLVMBuilderRef, LLVMBasicBlockRef)
@ -946,7 +938,6 @@ static PyMethodDef core_methods[] = {
/* Instruction builders */
_method( LLVMCreateBuilder )
_method( LLVMPositionBuilder )
_method( LLVMPositionBuilderBefore )
_method( LLVMPositionBuilderAtEnd )
_method( LLVMGetInsertBlock )

View file

@ -13,6 +13,7 @@ import llvm
def _check_gen(obj, type):
if not isinstance(obj, type):
type_str = type.__name__
msg = "argument not an instance of llvm.core.%s" % type_str
raise TypeError, msg
@ -51,7 +52,7 @@ def unpack_constants(objlist): return _unpack_gen(objlist, check_is_constant)
# we now return a list.
#===----------------------------------------------------------------------===
def wrapiter(first, next, container, wrapper):
def wrapiter(first, next, container, wrapper, extra=[]):
# ptr = first(container)
# while ptr:
# yield wrapper(ptr)
@ -59,7 +60,7 @@ def wrapiter(first, next, container, wrapper):
ret = []
ptr = first(container)
while ptr:
ret.append(wrapper(ptr))
ret.append(wrapper(ptr, *extra))
ptr = next(ptr)
return ret

View file

@ -132,9 +132,6 @@ class Module(llvm.Ownable):
"""
llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule)
def __del__(self):
llvm.Ownable.__del__(self)
def __str__(self):
"""Text representation of a module.
@ -212,7 +209,7 @@ class Module(llvm.Ownable):
# do stuff with gv
"""
return wrapiter(_core.LLVMGetFirstGlobal, _core.LLVMGetNextGlobal,
self.ptr, GlobalVariable)
self.ptr, GlobalVariable, [self])
def add_function(self, ty, name):
"""Add a function of given type with given name."""
@ -233,9 +230,13 @@ class Module(llvm.Ownable):
# do stuff with f
"""
return wrapiter(_core.LLVMGetFirstFunction,
_core.LLVMGetNextFunction, self.ptr, Function)
_core.LLVMGetNextFunction, self.ptr, Function, [self])
def verify(self):
"""Verify module.
Checks module for errors. Raises `llvm.LLVMException' on any
error."""
ret = _core.LLVMVerifyModule(self.ptr)
if ret != "":
raise llvm.LLVMException, ret
@ -267,6 +268,7 @@ class Type(object):
elif bits == 64:
return _make_type(_core.LLVMInt64Type(), TYPE_INTEGER)
else:
bits = int(bits) # bits must be an int
return _make_type(_core.LLVMIntType(bits), TYPE_INTEGER)
@staticmethod
@ -306,7 +308,8 @@ class Type(object):
check_is_type(return_ty)
var_arg = 1 if var_arg else 0 # convert to int
params = unpack_types(param_tys)
return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, var_arg), TYPE_FUNCTION)
return _make_type(_core.LLVMFunctionType(return_ty.ptr, params,
var_arg), TYPE_FUNCTION)
@staticmethod
def struct(element_tys): # not packed
@ -314,7 +317,7 @@ class Type(object):
Creates a structure type with elements of types as given in the
iterable `element_tys'. This method creates a unpacked
structure. For a packed one, use packed_struct() method."""
structure. For a packed one, use the packed_struct() method."""
elems = unpack_types(element_tys)
return _make_type(_core.LLVMStructType(elems, 0), TYPE_STRUCT)
@ -324,42 +327,77 @@ class Type(object):
Creates a structure type with elements of types as given in the
iterable `element_tys'. This method creates a packed
structure. For an unpacked one, use struct() method."""
structure. For an unpacked one, use the struct() method."""
elems = unpack_types(element_tys)
return _make_type(_core.LLVMStructType(elems, 1), TYPE_STRUCT)
@staticmethod
def array(element_ty, count):
"""Create an array type.
Creates a type for an array of elements of type `element_ty',
having 'count' elements."""
check_is_type(element_ty)
return _make_type(_core.LLVMArrayType(element_ty.ptr, count), TYPE_ARRAY)
count = int(count) # must be an int
return _make_type(_core.LLVMArrayType(element_ty.ptr, count),
TYPE_ARRAY)
@staticmethod
def pointer(pointee_ty, addr_space=0):
"""Create a pointer type.
Creates a pointer type, which can point to values of type
`pointee_ty', in the address space `addr_space'."""
check_is_type(pointee_ty)
return _make_type(_core.LLVMPointerType(pointee_ty.ptr, addr_space), TYPE_POINTER)
addr_space = int(addr_space) # must be an int
return _make_type(_core.LLVMPointerType(pointee_ty.ptr,
addr_space), TYPE_POINTER)
@staticmethod
def vector(element_ty, count):
"""Create a vector type.
Creates a type for a vector of elements of type `element_ty',
having `count' elements."""
check_is_type(element_ty)
return _make_type(_core.LLVMVectorType(element_ty.ptr, count), TYPE_VECTOR)
count = int(count) # must be an int
return _make_type(_core.LLVMVectorType(element_ty.ptr, count),
TYPE_VECTOR)
@staticmethod
def void():
"""Create a void type.
Represents the `void' type."""
return _make_type(_core.LLVMVoidType(), TYPE_VOID)
@staticmethod
def label():
"""Create a label type."""
return _make_type(_core.LLVMLabelType(), TYPE_LABEL)
@staticmethod
def opaque():
"""Create an opaque type.
Opaque types are used to create self-referencing types."""
return _make_type(_core.LLVMOpaqueType(), TYPE_OPAQUE)
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods instead."""
self.ptr = ptr
self.kind = kind
"""An enum (int) value denoting which type this is.
Use the symbolic constants TYPE_* defined in llvm.core
module."""
def __str__(self):
"""Text representation of a type.
Returns the textual representation (`llvm assembly') of the type."""
return _core.LLVMDumpTypeToString(self.ptr)
def __eq__(self, rhs):
@ -369,10 +407,10 @@ class Type(object):
return False
def refine(self, dest):
"""Refine the abstract type represented by self to a concrete class.
"""Refine the abstract type represented by self into a concrete class.
This object is no longer valid after refining, so do not hold references
to it after calling."""
to it after calling. See the user guide for examples on how to use this."""
check_is_type(dest)
_core.LLVMRefineType(self.ptr, dest.ptr)
@ -380,43 +418,62 @@ class Type(object):
class IntegerType(Type):
"""Represents an integer type."""
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
def width(self):
"""The width of the integer type, in bits."""
return _core.LLVMGetIntTypeWidth(self.ptr)
class FunctionType(Type):
"""Represents a function type."""
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
def return_type(self):
"""The type of the value returned by this function."""
ptr = _core.LLVMGetReturnType(self.ptr)
kind = _core.LLVMGetTypeKind(ptr)
return _make_type(ptr, kind)
@property
def vararg(self):
"""True if this function is variadic."""
return _core.LLVMIsFunctionVarArg(self.ptr) != 0
@property
def args(self):
"""An iterable that yields Type objects, representing the types of the
arguments accepted by this function, in order."""
pp = _core.LLVMGetFunctionTypeParams(self.ptr)
return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ]
@property
def arg_count(self):
"""Number of arguments accepted by this function.
Same as len(obj.args), but faster."""
return _core.LLVMCountParamTypes(self.ptr)
class StructType(Type):
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
@ -436,6 +493,9 @@ class StructType(Type):
class ArrayType(Type):
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
@ -452,6 +512,9 @@ class ArrayType(Type):
class PointerType(Type):
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
@ -462,6 +525,9 @@ class PointerType(Type):
class VectorType(Type):
def __init__(self, ptr, kind):
"""DO NOT CALL DIRECTLY.
Use one of the static methods of the *base* class (Type) instead."""
Type.__init__(self, ptr, kind)
@property
@ -602,12 +668,12 @@ class Constant(Value):
@staticmethod
def struct(consts): # not packed
const_ptrs = unpack_constants(consts)
return Constant(_core.LLVMConstStruct(consts, 0))
return Constant(_core.LLVMConstStruct(const_ptrs, 0))
@staticmethod
def packed_struct(consts):
const_ptrs = unpack_constants(consts)
return Constant(_core.LLVMConstStruct(consts, 1))
return Constant(_core.LLVMConstStruct(const_ptrs, 1))
@staticmethod
def vector(consts):
@ -770,7 +836,7 @@ class Constant(Value):
check_is_constant(index)
return Constant(_core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr))
def shuffle_element(self, vector_b, mask): # note: self must be a _vector_ constant
def shuffle_vector(self, vector_b, mask): # note: self must be a _vector_ constant
check_is_constant(vector_b) # note: vector_b must be a _vector_ constant
check_is_constant(mask)
return Constant(_core.LLVMConstShuffleVector(self.ptr, vector_b.ptr, mask.ptr))
@ -778,8 +844,13 @@ class Constant(Value):
class GlobalValue(Constant):
def __init__(self, ptr):
def __init__(self, ptr, module):
Constant.__init__(self, ptr)
self._module = module # hang on to the module
def _delete(self):
self._module = None # set it free
self.ptr = None
def get_linkage(self): return _core.LLVMGetLinkage(self.ptr)
def set_linkage(self, value): _core.LLVMSetLinkage(self.ptr, value)
@ -799,13 +870,11 @@ class GlobalValue(Constant):
@property
def is_declaration(self):
return _core.LLVMIsDeclaration(self.ptr)
return _core.LLVMIsDeclaration(self.ptr) != 0
@property
def module(self):
mod = Module(_core.LLVMGetGlobalParent(self.ptr))
owner = dummy_owner(mod)
return mod
return self._module
class GlobalVariable(GlobalValue):
@ -813,18 +882,18 @@ class GlobalVariable(GlobalValue):
@staticmethod
def new(module, ty, name):
check_is_type(ty)
return GlobalVariable(_core.LLVMAddGlobal(module.ptr, ty.ptr, name))
return GlobalVariable(_core.LLVMAddGlobal(module.ptr, ty.ptr, name), module)
@staticmethod
def get(module, name):
return GlobalVariable(_core.LLVMGetNamedGlobal(module.ptr, name))
return GlobalVariable(_core.LLVMGetNamedGlobal(module.ptr, name), module)
def __init__(self, ptr):
GlobalValue.__init__(self, ptr)
def __init__(self, ptr, module):
GlobalValue.__init__(self, ptr, module)
def delete(self):
_core.LLVMDeleteGlobal(self.ptr)
self.ptr = None
self._delete()
def get_initializer(self):
if _core.LLVMHasInitializer(self.ptr):
@ -862,27 +931,23 @@ class Argument(Value):
def set_alignment(self, align):
_core.LLVMSetParamAlignment(self.ptr, align)
@property
def function(self):
return Function(_core.LLVMGetParamParent(self.ptr))
class Function(GlobalValue):
@staticmethod
def new(module, func_ty, name):
return Function(_core.LLVMAddFunction(module.ptr, name, func_ty.ptr))
return Function(_core.LLVMAddFunction(module.ptr, name, func_ty.ptr), module)
@staticmethod
def get(module, name):
return Function(_core.LLVMGetNamedFunction(module.ptr, name))
return Function(_core.LLVMGetNamedFunction(module.ptr, name), module)
def __init__(self, ptr):
GlobalValue.__init__(self, ptr)
def __init__(self, ptr, module):
GlobalValue.__init__(self, ptr, module)
def delete(self):
_core.LLVMDeleteFunction(self.ptr)
self.ptr = None
self._delete()
@property
def intrinsic_id(self):
@ -906,6 +971,8 @@ class Function(GlobalValue):
return _core.LLVMCountBasicBlocks(self.ptr)
def get_entry_basic_block(self):
if self.basic_block_count == 0:
return None
return BasicBlock(_core.LLVMGetEntryBasicBlock(self.ptr))
def append_basic_block(self, name):
@ -917,6 +984,8 @@ class Function(GlobalValue):
_core.LLVMGetNextBasicBlock, self.ptr, BasicBlock)
def verify(self):
# Although we're just asking LLVM to return the success or
# failure, it appears to print result to stderr and abort.
return _core.LLVMVerifyFunction(self.ptr) != 0
@ -939,8 +1008,8 @@ class CallOrInvokeInstruction(Instruction):
def __init__(self, ptr):
Instruction.__init__(self, ptr)
def get_calling_convention(self): return _core.LLVMGetFunctionCallConv(self.ptr)
def set_calling_convention(self, value): _core.LLVMSetFunctionCallConv(self.ptr, value)
def get_calling_convention(self): return _core.LLVMGetInstructionCallConv(self.ptr)
def set_calling_convention(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value)
calling_convention = property(get_calling_convention, set_calling_convention)
def add_parameter_attribute(self, idx, attr):
@ -1020,8 +1089,11 @@ class BasicBlock(Value):
class Builder(object):
@staticmethod
def new():
return Builder(_core.LLVMCreateBuilder())
def new(basic_block):
check_is_basic_block(basic_block)
b = Builder(_core.LLVMCreateBuilder())
b.position_at_end(basic_block)
return b
def __init__(self, ptr):
self.ptr = ptr
@ -1029,22 +1101,34 @@ class Builder(object):
def __del__(self):
_core.LLVMDisposeBuilder(self.ptr)
def position(self, block, instr=None):
if instr:
_core.LLVMPositionBuilder(self.ptr, block.ptr, instr.ptr)
else:
_core.LLVMPositionBuilder(self.ptr, block.ptr)
def position_before(self, instr):
_core.LLVMPositionBuilderBefore(self.ptr, instr.ptr)
def position_at_beginning(self, bblk):
"""Position the builder at the beginning of the given block.
Next instruction inserted will be first one in the block."""
# Avoids using "blk.instructions", which will fetch all the
# instructions into a list. Don't try this at home, though.
first_inst = Instruction(_core.LLVMGetFirstInstruction(self.block.ptr))
self.position_before(first_inst)
def position_at_end(self, bblk):
"""Position the builder at the end of the given block.
Next instruction inserted will be last one in the block."""
_core.LLVMPositionBuilderAtEnd(self.ptr, bblk.ptr)
def position_before(self, instr):
"""Position the builder before the given instruction.
The instruction can belong to a basic block other than the
current one."""
_core.LLVMPositionBuilderBefore(self.ptr, instr.ptr)
@property
def insert_block(self):
def block(self):
return BasicBlock(_core.LLVMGetInsertBlock(self.ptr))
# terminator instructions
def ret_void(self):
return Instruction(_core.LLVMBuildRetVoid(self.ptr))
@ -1084,7 +1168,7 @@ class Builder(object):
def unreachable(self):
return Instruction(_core.LLVMBuildUnreachable(self.ptr))
# arithmethic-related
# arithmethic, bitwise and logical
def add(self, lhs, rhs, name=""):
check_is_value(lhs)
@ -1207,7 +1291,7 @@ class Builder(object):
index_ptrs = unpack_values(indices)
return Value(_core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name))
# casts
# casts and extensions
def trunc(self, value, dest_ty, name=""):
check_is_value(value)
@ -1306,11 +1390,11 @@ class Builder(object):
arg_ptrs = unpack_values(args)
return CallOrInvokeInstruction(_core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name))
def select(self, if_blk, then_blk, else_blk, name=""):
check_is_basic_block(if_blk)
def select(self, cond, then_blk, else_blk, name=""):
check_is_value(cond)
check_is_basic_block(then_blk)
check_is_basic_block(else_blk)
return Value(_core.LLVMBuildSelect(self.ptr, if_blk.ptr, then_blk.ptr, else_blk.ptr, name))
return Value(_core.LLVMBuildSelect(self.ptr, cond.ptr, then_blk.ptr, else_blk.ptr, name))
def vaarg(self, list_val, ty, name=""):
check_is_value(list_val)
@ -1356,9 +1440,6 @@ class ModuleProvider(llvm.Ownable):
# a module provider is both a owner (of modules) and an ownable
# (can be owned by execution engines)
def __del__(self):
llvm.Ownable.__del__(self)
#===----------------------------------------------------------------------===
# Memory buffer

View file

@ -21,9 +21,6 @@ class TargetData(llvm.Ownable):
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)

View file

@ -78,9 +78,6 @@ class FunctionPassManager(PassManager):
def __init__(self, ptr):
PassManager.__init__(self, ptr)
def __del__(self):
PassManager.__del__(self)
def initialize(self):
_core.LLVMInitializeFunctionPassManager(self.ptr)

View file

@ -68,7 +68,7 @@ def call_setup(llvm_config):
description='Python Bindings for LLVM',
author='Mahadevan R',
author_email='mdevan.foobar@gmail.com',
url='http://code.google.com/p/llvm-py/',
url='http://mdevan.nfshost.com/llvm-py/',
packages=['llvm'],
py_modules = [ 'llvm.core' ],
ext_modules = [ ext_core ],)

381
test/testall.py Normal file
View file

@ -0,0 +1,381 @@
#!/usr/bin/env python
#
# This script attempts to achieve 100% function and branch coverage for
# all APIs in the llvm package. It only exercises the APIs, doesn't test
# them for correctness.
#
from llvm import *
from llvm.core import *
ti = Type.int()
def do_module():
print " Testing class Module"
m = Module.new('test')
m.target = 'a'
a = m.target
m.data_layout = 'a'
a = m.data_layout
m.add_type_name('a', ti)
m.delete_type_name('a')
s = str(m)
s = m == Module.new('a')
m.add_global_variable(ti, 'b')
m.get_global_variable_named('b')
gvs = list(m.global_variables)
ft = Type.function(ti, [ti])
m.add_function(ft, "func")
m.get_function_named("func")
fns = list(m.functions)
try:
m.verify()
except LLVMException:
pass
def do_type():
print " Testing class Type"
for i in range(1,100):
Type.int(i)
Type.float()
Type.double()
Type.x86_fp80()
Type.fp128()
Type.ppc_fp128()
Type.function(ti, [ti]*100, True)
Type.function(ti, [ti]*100, False)
Type.struct([ti]*100)
Type.packed_struct([ti]*100)
Type.array(ti, 100)
Type.pointer(ti, 4)
Type.vector(ti, 100)
Type.void()
Type.label()
Type.opaque()
s = str(ti)
s = ti == Type.float()
Type.opaque().refine(Type.int())
s = ti.width
ft = Type.function(ti, [ti]*10)
ft.return_type
ft.vararg
s = list(ft.args)
ft.arg_count
st = Type.struct([ti]*10)
s = st.element_count
s = list(st.elements)
s = st.packed
st = Type.packed_struct([ti]*10)
s = st.element_count
s = list(st.elements)
s = st.packed
at = Type.array(ti, 100)
s = at.element
s = at.count
pt = Type.pointer(ti, 10)
pt.address_space
vt = Type.vector(ti, 100)
s = vt.element
s = vt.count
def do_typehandle():
print " Testing class TypeHandle"
th = TypeHandle.new(Type.opaque())
ts = Type.struct([ Type.int(), Type.pointer(th.type) ])
th.type.refine(ts)
def do_value():
print " Testing class Value"
k = Constant.int(ti, 42)
k.name = 'a'
s = k.name
t = s.type
s = str(k)
s = k == Constant.int(ti, 43)
def do_constant():
print " Testing class Constant"
Constant.null(ti)
Constant.all_ones(ti)
Constant.undef(ti)
Constant.int(ti, 10)
Constant.int_signextend(ti, 10)
Constant.real(Type.float(), "10.0")
Constant.real(Type.float(), 3.14)
Constant.string("test")
Constant.stringz("test2")
Constant.array(ti, [Constant.int(ti,42)]*10)
Constant.struct([Constant.int(ti,42)]*10)
Constant.packed_struct([Constant.int(ti,42)]*10)
Constant.vector([Constant.int(ti,42)]*10)
Constant.sizeof(ti)
k = Constant.int(ti, 10)
f = Constant.real(Type.float(), 3.1415)
k.neg().not_().add(k).sub(k).mul(k).udiv(k).sdiv(k).urem(k)
k.srem(k).and_(k).or_(k).icmp(IPRED_ULT, k)
f.fdiv(f).frem(f).fcmp(RPRED_ULT, f)
vi = Constant.vector([Constant.int(ti,42)]*10)
vi.vicmp(IPRED_ULT, vi)
vf = Constant.vector([Constant.real(Type.float(), 3.14)]*10)
vf.vfcmp(RPRED_ULT, vf)
k.shl(k).lshr(k).ashr(k)
# TODO gep
k.trunc(Type.int(1))
k.sext(Type.int(64))
k.zext(Type.int(64))
Constant.real(Type.double(), 1.0).fptrunc(Type.float())
Constant.real(Type.float(), 1.0).fpext(Type.double())
k.uitofp(Type.float())
k.sitofp(Type.float())
f.fptoui(ti)
f.fptosi(ti)
p = Type.pointer(ti)
# TODO ptrtoint
k.inttoptr(p)
f.bitcast(Type.int(32))
k.trunc(Type.int(1)).select(k, k)
vi.extract_element( Constant.int(ti,0) )
vi.insert_element( k, k )
vi.shuffle_vector( vi, vi )
def do_global_value():
print " Testing class GlobalValue"
m = Module.new('a')
gv = GlobalVariable.new(m, Type.int(), 'b')
s = gv.is_declaration
m = gv.module
s = gv.is_declaration
gv.linkage = LINKAGE_EXTERNAL
s = gv.linkage
gv.section = '.text'
s = gv.section
gv.visibility = VISIBILITY_HIDDEN
s = gv.visibility
gv.alignment = 8
s = gv.alignment
def do_global_variable():
print " Testing class GlobalVariable"
m = Module.new('a')
gv = GlobalVariable.new(m, Type.int(), 'b')
gv = GlobalVariable.get(m, 'b')
gv.delete()
gv = GlobalVariable.new(m, Type.int(), 'c')
gv.initializer = Constant.int( ti, 10 )
s = gv.initializer
gv.global_constant = True
s = gv.global_constant
def do_argument():
print " Testing class Argument"
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
a = f.args[0]
a.add_attribute(ATTR_ZEXT)
a.remove_attribute(ATTR_ZEXT)
a.set_alignment(4)
def do_function():
print " Testing class Function"
ft = Type.function(ti, [ti]*20)
zz = Function.new(Module.new('z'), ft, 'foobar')
del zz
Function.new(Module.new('zz'), ft, 'foobar')
m = Module.new('a')
f = Function.new(m, ft, 'func')
f.delete()
ft = Type.function(ti, [ti]*20)
f = Function.new(m, ft, 'func2')
g = f.intrinsic_id
f.calling_convenion = CC_FASTCALL
g = f.calling_convenion
f.collector = 'a'
c = f.collector
a = list(f.args)
g = f.basic_block_count
g = f.get_entry_basic_block()
g = f.append_basic_block('a')
g = f.get_entry_basic_block()
g = list(f.basic_blocks)
# LLVM misbehaves:
#try:
# f.verify()
#except LLVMException:
# pass
def do_instruction():
print " Testing class Instruction"
m = Module.new('a')
ft = Type.function(ti, [ti]*20)
f = Function.new(m, ft, 'func')
b = f.append_basic_block('a')
bb = Builder.new(b)
i = bb.ret_void()
bb2 = i.basic_block
def do_callorinvokeinstruction():
print " Testing class CallOrInvokeInstruction"
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
b = f.append_basic_block('a')
bb = Builder.new(b)
i = bb.invoke(f, [Constant.int(ti, 10)], b, b)
a = i.calling_convention
i.calling_convention = CC_FASTCALL
i.add_parameter_attribute(0, ATTR_SEXT)
i.remove_parameter_attribute(0, ATTR_SEXT)
i.set_parameter_alignment(0, 8)
def do_phinode():
print " Testing class PhiNode"
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
b = f.append_basic_block('b')
c = f.append_basic_block('c')
d = f.append_basic_block('d')
bb = Builder.new(d)
p = bb.phi(ti)
v = p.incoming_count
p.add_incoming( Constant.int(ti, 10), b )
p.add_incoming( Constant.int(ti, 10), c )
p.get_incoming_value(0)
p.get_incoming_block(0)
def do_switchinstruction():
print " Testing class SwitchInstruction"
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
b = f.append_basic_block('b')
bb = Builder.new(b)
s = bb.switch(f.args[0], b)
s.add_case(Constant.int(ti, 10), b)
def do_builder():
print " Testing class Builder"
m = Module.new('a')
ft = Type.function(ti, [ti])
f = Function.new(m, ft, 'func')
blk = f.append_basic_block('b')
b = Builder.new(blk)
b.ret(Constant.int(ti, 10))
b.position_at_beginning(blk)
b.position_at_end(blk)
b.position_before(blk.instructions[0])
blk2 = b.block
b.ret_void()
b.ret(Constant.int(ti, 10))
b.ret_many([Constant.int(ti, 10)]*10)
b.branch(blk)
b.cbranch(Constant.int(Type.int(1), 1), blk, blk)
b.switch(f.args[0], blk)
b.invoke(f, [Constant.int(ti,10)], blk, blk)
b.unwind()
b.unreachable()
v = f.args[0]
fv = Constant.real(Type.float(), "1.0")
k = Constant.int(ti, 10)
b.add(v, v)
b.sub(v, v)
b.mul(v, v)
b.udiv(v, v)
b.sdiv(v, v)
b.fdiv(fv, fv)
b.urem(v, v)
b.srem(v, v)
b.frem(fv, fv)
b.shl(v, k)
b.lshr(v, k)
b.ashr(v, k)
b.and_(v, v)
b.or_(v, v)
b.xor(v, v)
b.neg(v)
b.not_(v)
p = b.malloc(Type.int())
b.malloc_array(Type.int(), k)
b.alloca(Type.int())
b.alloca_array(Type.int(), k)
b.free(p)
b.load(p)
b.store(k, p)
# TODO gep
b.trunc(v, Type.int(1))
b.zext(v, Type.int(64))
b.sext(v, Type.int(64))
b.fptoui(fv, ti)
b.fptosi(fv, ti)
b.uitofp(k, Type.float())
b.sitofp(k, Type.float())
b.fptrunc(Constant.real(Type.double(), "1.0"), Type.float())
b.fpext(Constant.real(Type.float(), "1.0"), Type.double())
b.ptrtoint(p, ti)
b.inttoptr(k, Type.pointer(Type.int()))
b.bitcast(v, Type.float())
b.icmp(IPRED_ULT, v, v)
b.fcmp(RPRED_ULT, fv, fv)
vi = Constant.vector([Constant.int(ti,42)]*10)
b.vicmp(IPRED_ULT, vi, vi)
vf = Constant.vector([Constant.real(Type.float(), 3.14)]*10)
b.vfcmp(RPRED_ULT, vf, vf)
# TODO b.getresult(v, 0)
b.call(f, [v])
b.select(Constant.int(Type.int(1), 1), blk, blk)
b.vaarg(v, Type.int())
b.extract_element(vi, v)
b.insert_element(vi, v, v)
b.shuffle_vector(vi, vi, vi)
# NOTE: phi nodes without incoming values segfaults in LLVM during
# destruction.
i = b.phi(Type.int())
i.add_incoming(v, blk)
def do_moduleprovider():
print " Testing class ModuleProvider"
m = Module.new('a')
mp = ModuleProvider.new(m)
def do_llvm_core():
print " Testing module llvm.core"
do_module()
do_type()
do_typehandle()
do_constant()
do_global_value()
do_global_variable()
do_argument()
do_function()
do_instruction()
do_callorinvokeinstruction()
do_phinode()
do_switchinstruction()
do_builder()
do_moduleprovider()
def do_llvm():
print "Testing package llvm"
do_llvm_core()
do_llvm()

View file

@ -6,7 +6,7 @@ from string import Template
from optparse import OptionParser
# files in src dir that should not be copied to web dir
SKIP_FILES = [ 'layout.conf', '.svn' ]
SKIP_FILES = [ 'layout.conf', '.svn', 'instrset.inc' ]
# asciidoc command line
ASCIIDOC = 'asciidoc --unsafe --conf-file=${srcdir}/layout.conf -a icons -o ${outfile} ${infile}'

View file

@ -11,7 +11,6 @@ Browse SVN, http://code.google.com/p/llvm-py/source/browse/[http://code.google.c
Issues tracker, http://code.google.com/p/llvm-py/issues/list[http://code.google.com/p/llvm-py/issues/list]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SVN HEAD can be checked out like so:
----
@ -21,3 +20,12 @@ $ svn checkout http://llvm-py.googlecode.com/svn/trunk/ llvm-py
Mahadevan R (mdevan.foobar@gmail.com) is available to answer your
queries.
Current Next Steps
------------------
- Wrap GenericValue, function call args for execution engine.
- Add APIs to read/write `.bc` and `.ll` files.
- Wrap `lto`.
- Add examples.
- Update documentation.
- Improve tests.

View file

@ -6,9 +6,11 @@ http://llvm.org/[LLVM]. It's goal is to expose enough of LLVM APIs to
implement a compiler or VM in pure Python. Currently, llvm-py is
available for LLVM 2.3 and Python 2.5, on Linux/x86. It is expected to
be usable on various unices, as well as with Python 2.4, with minimal
changes, if any. It should be stable enough for you to play with.
changes, if any.
llvm-py is just hatching, and your contributions would be most welcome.
llvm-py is just hatching. It should be stable enough to start hacking
away, though. Be sure to send in a patch (or shout at the author) if you
miss any specific LLVM API.
News
----

View file

@ -1,6 +1,8 @@
llvm-py User Guide
===================
NOTE: This document is updated constantly. Check back often.
llvm-py provides Python bindings for LLVM. This document explains how
you can setup and use it. A working knowledge of Python and a basic idea
of LLVM is assumed.
@ -46,7 +48,7 @@ llvm-py is distributed as a source tarball. You'll need to build and
install it before it can be used. At least the following will be
required for this:
- compilers, both gcc and g++
- C and C\+\+ compilers (gcc/g\+\+)
- Python itself
- Python development files (headers and libraries)
- LLVM, either installed or built
@ -56,7 +58,11 @@ command `sudo apt-get install gcc g++ python python-dev'. Note that
ubuntu repository has an old version of llvm (1.8) which will not work
with llvm-py.
Tip: If LLVM 2.3 does not install cleanly, try installing 'ocamldoc'
It does not matter which compiler LLVM itself was built with (g\+\+,
llvm-g\+\+ or any other); llvm-py can be built with any compiler. It has
been tried only with gcc/g\+\+ though.
Tip: If LLVM 2.3 does not install cleanly, try installing ``ocamldoc''
first.
@ -108,11 +114,16 @@ libraries of LLVM, use this:
$ tar jxvf llvm-py-0.2.tar.bz2
$ cd llvm-py-0.2
$ python setup.py build -g --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config
$ sudo python setup.py install -g --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config
$ sudo python setup.py install --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config
-----------------------------------------------------------------------
Be warned that debug binaries will be huge (65MB+) !
`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.
[[uninstall]]
Uninstall
@ -891,6 +902,12 @@ r3 = Constant.undef() # an `undefined' value
source~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TypeHandle (llvm.core)
~~~~~~~~~~~~~~~~~~~~~~
TODO
Instructions (llvm.core)
~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -81,10 +81,45 @@ cellspacing="0" cellpadding="4">
queries.</p>
</div>
</div>
<h2>Current Next Steps</h2>
<div class="sectionbody">
<ul>
<li>
<p>
Wrap GenericValue, function call args for execution engine.
</p>
</li>
<li>
<p>
Add APIs to read/write <tt>.bc</tt> and <tt>.ll</tt> files.
</p>
</li>
<li>
<p>
Wrap <tt>lto</tt>.
</p>
</li>
<li>
<p>
Add examples.
</p>
</li>
<li>
<p>
Update documentation.
</p>
</li>
<li>
<p>
Improve tests.
</p>
</li>
</ul>
</div>
<div id="footer">
<div id="footer-text">
Web pages &copy; Mahadevan R. Generated with <a href="http://www.methods.co.nz/asciidoc/">asciidoc</a>.
Last updated 10-Jun-2008.
Last updated 15-Jun-2008.
</div>
</div>
</div>

View file

@ -40,8 +40,10 @@
implement a compiler or VM in pure Python. Currently, llvm-py is
available for LLVM 2.3 and Python 2.5, on Linux/x86. It is expected to
be usable on various unices, as well as with Python 2.4, with minimal
changes, if any. It should be stable enough for you to play with.</p>
<p>llvm-py is just hatching, and your contributions would be most welcome.</p>
changes, if any.</p>
<p>llvm-py is just hatching. It should be stable enough to start hacking
away, though. Be sure to send in a patch (or shout at the author) if you
miss any specific LLVM API.</p>
</div>
</div>
<h2>News</h2>
@ -60,7 +62,7 @@ changes, if any. It should be stable enough for you to play with.</p>
<div id="footer">
<div id="footer-text">
Web pages &copy; Mahadevan R. Generated with <a href="http://www.methods.co.nz/asciidoc/">asciidoc</a>.
Last updated 10-Jun-2008.
Last updated 15-Jun-2008.
</div>
</div>
</div>

View file

@ -35,6 +35,14 @@
</div>
<div id="preamble">
<div class="sectionbody">
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">This document is updated constantly. Check back often.</td>
</tr></table>
</div>
<p>llvm-py provides Python bindings for LLVM. This document explains how
you can setup and use it. A working knowledge of Python and a basic idea
of LLVM is assumed.</p>
@ -73,7 +81,7 @@ required for this:</p>
<ul>
<li>
<p>
compilers, both gcc and g++
C and C++ compilers (gcc/g++)
</p>
</li>
<li>
@ -96,7 +104,10 @@ LLVM, either installed or built
command `sudo apt-get install gcc g++ python python-dev'. Note that
ubuntu repository has an old version of llvm (1.8) which will not work
with llvm-py.</p>
<p>Tip: If LLVM 2.3 does not install cleanly, try installing <em>ocamldoc</em>
<p>It does not matter which compiler LLVM itself was built with (g++,
llvm-g++ or any other); llvm-py can be built with any compiler. It has
been tried only with gcc/g++ though.</p>
<p>Tip: If LLVM 2.3 does not install cleanly, try installing &#8220;ocamldoc&#8221;
first.</p>
<h3>llvm-config</h3>
<p>Inorder to build llvm-py, it's build script needs to know from where to
@ -136,9 +147,13 @@ libraries of LLVM, use this:</p>
<pre><tt>$ tar jxvf llvm-py-0.2.tar.bz2
$ cd llvm-py-0.2
$ python setup.py build -g --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config
$ sudo python setup.py install -g --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config</tt></pre>
$ sudo python setup.py install --llvm-config=/home/mdevan/llvm/Debug/bin/llvm-config</tt></pre>
</div></div>
<p>Be warned that debug binaries will be huge (65MB+) !</p>
<p><tt>setup.py</tt> is a standard Python distutils script. See the Python
documentation regarding <a href="http://docs.python.org/inst/inst.html">Installing
Python Modules</a> and <a href="http://docs.python.org/dist/dist.html">Distributing
Python Modules</a> for more information on such scripts.</p>
<h3><a id="uninstall"></a>Uninstall</h3>
<p>To get rid of llvm-py completely, if you wish to do so:</p>
<div class="listingblock">
@ -1659,6 +1674,8 @@ r2 <span style="color: #990000">=</span> <span style="color: #009900">Constant</
r3 <span style="color: #990000">=</span> <span style="color: #009900">Constant</span><span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #000000">undef</span></span><span style="color: #990000">()</span> <span style="font-style: italic"><span style="color: #9A1900"># an `undefined' value</span></span>
</tt></pre></div></div>
<h3>TypeHandle (llvm.core)</h3>
<p>TODO</p>
<h3>Instructions (llvm.core)</h3>
<p>TODO</p>
<h3>Basic Block (llvm.core)</h3>
@ -1702,7 +1719,7 @@ reached at <em>mdevan.foobar@gmail.com</em>.</p>
<div id="footer">
<div id="footer-text">
Web pages &copy; Mahadevan R. Generated with <a href="http://www.methods.co.nz/asciidoc/">asciidoc</a>.
Last updated 12-Jun-2008.
Last updated 15-Jun-2008.
</div>
</div>
</div>