From 2255a7e5dd3e9c6734a42babd8e724cae28d4aa4 Mon Sep 17 00:00:00 2001 From: "mdevan.foobar" Date: Sat, 7 Jun 2008 13:44:25 +0000 Subject: [PATCH] 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 --- llvm/__init__.py | 25 +++ llvm/_core.c | 104 +++++++++ llvm/_util.py | 52 ++++- llvm/core.py | 498 ++++++++++++++++++----------------------- llvm/ee.py | 67 +++--- llvm/passes.py | 29 ++- llvm/wrap.c | 3 + llvm/wrap.h | 32 +++ setup.py | 10 +- test/example.py | 14 +- test/test.py | 26 ++- www/src/about.txt | 7 +- www/src/contribute.txt | 5 +- www/src/download.txt | 39 +++- www/src/examples.txt | 44 +--- 15 files changed, 559 insertions(+), 396 deletions(-) diff --git a/llvm/__init__.py b/llvm/__init__.py index ac0afac..ebc8c14 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -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) + diff --git a/llvm/_core.c b/llvm/_core.c index c3f897a..051159f 100644 --- a/llvm/_core.c +++ b/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 /* 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 } }; diff --git a/llvm/_util.py b/llvm/_util.py index 1d8704b..bbbc23d 100644 --- a/llvm/_util.py +++ b/llvm/_util.py @@ -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) - diff --git a/llvm/core.py b/llvm/core.py index ebfc722..37b4ac3 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -4,8 +4,9 @@ The llvm.core module contains classes and constants required to build the in-memory intermediate representation (IR) data structures.""" -import llvm # top-level, for common stuff -import _core # C wrappers +import llvm # top-level, for common stuff +import _core # C wrappers +from _util import * # utility functions #===----------------------------------------------------------------------=== @@ -96,51 +97,12 @@ ATTR_READ_NONE = 512 ATTR_READONLY = 1024 -#===----------------------------------------------------------------------=== -# Helper functions -#===----------------------------------------------------------------------=== - - -def _check_gen(obj, type, type_str): - if not isinstance(obj, type): - type_str = type.__module__ + "." + type.__name__ - msg = "argument must be an instance of llvm.core.%s (or of a class derived from it)" % type_str - raise TypeError, msg - -def _check_is_type(obj): _check_gen(obj, Type, "Type") -def _check_is_value(obj): _check_gen(obj, Value, "Value") -def _check_is_pointer(obj): _check_gen(obj, Pointer, "Pointer") -def _check_is_constant(obj): _check_gen(obj, Constant, "Constant") -def _check_is_function(obj): _check_gen(obj, Function, "Function") -def _check_is_basic_block(obj): _check_gen(obj, BasicBlock, "BasicBlock") -def _check_is_module_provider(obj): _check_gen(obj, ModuleProvider, "ModuleProvider") - -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 _wrapiter(first, next, container, wrapper): - ptr = first(container) - while ptr: - yield wrapper(ptr) - ptr = next(ptr) - -class _dummy_owner(object): - - def __init__(self, ownee): - ownee._own(self) - - #===----------------------------------------------------------------------=== # Module #===----------------------------------------------------------------------=== -class Module(object): +class Module(llvm.Ownable): """A Module instance stores all the information related to an LLVM module. Modules are the top level container of all other LLVM Intermediate @@ -168,12 +130,10 @@ class Module(object): Use the static method `Module.new' instead. """ - self.ptr = ptr - self.owner = None + llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule) def __del__(self): - if not self.owner: - _core.LLVMDisposeModule(self.ptr) + llvm.Ownable.__del__(self) def __str__(self): """Text representation of a module. @@ -192,10 +152,6 @@ class Module(object): else: return False - def _own(self, owner): - assert not self.owner - self.owner = owner - def _get_target(self): return _core.LLVMGetTarget(self.ptr) @@ -227,7 +183,7 @@ class Module(object): if entry already existed (in which case nothing is changed), False otherwise. """ - _check_is_type(ty) + check_is_type(ty) return _core.LLVMAddTypeName(self.ptr, name, ty.ptr) != 0 def delete_type_name(self, name): @@ -255,7 +211,7 @@ class Module(object): # gv is an instance of GlobalVariable # do stuff with gv """ - return _wrapiter(_core.LLVMGetFirstGlobal, _core.LLVMGetNextGlobal, + return wrapiter(_core.LLVMGetFirstGlobal, _core.LLVMGetNextGlobal, self.ptr, GlobalVariable) def add_function(self, ty, name): @@ -276,7 +232,7 @@ class Module(object): # f is an instance of Function # do stuff with f """ - return _wrapiter(_core.LLVMGetFirstFunction, + return wrapiter(_core.LLVMGetFirstFunction, _core.LLVMGetNextFunction, self.ptr, Function) def verify(self): @@ -291,13 +247,19 @@ class Module(object): class Type(object): + """Represents a type, like a 32-bit integer or an 80-bit x86 float. + + Use one of the static methods to create an instance. Example: + ty = Type.double() + """ @staticmethod def int(bits=32): + """Create an integer type having the given bit width.""" if bits == 1: return _make_type(_core.LLVMInt1Type(), TYPE_INTEGER) elif bits == 8: - return _make_type(_core.LLVMInt2Type(), TYPE_INTEGER) + return _make_type(_core.LLVMInt8Type(), TYPE_INTEGER) elif bits == 16: return _make_type(_core.LLVMInt16Type(), TYPE_INTEGER) elif bits == 32: @@ -309,54 +271,76 @@ class Type(object): @staticmethod def float(): + """Create a 32-bit floating point type.""" return _make_type(_core.LLVMFloatType(), TYPE_FLOAT) @staticmethod def double(): + """Create a 64-bit floating point type.""" return _make_type(_core.LLVMDoubleType(), TYPE_DOUBLE) @staticmethod def x86_fp80(): + """Create a 80-bit x86 floating point type.""" return _make_type(_core.LLVMX86FP80Type(), TYPE_X86_FP80) @staticmethod def fp128(): + """Create a 128-bit floating point type (with 112-bit + mantissa).""" return _make_type(_core.LLVMFP128Type(), TYPE_FP128) @staticmethod def ppc_fp128(): + """Create a 128-bit floating point type (two 64-bits).""" return _make_type(_core.LLVMPPCFP128Type(), TYPE_PPC_FP128) @staticmethod def function(return_ty, param_tys, var_arg=False): - _check_is_type(return_ty) + """Create a function type. + + Creates a function type that returns a value of type + `return_ty', takes arguments of types as given in the iterable + `param_tys'. Set `var_arg' to True (default is False) for a + variadic function.""" + check_is_type(return_ty) var_arg = 1 if var_arg else 0 # convert to int - params = _unpack_types(param_tys) + params = unpack_types(param_tys) return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, var_arg), TYPE_FUNCTION) @staticmethod def struct(element_tys): # not packed - elems = _unpack_types(element_tys) + """Create a (unpacked) structure type. + + 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 struct_packed() method.""" + elems = unpack_types(element_tys) return _make_type(_core.LLVMStructType(elems, 0), TYPE_STRUCT) @staticmethod def struct_packed(element_tys): - elems = _unpack_types(element_tys) + """Create a (packed) structure type. + + 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.""" + elems = unpack_types(element_tys) return _make_type(_core.LLVMStructType(elems, 1), TYPE_STRUCT) @staticmethod def array(element_ty, count): - _check_is_type(element_ty) + check_is_type(element_ty) return _make_type(_core.LLVMArrayType(element_ty.ptr, count), TYPE_ARRAY) @staticmethod def pointer(pointee_ty, addr_space=0): - _check_is_type(pointee_ty) + check_is_type(pointee_ty) return _make_type(_core.LLVMPointerType(pointee_ty.ptr, addr_space), TYPE_POINTER) @staticmethod def vector(element_ty, count): - _check_is_type(element_ty) + check_is_type(element_ty) return _make_type(_core.LLVMVectorType(element_ty.ptr, count), TYPE_VECTOR) @staticmethod @@ -390,7 +374,7 @@ class Type(object): This object is no longer valid after refining, so do not hold references to it after calling.""" - _check_is_type(dest) + check_is_type(dest) _core.LLVMRefineType(self.ptr, dest.ptr) self.ptr = None @@ -517,7 +501,7 @@ class TypeHandle(object): @staticmethod def new(abstract_ty): - _check_is_type(abstract_ty) + check_is_type(abstract_ty) return TypeHandle(_core.LLVMCreateTypeHandle(abstract_ty.ptr)) def __init__(self, ptr): @@ -570,32 +554,32 @@ class Constant(Value): @staticmethod def null(ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstNull(ty.ptr)); @staticmethod def all_ones(ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstAllOnes(ty.ptr)); @staticmethod def undef(ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMGetUndef(ty.ptr)); @staticmethod def int(ty, value): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstInt(ty.ptr, value, 0)) @staticmethod def int_signextend(ty, value): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstInt(ty.ptr, value, 1)) @staticmethod def real(ty, value): - _check_is_type(ty) + check_is_type(ty) if isinstance(value, str): return Constant(_core.LLVMConstRealOfString(ty.ptr, value)) else: @@ -611,32 +595,32 @@ class Constant(Value): @staticmethod def array(ty, consts): - _check_is_type(ty) - const_ptrs = _unpack_constants(consts) + check_is_type(ty) + const_ptrs = unpack_constants(consts) return Constant(_core.LLVMConstArray(ty.ptr, const_ptrs)) @staticmethod def struct(consts): # not packed - const_ptrs = _unpack_constants(consts) + const_ptrs = unpack_constants(consts) return Constant(_core.LLVMConstStruct(consts, 0)) @staticmethod def struct_packed(consts): - const_ptrs = _unpack_constants(consts) + const_ptrs = unpack_constants(consts) return Constant(_core.LLVMConstStruct(consts, 1)) @staticmethod def vector(consts): - const_ptrs = _unpack_constants(consts) + const_ptrs = unpack_constants(consts) return Constant(_core.LLVMConstVector(const_ptrs)) @staticmethod def sizeof(ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMSizeOf(ty.ptr)) def __init__(self, ptr): - self.ptr = ptr + Value.__init__(self, ptr) def neg(self): return Constant(_core.LLVMConstNeg(self.ptr)) @@ -645,145 +629,145 @@ class Constant(Value): return Constant(_core.LLVMConstNot(self.ptr)) def add(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstAdd(self.ptr, rhs.ptr)) def sub(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstSub(self.ptr, rhs.ptr)) def mul(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstMul(self.ptr, rhs.ptr)) def udiv(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstUDiv(self.ptr, rhs.ptr)) def sdiv(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstSDiv(self.ptr, rhs.ptr)) def fdiv(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstFDiv(self.ptr, rhs.ptr)) def urem(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstURem(self.ptr, rhs.ptr)) def srem(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstSRem(self.ptr, rhs.ptr)) def and_(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstAnd(self.ptr, rhs.ptr)) def or_(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstOr(self.ptr, rhs.ptr)) def xor(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstXor(self.ptr, rhs.ptr)) def icmp(self, int_pred, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstICmp(self.ptr, int_pred, rhs.ptr)) def fcmp(self, real_pred, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstFCmp(self.ptr, real_pred, rhs.ptr)) def shl(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstShl(self.ptr, rhs.ptr)) def lshr(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstLShr(self.ptr, rhs.ptr)) def ashr(self, rhs): - _check_is_constant(rhs) + check_is_constant(rhs) return Constant(_core.LLVMConstAShr(self.ptr, rhs.ptr)) def gep(self, indices): - index_ptrs = _unpack_constants(indices) + index_ptrs = unpack_constants(indices) return Constant(_core.LLVMConstGEP(self.ptr, index_ptrs)) def trunc(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstTrunc(self.ptr, ty.ptr)) def sext(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstSExt(self.ptr, ty.ptr)) def zext(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstZExt(self.ptr, ty.ptr)) def fptrunc(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstFPTrunc(self.ptr, ty.ptr)) def fpext(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstFPExt(self.ptr, ty.ptr)) def uitofp(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstUIToFP(self.ptr, ty.ptr)) def sitofp(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstSIToFP(self.ptr, ty.ptr)) def fptoui(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstFPToUI(self.ptr, ty.ptr)) def fptosi(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstFPToSI(self.ptr, ty.ptr)) def ptrtoint(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstPtrToInt(self.ptr, ty.ptr)) def inttoptr(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstIntToPtr(self.ptr, ty.ptr)) def bitcast(self, ty): - _check_is_type(ty) + check_is_type(ty) return Constant(_core.LLVMConstBitCast(self.ptr, ty.ptr)) def select(self, true_const, false_const): - _check_is_constant(true_const) - _check_is_constant(false_const) + check_is_constant(true_const) + check_is_constant(false_const) return Constant(_core.LLVMConstSelect(self.ptr, true_const.ptr, false_const.ptr)) def extract(self, index): # note: self must be a _vector_ constant - _check_is_constant(index) + check_is_constant(index) return Constant(_core.LLVMConstExtractElement(self.ptr, index.ptr)) def insert(self, value, index): # note: self must be a _vector_ constant - _check_is_constant(value) - _check_is_constant(index) + check_is_constant(value) + check_is_constant(index) return Constant(_core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr)) def shuffle(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) + 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)) -class GlobalValue(Value): +class GlobalValue(Constant): def __init__(self, ptr): - self.ptr = ptr + Constant.__init__(self, ptr) def get_linkage(self): return _core.LLVMGetLinkage(self.ptr) def set_linkage(self, value): _core.LLVMSetLinkage(self.ptr, value) @@ -808,7 +792,7 @@ class GlobalValue(Value): @property def module(self): mod = Module(_core.LLVMGetGlobalParent(self.ptr)) - owner = _dummy_owner(mod) + owner = dummy_owner(mod) return mod @@ -816,7 +800,7 @@ class GlobalVariable(GlobalValue): @staticmethod def new(module, ty, name): - _check_is_type(ty) + check_is_type(ty) return GlobalVariable(_core.LLVMAddGlobal(module.ptr, ty.ptr, name)) @staticmethod @@ -837,7 +821,7 @@ class GlobalVariable(GlobalValue): return None def set_initializer(self, const): - _check_is_constant(const) + check_is_constant(const) _core.LLVMSetInitializer(self.ptr, const.ptr) initializer = property(get_initializer, set_initializer) @@ -902,7 +886,7 @@ class Function(GlobalValue): @property def args(self): - return _wrapiter(_core.LLVMGetFirstParam, _core.LLVMGetNextParam, + return wrapiter(_core.LLVMGetFirstParam, _core.LLVMGetNextParam, self.ptr, Argument) @property @@ -917,7 +901,7 @@ class Function(GlobalValue): @property def basic_blocks(self): - return _wrapiter(_core.LLVMGetFirstBasicBlock, + return wrapiter(_core.LLVMGetFirstBasicBlock, _core.LLVMGetNextBasicBlock, self.ptr, BasicBlock) def verify(self): @@ -967,8 +951,8 @@ class PHINode(Instruction): return _core.LLVMCountIncoming(self.ptr) def add_incoming(self, value, block): - _check_is_value(value) - _check_is_basic_block(block) + check_is_value(value) + check_is_basic_block(block) _core.LLVMAddIncoming1(self.ptr, value.ptr, block.ptr) def get_incoming_value(self, idx): @@ -984,8 +968,8 @@ class SwitchInstruction(Instruction): Instruction.__init__(self, ptr) def add_case(self, const, bblk): - _check_is_constant(const) # and has to be an int too - _check_is_basic_block(bblk) + check_is_constant(const) # and has to be an int too + check_is_basic_block(bblk) _core.LLVMAddCase(self.ptr, const.ptr, bblk.ptr) @@ -1012,7 +996,7 @@ class BasicBlock(Value): @property def instructions(self): - return _wrapiter(_core.LLVMGetFirstInstruction, + return wrapiter(_core.LLVMGetFirstInstruction, _core.LLVMGetNextInstruction, self.ptr, Instruction) @@ -1053,29 +1037,29 @@ class Builder(object): return Instruction(_core.LLVMBuildRetVoid(self.ptr)) def ret(self, value): - _check_is_value(value) + check_is_value(value) return Instruction(_core.LLVMBuildRet(self.ptr, value.ptr)) def branch(self, bblk): - _check_is_basic_block(bblk) + check_is_basic_block(bblk) return Instruction(_core.LLVMBuildBr(self.ptr, bblk.ptr)) def cbranch(self, if_value, then_blk, else_blk): - _check_is_value(if_value) - _check_is_basic_block(then_blk) - _check_is_basic_block(else_blk) + check_is_value(if_value) + check_is_basic_block(then_blk) + check_is_basic_block(else_blk) return Instruction(_core.LLVMBuildCondBr(self.ptr, if_value.ptr, then_blk.ptr, else_blk.ptr)) def switch(self, value, else_blk, n=10): - _check_is_value(value) - _check_is_basic_block(else_blk) + check_is_value(value) + check_is_basic_block(else_blk) return SwitchInstruction(_core.LLVMBuildSwitch(self.ptr, value.ptr, else_blk.ptr, n)) def invoke(self, func, args, then_blk, catch_blk, name=""): - _check_is_function(func) - _check_is_basic_block(then_blk) - _check_is_basic_block(catch_blk) - args2 = _unpack_values(args) + check_is_function(func) + check_is_basic_block(then_blk) + check_is_basic_block(catch_blk) + args2 = unpack_values(args) return CallOrInvokeInstruction(_core.LLVMBuildInvoke(self.ptr, func.ptr, args2, then_blk.ptr, catch_blk.ptr, name)) def unwind(self): @@ -1087,237 +1071,237 @@ class Builder(object): # arithmethic-related def add(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildAdd(self.ptr, lhs.ptr, rhs.ptr, name)) def sub(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildSub(self.ptr, lhs.ptr, rhs.ptr, name)) def mul(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildMul(self.ptr, lhs.ptr, rhs.ptr, name)) def udiv(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildUDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def sdiv(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildSDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def fdiv(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildFDiv(self.ptr, lhs.ptr, rhs.ptr, name)) def urem(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildURem(self.ptr, lhs.ptr, rhs.ptr, name)) def srem(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildSRem(self.ptr, lhs.ptr, rhs.ptr, name)) def frem(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildFRem(self.ptr, lhs.ptr, rhs.ptr, name)) def shl(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildShl(self.ptr, lhs.ptr, rhs.ptr, name)) def lshr(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildLShr(self.ptr, lhs.ptr, rhs.ptr, name)) def ashr(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildAShr(self.ptr, lhs.ptr, rhs.ptr, name)) def and_(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildAnd(self.ptr, lhs.ptr, rhs.ptr, name)) def or_(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildOr(self.ptr, lhs.ptr, rhs.ptr, name)) def xor(self, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildXor(self.ptr, lhs.ptr, rhs.ptr, name)) def neg(self, val, name=""): - _check_is_value(val) + check_is_value(val) return Instruction(_core.LLVMBuildNeg(self.ptr, val.ptr, name)) def not_(self, val, name=""): - _check_is_value(val) + check_is_value(val) return Instruction(_core.LLVMBuildNot(self.ptr, val.ptr, name)) # memory def malloc(self, ty, name=""): - _check_is_type(ty) + check_is_type(ty) return Instruction(_core.LLVMBuildMalloc(self.ptr, ty.ptr, name)) def malloc_array(self, ty, size, name=""): - _check_is_type(ty) - _check_is_value(size) + check_is_type(ty) + check_is_value(size) return Instruction(_core.LLVMBuildArrayMalloc(self.ptr, ty.ptr, size.ptr, name)) def alloca(self, ty, name=""): - _check_is_type(ty) - return Instruction(_core.LLVMBuildAlloc(self.ptr, ty.ptr, name)) + check_is_type(ty) + return Instruction(_core.LLVMBuildAlloca(self.ptr, ty.ptr, name)) def alloca_array(self, ty, size, name=""): - _check_is_type(ty) - _check_is_value(size) + check_is_type(ty) + check_is_value(size) return Instruction(_core.LLVMBuildArrayAlloca(self.ptr, ty.ptr, size.ptr, name)) def free(self, ptr): - _check_is_pointer(ptr) + check_is_value(ptr) return Instruction(_core.LLVMBuildFree(self.ptr, ptr.ptr)) def load(self, ptr, name=""): - _check_is_pointer(ptr) + check_is_value(ptr) return Instruction(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name)) def store(self, value, ptr): - _check_is_value(value) - _check_is_pointer(ptr) + check_is_value(value) + check_is_value(ptr) return Instruction(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr)) def gep(self, ptr, indices, name=""): - _check_is_pointer(ptr) - index_ptrs = _unpack_values(indices) + check_is_value(ptr) + index_ptrs = unpack_values(indices) return Value(_core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name)) # casts def trunc(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) def zext(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildZExt(self.ptr, value.ptr, dest_ty.ptr, name)) def sext(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildSExt(self.ptr, value.ptr, dest_ty.ptr, name)) def fptoui(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildFPToUI(self.ptr, value.ptr, dest_ty.ptr, name)) def fptosi(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildFPToSI(self.ptr, value.ptr, dest_ty.ptr, name)) def uitofp(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildUIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) def sitofp(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildSIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) def fptrunc(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildFPTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) def fpext(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildFPExt(self.ptr, value.ptr, dest_ty.ptr, name)) def ptrtoint(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildPtrToInt(self.ptr, value.ptr, dest_ty.ptr, name)) def inttoptr(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildIntToPtr(self.ptr, value.ptr, dest_ty.ptr, name)) def bitcast(self, value, dest_ty, name=""): - _check_is_value(value) - _check_is_type(dest_ty) + check_is_value(value) + check_is_type(dest_ty) return Value(_core.LLVMBuildBitCast(self.ptr, value.ptr, dest_ty.ptr, name)) # comparisons def icmp(self, ipred, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildICmp(self.ptr, ipred, lhs.ptr, rhs.ptr, name)) def fcmp(self, rpred, lhs, rhs, name=""): - _check_is_value(lhs) - _check_is_value(rhs) + check_is_value(lhs) + check_is_value(rhs) return Value(_core.LLVMBuildFCmp(self.ptr, rpred, lhs.ptr, rhs.ptr, name)) # misc def phi(self, ty, name=""): - _check_is_type(ty) + check_is_type(ty) return PHINode(_core.LLVMBuildPhi(self.ptr, ty.ptr, name)) def call(self, fn, args, name=""): - _check_is_function(fn) - arg_ptrs = _unpack_values(args) + check_is_function(fn) + 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) - _check_is_basic_block(then_blk) - _check_is_basic_block(else_blk) + check_is_basic_block(if_blk) + 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)) def vaarg(self, list_val, ty, name=""): - _check_is_value(list_val) - _check_is_type(ty) + check_is_value(list_val) + check_is_type(ty) return Instruction(_core.LLVMBuildVAArg(self.ptr, list_val.ptr, ty.ptr, name)) def extract_element(self, vec_val, idx_val, name=""): - _check_is_value(vec_val) - _check_is_value(idx_val) + check_is_value(vec_val) + check_is_value(idx_val) return Value(_core.LLVMBuildExtractElement(self.ptr, vec_val.ptr, idx_val.ptr, name)) def insert_element(self, vec_val, elt_val, idx_val, name=""): - _check_is_value(vec_val) - _check_is_value(elt_val) - _check_is_value(idx_val) + check_is_value(vec_val) + check_is_value(elt_val) + check_is_value(idx_val) return Value(_core.LLVMBuildInsertElement(self.ptr, vec_val.ptr, elt_val.ptr, idx_val.ptr, name)) def shuffle_vector(self, vecA, vecB, mask, name=""): - _check_is_value(vecA) - _check_is_value(vecB) - _check_is_value(mask) + check_is_value(vecA) + check_is_value(vecB) + check_is_value(mask) return Value(_core.LLVMBuildShuffleVector(self.ptr, vecA.ptr, vecB.ptr, mask.ptr, name)) @@ -1325,20 +1309,25 @@ class Builder(object): # Module provider #===----------------------------------------------------------------------=== - -class ModuleProvider(object): + +class ModuleProvider(llvm.Ownable): @staticmethod def new(module): - mp = ModuleProvider(_core.LLVMCreateModuleProviderForExistingModule(module.ptr)) - module._own(mp) - return mp + check_is_module(module) + check_is_unowned(module) + return ModuleProvider( + _core.LLVMCreateModuleProviderForExistingModule(module.ptr), + module) - def __init__(self, ptr): - self.ptr = ptr + def __init__(self, ptr, module): + llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModuleProvider) + module._own(self) + # a module provider is both a owner (of modules) and an ownable + # (can be owned by execution engines) def __del__(self): - _core.LLVMDisposeModuleProvider(self.ptr) + llvm.Ownable.__del__(self) #===----------------------------------------------------------------------=== @@ -1372,48 +1361,3 @@ class MemoryBuffer(object): def __del__(self): _core.LLVMDisposeMemoryBuffer(self.ptr) - -#===----------------------------------------------------------------------=== -# Pass manager -#===----------------------------------------------------------------------=== - -class PassManager(object): - - @staticmethod - def new(): - return PassManager(_core.LLVMCreatePassManager()) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposePassManager(self.ptr) - - def run(self, module): - _check_is_module(module) - return _core.LLVMRunPassManager(self.ptr, module.ptr) - - -class FunctionPassManager(PassManager): - - @staticmethod - def new(mp): - _check_is_module_provider(mp) - return FunctionPassManager(_core.LLVMCreateFunctionPassManager(mp.ptr)) - - def __init__(self, ptr): - PassManager.__init__(self, ptr) - - def __del__(self): - PassManager.__del__(self) - - def initialize(self): - _core.LLVMInitializeFunctionPassManager(self.ptr) - - def run(self, fn): - _check_is_function(fn) - return _core.LLVMRunFunctionPassManager(fn.ptr) - - def finalize(self): - _core.LLVMFinalizeFunctionPassManager(self.ptr) - diff --git a/llvm/ee.py b/llvm/ee.py index 918fe3a..2dafb8c 100644 --- a/llvm/ee.py +++ b/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 + diff --git a/llvm/passes.py b/llvm/passes.py index 208a788..fff381b 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -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) diff --git a/llvm/wrap.c b/llvm/wrap.c index d6cf4bb..062eef2 100644 --- a/llvm/wrap.c +++ b/llvm/wrap.c @@ -74,6 +74,9 @@ PyObject *ctor_int(int i) return PyInt_FromLong(i); } +_define_std_ctor(LLVMExecutionEngineRef) +_define_std_ctor(LLVMTargetDataRef) + /*===----------------------------------------------------------------------===*/ /* Helper functions */ diff --git a/llvm/wrap.h b/llvm/wrap.h index e231ef0..7be34b6 100644 --- a/llvm/wrap.h +++ b/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() diff --git a/setup.py b/setup.py index 95f7d37..a376d82 100644 --- a/setup.py +++ b/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) diff --git a/test/example.py b/test/example.py index f1e266a..3a61dde 100644 --- a/test/example.py +++ b/test/example.py @@ -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 diff --git a/test/test.py b/test/test.py index d400b23..7ac55c5 100644 --- a/test/test.py +++ b/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) diff --git a/www/src/about.txt b/www/src/about.txt index 3d073b8..d4fcdca 100644 --- a/www/src/about.txt +++ b/www/src/about.txt @@ -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]. diff --git a/www/src/contribute.txt b/www/src/contribute.txt index 93d7226..200b911 100644 --- a/www/src/contribute.txt +++ b/www/src/contribute.txt @@ -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 diff --git a/www/src/download.txt b/www/src/download.txt index aa7c2e3..866ec60 100644 --- a/www/src/download.txt +++ b/www/src/download.txt @@ -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[] ---- diff --git a/www/src/examples.txt b/www/src/examples.txt index b95013d..9eb17e0 100644 --- a/www/src/examples.txt +++ b/www/src/examples.txt @@ -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: