Value.uses API

git-svn-id: http://llvm-py.googlecode.com/svn/trunk@70 8d1e9007-1d4e-0410-b67e-1979fd6579aa
This commit is contained in:
mdevan.foobar 2009-02-25 17:41:37 +00:00
commit d5328ef255
8 changed files with 152 additions and 17 deletions

View file

@ -322,6 +322,25 @@ _wrap_objstr2none(LLVMSetValueName, LLVMValueRef)
_wrap_obj2none(LLVMDumpValue, LLVMValueRef)
_wrap_dumper(LLVMDumpValueToString, LLVMValueRef)
_wrap_obj2obj(LLVMValueGetID, LLVMValueRef, int)
_wrap_obj2obj(LLVMValueGetNumUses, LLVMValueRef, int)
static PyObject *
_wLLVMValueGetUses(PyObject *self, PyObject *args)
{
LLVMValueRef value;
if (!(value = (LLVMValueRef)get_object_arg(args)))
return NULL;
LLVMValueRef *uses = 0;
unsigned n = LLVMValueGetUses(value, &uses);
PyObject *list = make_list_from_LLVMValueRef_array(uses, n);
if (n > 0)
LLVMDisposeValueRefArray(uses);
return list;
}
/*===-- Users ------------------------------------------------------------===*/
@ -1117,6 +1136,8 @@ static PyMethodDef core_methods[] = {
_method( LLVMDumpValue )
_method( LLVMDumpValueToString )
_method( LLVMValueGetID )
_method( LLVMValueGetNumUses )
_method( LLVMValueGetUses )
/* Users */

View file

@ -852,6 +852,14 @@ class Value(llvm.Cacheable):
kind = _core.LLVMGetTypeKind(ptr)
return _make_type(ptr, kind)
@property
def use_count(self):
return _core.LLVMValueGetNumUses(self.ptr)
@property
def uses(self):
return [ _make_value(v) for v in _core.LLVMValueGetUses(self.ptr) ]
class User(Value):

View file

@ -299,6 +299,47 @@ unsigned LLVMValueGetID(LLVMValueRef value)
return valuep->getValueID();
}
unsigned LLVMValueGetNumUses(LLVMValueRef value)
{
llvm::Value *valuep = llvm::unwrap(value);
assert(valuep);
return valuep->getNumUses();
}
unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs)
{
llvm::Value *valuep = llvm::unwrap(value);
assert(valuep);
unsigned n = valuep->getNumUses();
if (n == 0)
return 0;
assert(refs);
LLVMValueRef *out = (LLVMValueRef *)malloc(sizeof(LLVMValueRef) * n);
if (!out)
return 0;
*refs = out;
memset(out, 0, sizeof(LLVMValueRef) * n);
llvm::Value::use_iterator it = valuep->use_begin();
while (it != valuep->use_end()) {
*out++ = llvm::wrap(*it);
++it;
}
return n;
}
void LLVMDisposeValueRefArray(LLVMValueRef *refs)
{
assert(refs);
free(refs);
}
unsigned LLVMUserGetNumOperands(LLVMValueRef user)
{
llvm::User *userp = llvm::unwrap<llvm::User>(user);

View file

@ -69,6 +69,18 @@ LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value,
/* Wraps llvm::Value::getValueID(). */
unsigned LLVMValueGetID(LLVMValueRef value);
/* Wraps llvm::Value::getNumUses(). */
unsigned LLVMValueGetNumUses(LLVMValueRef value);
/* Wraps llvm::Value::use_{begin,end}. Allocates LLVMValueRef's as
* required. Number of objects are returned as return value. If that is
* greater than zero, the pointer given out must be freed by a
* subsequent call to LLVMDisposeValueRefArray(). */
unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs);
/* See above. */
void LLVMDisposeValueRefArray(LLVMValueRef *refs);
/* Wraps llvm:User::getNumOperands(). */
unsigned LLVMUserGetNumOperands(LLVMValueRef user);

View file

@ -98,19 +98,22 @@ void **make_array_from_list(PyObject *list, int n)
return arr;
}
PyObject *make_list_from_LLVMTypeRef_array(LLVMTypeRef *p, unsigned n)
{
size_t i;
PyObject *list = PyList_New(n);
if (!list)
return NULL;
for (i=0; i<n; i++) {
PyObject *elem = ctor_LLVMTypeRef(p[i]);
PyList_SetItem(list, i, elem);
}
return list;
#define LIST_FROM_ARRAY_IMPL(TYPE) \
PyObject *make_list_from_ ## TYPE ## _array( TYPE *p, unsigned n) \
{ \
size_t i; \
PyObject *list = PyList_New(n); \
\
if (!list) \
return NULL; \
\
for (i=0; i<n; i++) { \
PyObject *elem = ctor_ ## TYPE (p[i]); \
PyList_SetItem(list, i, elem); \
} \
\
return list; \
}
LIST_FROM_ARRAY_IMPL(LLVMTypeRef)
LIST_FROM_ARRAY_IMPL(LLVMValueRef)

View file

@ -98,12 +98,15 @@ void *get_object_arg(PyObject *args);
void **make_array_from_list(PyObject *list, int n);
/**
* Given an array of LLVMTypeRef's, create a PyList object. Note that
* currently such an action is required only for LLVMTypeRef's, when
* it is required another type, this method has to be generalized.
* Given an array of LLVMTypeRef's, create a PyList object.
*/
PyObject *make_list_from_LLVMTypeRef_array(LLVMTypeRef *p, unsigned n);
/**
* Given an array of LLVMValueRef's, create a PyList object.
*/
PyObject *make_list_from_LLVMValueRef_array(LLVMValueRef *p, unsigned n);
/*===----------------------------------------------------------------------===*/
/* Wrapper macros */

View file

@ -166,6 +166,8 @@ def do_value():
s = str(k)
s = k == Constant.int(ti, 43)
i = k.value_id
i = k.use_count
i = k.uses
def do_user():

45
test/uses.py Executable file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env python
from llvm.core import *
m = Module.new('a')
t = Type.int()
ft = Type.function(t, [t, t, t])
f = m.add_function(ft, "func")
b = f.append_basic_block('entry')
bld = Builder.new(b)
tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1")
tmp2 = bld.add(tmp1, f.args[1], "tmp2")
tmp3 = bld.add(tmp1, f.args[2], "tmp3")
bld.ret(tmp3)
print "-"*60
print m
print "-"*60
print "Testing use count ..",
c1 = f.args[0].use_count == 1
c2 = f.args[1].use_count == 1
c3 = f.args[2].use_count == 1
c4 = tmp1.use_count == 2
c5 = tmp2.use_count == 0
c6 = tmp3.use_count == 1
if c1 and c2 and c3 and c4 and c5 and c6:
print "OK"
else:
print "FAIL"
print "Testing uses ..",
c1 = f.args[0].uses[0] is tmp1
c2 = len(f.args[0].uses) == 1
c3 = f.args[1].uses[0] is tmp2
c4 = len(f.args[1].uses) == 1
c5 = f.args[2].uses[0] is tmp3
c6 = len(f.args[2].uses) == 1
c7 = len(tmp1.uses) == 2
c8 = len(tmp2.uses) == 0
c9 = len(tmp3.uses) == 1
if c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9:
print "OK"
else:
print "FAIL"