Merge branch 'master' of github.com:llvmpy/llvmpy

This commit is contained in:
Travis E. Oliphant 2012-08-08 17:49:34 -05:00
commit c1c9b6e724
9 changed files with 618 additions and 7 deletions

View file

@ -596,6 +596,7 @@ _wrap_obj2obj(LLVMInstIsArithmeticShift, LLVMValueRef, int)
_wrap_obj2obj(LLVMInstIsAssociative, LLVMValueRef, int)
_wrap_obj2obj(LLVMInstIsCommutative, LLVMValueRef, int)
_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int)
_wrap_objint2none(LLVMSetVolatile, LLVMValueRef)
_wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int)
_wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef)
@ -739,6 +740,14 @@ _wrap_objobjobjstr2obj(LLVMBuildBitCast, LLVMBuilderRef, LLVMValueRef, LLVMTypeR
_wrap_objenumobjobjstr2obj(LLVMBuildICmp, LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef)
_wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef)
/* Atomics */
_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef)
_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef)
/* Miscellaneous instructions */
_wrap_objobjintstr2obj(LLVMBuildGetResult, LLVMBuilderRef, LLVMValueRef, LLVMValueRef)
@ -1554,6 +1563,7 @@ static PyMethodDef core_methods[] = {
_method( LLVMInstIsAssociative )
_method( LLVMInstIsCommutative )
_method( LLVMInstIsVolatile )
_method( LLVMSetVolatile )
_method( LLVMInstGetOpcode )
_method( LLVMInstGetOpcodeName )
@ -1645,6 +1655,13 @@ static PyMethodDef core_methods[] = {
_method( LLVMBuildICmp )
_method( LLVMBuildFCmp )
/* Atomics */
_method( LLVMBuildAtomicCmpXchg )
_method( LLVMBuildAtomicRMW )
_method( LLVMBuildAtomicLoad )
_method( LLVMBuildAtomicStore )
_method( LLVMBuildFence )
/* Miscellaneous instructions */
_method( LLVMBuildGetResult )
_method( LLVMBuildPhi )

View file

@ -1458,6 +1458,9 @@ class Instruction(User):
"""True if this is a volatile load or store."""
return _core.LLVMInstIsVolatile(self.ptr) != 0
def set_volatile(self, flag):
return _core.LLVMSetVolatile(self.ptr, int(bool(flag)))
@property
def opcode(self):
return _core.LLVMInstGetOpcode(self.ptr)
@ -1827,14 +1830,20 @@ class Builder(object):
check_is_value(ptr)
return _make_value(_core.LLVMBuildFree(self.ptr, ptr.ptr))
def load(self, ptr, name=""):
def load(self, ptr, name="", volatile=False):
check_is_value(ptr)
return _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name))
inst = _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name))
if volatile:
inst.set_volatile(volatile)
return inst
def store(self, value, ptr):
def store(self, value, ptr, volatile=False):
check_is_value(value)
check_is_value(ptr)
return _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr))
inst = _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr))
if volatile:
inst.set_volatile(volatile)
return inst
def gep(self, ptr, indices, name=""):
check_is_value(ptr)
@ -1987,6 +1996,85 @@ class Builder(object):
_core.LLVMBuildShuffleVector(self.ptr,
vecA.ptr, vecB.ptr, mask.ptr, name))
# atomics
def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True):
check_is_value(ptr)
check_is_value(old)
check_is_value(new)
inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr,
ordering.lower(),
int(bool(crossthread)))
return _make_value(inst)
def atomic_rmw(self, op, ptr, val, ordering, crossthread=True):
check_is_value(ptr)
check_is_value(val)
inst = _core.LLVMBuildAtomicRMW(self.ptr, op.lower(), ptr.ptr, val.ptr,
ordering.lower(), int(bool(crossthread)))
return _make_value(inst)
def atomic_xchg(self, *args, **kwargs):
return self.atomic_rmw('xchg', *args, **kwargs)
def atomic_add(self, *args, **kwargs):
return self.atomic_rmw('add', *args, **kwargs)
def atomic_sub(self, *args, **kwargs):
return self.atomic_rmw('sub', *args, **kwargs)
def atomic_and(self, *args, **kwargs):
return self.atomic_rmw('and', *args, **kwargs)
def atomic_nand(self, *args, **kwargs):
return self.atomic_rmw('nand', *args, **kwargs)
def atomic_or(self, *args, **kwargs):
return self.atomic_rmw('or', *args, **kwargs)
def atomic_xor(self, *args, **kwargs):
return self.atomic_rmw('xor', *args, **kwargs)
def atomic_max(self, *args, **kwargs):
return self.atomic_rmw('max', *args, **kwargs)
def atomic_min(self, *args, **kwargs):
return self.atomic_rmw('min', *args, **kwargs)
def atomic_umax(self, *args, **kwargs):
return self.atomic_rmw('umax', *args, **kwargs)
def atomic_umin(self, *args, **kwargs):
return self.atomic_rmw('umin', *args, **kwargs)
def atomic_load(self, ptr, ordering, align=1, crossthread=True,
volatile=False, name=""):
check_is_value(ptr)
inst = _make_value(_core.LLVMBuildAtomicLoad(
self.ptr, ptr.ptr, int(align),
ordering.lower(), int(bool(crossthread))))
if volatile:
inst.set_volatile(volatile)
if inst:
inst.name = name
return inst
def atomic_store(self, value, ptr, ordering, align=1, crossthread=True,
volatile=False):
check_is_value(value)
check_is_value(ptr)
inst = _make_value(_core.LLVMBuildAtomicStore(
self.ptr, ptr.ptr, value.ptr, int(align),
ordering.lower(), int(bool(crossthread))))
if volatile:
inst.set_volatile(volatile)
return inst
def fence(self, ordering, crossthread=True):
inst = _make_value(_core.LLVMBuildFence(self.ptr, ordering.lower(),
int(bool(crossthread))))
return inst
#===----------------------------------------------------------------------===
# Memory buffer

View file

@ -110,6 +110,135 @@ char *do_print(W obj)
p->print(buf);
return strdup(buf.str().c_str());
}
static
llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering)
{
using namespace llvm;
if ( strcmp(ordering, "unordered") == 0 )
return Unordered;
else if ( strcmp(ordering, "monotonic") == 0 )
return Monotonic;
else if ( strcmp(ordering, "acquire") == 0 )
return Acquire;
else if ( strcmp(ordering, "release") == 0 )
return Release;
else if ( strcmp(ordering, "acq_rel") == 0 )
return AcquireRelease;
else if ( strcmp(ordering, "seq_cst") == 0 )
return SequentiallyConsistent;
else
return NotAtomic;
}
static
llvm::SynchronizationScope sync_scope_from_int(int crossthread)
{
if( crossthread )
return llvm::CrossThread;
else
return llvm::SingleThread;
}
LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering,
int crossthread)
{
using namespace llvm;
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
SynchronizationScope sync_scope = sync_scope_from_int(crossthread);
Value * inst = unwrap(builder)->CreateFence(atomic_order, sync_scope);
return wrap(inst);
}
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname,
LLVMValueRef ptr, LLVMValueRef val,
const char* ordering, int crossthread)
{
using namespace llvm;
AtomicRMWInst::BinOp op;
if( strcmp(opname, "xchg") == 0 )
op = AtomicRMWInst::Xchg;
else if( strcmp(opname, "add") == 0 )
op = AtomicRMWInst::Add;
else if( strcmp(opname, "sub") == 0 )
op = AtomicRMWInst::Sub;
else if( strcmp(opname, "and") == 0 )
op = AtomicRMWInst::And;
else if( strcmp(opname, "nand") == 0 )
op = AtomicRMWInst::Nand;
else if( strcmp(opname, "or") == 0 )
op = AtomicRMWInst::Or;
else if( strcmp(opname, "xor") == 0 )
op = AtomicRMWInst::Xor;
else if( strcmp(opname, "max") == 0 )
op = AtomicRMWInst::Max;
else if( strcmp(opname, "min") == 0 )
op = AtomicRMWInst::Min;
else if( strcmp(opname, "umax") == 0 )
op = AtomicRMWInst::UMax;
else if( strcmp(opname, "umin") == 0 )
op = AtomicRMWInst::UMin;
else
op = AtomicRMWInst::BAD_BINOP;
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
SynchronizationScope sync_scope = sync_scope_from_int(crossthread);
Value * inst = unwrap(builder)->CreateAtomicRMW(op, unwrap(ptr), unwrap(val),
atomic_order, sync_scope);
return wrap(inst);
}
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
unsigned align, const char* ordering,
int crossthread)
{
using namespace llvm;
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
SynchronizationScope sync_scope = sync_scope_from_int(crossthread);
LoadInst * inst = unwrap(builder)->CreateLoad(unwrap(ptr));
inst->setAtomic(atomic_order, sync_scope);
inst->setAlignment(align);
return wrap(inst);
}
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
LLVMValueRef ptr, LLVMValueRef val,
unsigned align, const char* ordering,
int crossthread)
{
using namespace llvm;
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
SynchronizationScope sync_scope = sync_scope_from_int(crossthread);
StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr));
inst->setAtomic(atomic_order, sync_scope);
inst->setAlignment(align);
return wrap(inst);
}
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr,
LLVMValueRef cmp, LLVMValueRef val,
const char* ordering, int crossthread)
{
using namespace llvm;
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
SynchronizationScope sync_scope = sync_scope_from_int(crossthread);
Value * inst = unwrap(builder)->CreateAtomicCmpXchg(
unwrap(ptr), unwrap(cmp), unwrap(val),
atomic_order, sync_scope);
return wrap(inst);
}
LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod)
{

View file

@ -45,6 +45,41 @@
extern "C" {
#endif
/*
* Wraps IRBuilder::CreateFence
*/
LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateLoad, LoadInst::setAtomic
*/
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
unsigned align, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateStore, StoreInst::setAtomic
*/
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
LLVMValueRef ptr, LLVMValueRef val,
unsigned align, const char* ordering,
int crossthread);
/*
* Wraps IRBuilder::CreateAtomicRMW
*/
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op,
LLVMValueRef ptr, LLVMValueRef val,
const char* ordering, int crossthread);
/*
* Wraps IRBuilder::CreateAtomicCmpXchg
*/
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr,
LLVMValueRef cmp, LLVMValueRef val,
const char* ordering, int crossthread);
/*
* Wraps new EngineBuilder
*/

View file

@ -671,6 +671,185 @@ _w ## func (PyObject *self, PyObject *args) \
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, const char *arg3, <unsigned/signed int> arg4)
*/
#define _wrap_objobjstrint2obj(func, intype1, intype2, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2; \
intype1 arg1; \
intype2 arg2; \
const char *arg3; \
int arg4; \
\
if (!PyArg_ParseTuple(args, "OOsi", &obj1, &obj2, &arg3, &arg4)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2 = ( intype2 ) PyCapsule_GetPointer(obj2, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, <unsigned/signed int> arg3, const char *arg4, <unsigned/signed int> arg5)
*/
#define _wrap_objobjintstrint2obj(func, intype1, intype2, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2; \
intype1 arg1; \
intype2 arg2; \
int arg3; \
const char *arg4; \
int arg5; \
\
if (!PyArg_ParseTuple(args, "OOisi", &obj1, &obj2, &arg3, &arg4, &arg5)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2 = ( intype2 ) PyCapsule_GetPointer(obj2, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, const char *arg2, <unsigned/signed int> arg3)
*/
#define _wrap_objstrint2obj(func, intype1, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1; \
intype1 arg1; \
const char *arg2; \
int arg3; \
\
if (!PyArg_ParseTuple(args, "Osi", &obj1, &arg2, &arg3)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, intype3, const char *arg4, <unsigned/signed int> arg5)
*/
#define _wrap_objobjobjstrint2obj(func, intype1, intype2, intype3, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2, *obj3; \
intype1 arg1; \
intype2 arg2; \
intype3 arg3; \
const char *arg4; \
int arg5; \
\
if (!PyArg_ParseTuple(args, "OOOsi", &obj1, &obj2, &obj3, &arg4, &arg5)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2 = ( intype2 ) PyCapsule_GetPointer(obj2, NULL); \
arg3 = ( intype3 ) PyCapsule_GetPointer(obj3, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, intype3, <unsigned/signed int> arg4, const char *arg5, <unsigned/signed int> arg6)
*/
#define _wrap_objobjobjintstrint2obj(func, intype1, intype2, intype3, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2, *obj3; \
intype1 arg1; \
intype2 arg2; \
intype3 arg3; \
int arg4; \
const char *arg5; \
int arg6; \
\
if (!PyArg_ParseTuple(args, "OOOisi", &obj1, &obj2, &obj3, &arg4, &arg5, &arg6)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2 = ( intype2 ) PyCapsule_GetPointer(obj2, NULL); \
arg3 = ( intype3 ) PyCapsule_GetPointer(obj3, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5, arg6)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
*/
#define _wrap_objobjobjobjstrint2obj(func, intype1, intype2, intype3, intype4, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2, *obj3, *obj4; \
intype1 arg1; \
intype2 arg2; \
intype3 arg3; \
intype4 arg4; \
const char *arg5; \
int arg6; \
\
if (!PyArg_ParseTuple(args, "OOOOsi", &obj1, &obj2, &obj3, &obj4, &arg5, &arg6)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2 = ( intype2 ) PyCapsule_GetPointer(obj2, NULL); \
arg3 = ( intype3 ) PyCapsule_GetPointer(obj3, NULL); \
arg4 = ( intype4 ) PyCapsule_GetPointer(obj4, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5, arg6)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, const char* arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
*/
#define _wrap_objstrobjobjstrint2obj(func, intype1, intype3, intype4, outtype)\
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj3, *obj4; \
intype1 arg1; \
const char *arg2; \
intype3 arg3; \
intype4 arg4; \
const char *arg5; \
int arg6; \
\
if (!PyArg_ParseTuple(args, "OsOOsi", &obj1, &arg2, &obj3, &obj4, &arg5, &arg6)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg3 = ( intype3 ) PyCapsule_GetPointer(obj3, NULL); \
arg4 = ( intype4 ) PyCapsule_GetPointer(obj4, NULL); \
\
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5, arg6)); \
}
/**
* Wrap LLVM functions of the type
* outtype func(intype1 arg1, intype2 arg2, intype3 arg3, <unsigned/signed int> arg4)

108
test/atomic.py Normal file
View file

@ -0,0 +1,108 @@
from llvm.core import *
import unittest
test_these_orderings = list(filter(bool, map(lambda s:s.strip(),
'''
unordered
monotonic
acquire
release
acq_rel
seq_cst
'''.splitlines())))
test_these_atomic_op = list(filter(bool, map(lambda s:s.strip(),
'''
xchg
add
sub
and
nand
or
xor
max
min
umax
umin
'''.splitlines())))
class TestAtomic(unittest.TestCase):
def test_atomic_cmpxchg(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
old = bldr.load(ptr)
new = Constant.int(Type.int(), 1234)
for ordering in test_these_orderings:
inst = bldr.atomic_cmpxchg(ptr, old, new, ordering)
self.assertEqual(ordering, str(inst).strip().split(' ')[-1])
inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False)
self.assertEqual('singlethread', str(inst).strip().split(' ')[-2])
def test_atomic_rmw(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
old = bldr.load(ptr)
val = Constant.int(Type.int(), 1234)
for ordering in test_these_orderings:
inst = bldr.atomic_rmw('xchg', ptr, val, ordering)
self.assertEqual(ordering, str(inst).split(' ')[-1])
for op in test_these_atomic_op:
inst = bldr.atomic_rmw(op, ptr, val, ordering)
self.assertEqual(op, str(inst).strip().split(' ')[3])
inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False)
self.assertEqual('singlethread', str(inst).strip().split(' ')[-2])
for op in test_these_atomic_op:
atomic_op = getattr(bldr, 'atomic_%s' % op)
inst = atomic_op(ptr, val, ordering)
self.assertEqual(op, str(inst).strip().split(' ')[3])
def test_atomic_ldst(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
val = Constant.int(Type.int(), 1234)
for ordering in test_these_orderings:
loaded = bldr.atomic_load(ptr, ordering)
self.assertIn('load atomic', str(loaded))
self.assertEqual(ordering,
str(loaded).strip().split(' ')[-3].rstrip(','))
self.assertIn('align 1', str(loaded))
stored = bldr.atomic_store(loaded, ptr, ordering)
self.assertIn('store atomic', str(stored))
self.assertEqual(ordering,
str(stored).strip().split(' ')[-3].rstrip(','))
self.assertIn('align 1', str(stored))
fenced = bldr.fence(ordering)
self.assertEqual(['fence', ordering], str(fenced).strip().split(' '))
if __name__ == '__main__':
unittest.main()

View file

@ -610,7 +610,7 @@ def do_functionpassmanager():
b.ret(Constant.int(ti, 42))
fpm = FunctionPassManager.new(m)
fpm.add(TargetData.new(''))
fpm.add(PASS_AGGRESSIVE_DCE)
fpm.add(PASS_ADCE)
fpm.initialize()
fpm.run(f)
fpm.finalize()

View file

@ -21,7 +21,7 @@ class TestUses(unittest.TestCase):
logging.debug(m)
logging.debug("-"*60)
logging.debug("Testing use count ..", end=' ')
logging.debug("Testing use count ..")
self.assertEqual(f.args[0].use_count, 1)
self.assertEqual(f.args[1].use_count, 1)
self.assertEqual(f.args[2].use_count, 1)
@ -29,7 +29,7 @@ class TestUses(unittest.TestCase):
self.assertEqual(tmp2.use_count, 0)
self.assertEqual(tmp3.use_count, 1)
logging.debug("Testing uses ..", end=' ')
logging.debug("Testing uses ..")
self.assertIs(f.args[0].uses[0], tmp1)
self.assertEqual(len(f.args[0].uses), 1)
self.assertIs(f.args[1].uses[0], tmp2)

55
test/volatile.py Normal file
View file

@ -0,0 +1,55 @@
from llvm.core import *
import unittest
class TestVolatile(unittest.TestCase):
def test_volatile(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
# test load inst
val = bldr.load(ptr)
self.assertFalse(val.is_volatile, "default must be non-volatile")
val.set_volatile(True)
self.assertTrue(val.is_volatile, "fail to set volatile")
val.set_volatile(False)
self.assertFalse(val.is_volatile, "fail to unset volatile")
# test store inst
store_inst = bldr.store(val, ptr)
self.assertFalse(store_inst.is_volatile, "default must be non-volatile")
store_inst.set_volatile(True)
self.assertTrue(store_inst.is_volatile, "fail to set volatile")
store_inst.set_volatile(False)
self.assertFalse(store_inst.is_volatile, "fail to unset volatile")
def test_volatile_another(self):
mod = Module.new('mod')
functype = Type.function(Type.void(), [])
func = mod.add_function(functype, name='foo')
bb = func.append_basic_block('entry')
bldr = Builder.new(bb)
ptr = bldr.alloca(Type.int())
# test load inst
val = bldr.load(ptr, volatile=True)
self.assertTrue(val.is_volatile, "volatile kwarg does not work")
val.set_volatile(False)
self.assertFalse(val.is_volatile, "fail to unset volatile")
val.set_volatile(True)
self.assertTrue(val.is_volatile, "fail to set volatile")
# test store inst
store_inst = bldr.store(val, ptr, volatile=True)
self.assertTrue(store_inst.is_volatile, "volatile kwarg does not work")
store_inst.set_volatile(False)
self.assertFalse(store_inst.is_volatile, "fail to unset volatile")
store_inst.set_volatile(True)
self.assertTrue(store_inst.is_volatile, "fail to set volatile")
if __name__ == '__main__':
unittest.main()