From 9d068fd582659b1650ab37801879d09e8e3428be Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 2 Aug 2012 16:51:42 -0700 Subject: [PATCH 1/9] Add methods to set volatile inst. --- llvm/_core.cpp | 2 ++ llvm/core.py | 17 +++++++++++---- test/volatile.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 test/volatile.py diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 765d106..821537e 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -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) @@ -1554,6 +1555,7 @@ static PyMethodDef core_methods[] = { _method( LLVMInstIsAssociative ) _method( LLVMInstIsCommutative ) _method( LLVMInstIsVolatile ) + _method( LLVMSetVolatile ) _method( LLVMInstGetOpcode ) _method( LLVMInstGetOpcodeName ) diff --git a/llvm/core.py b/llvm/core.py index f4c75bf..f1cade7 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -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) diff --git a/test/volatile.py b/test/volatile.py new file mode 100644 index 0000000..e567a80 --- /dev/null +++ b/test/volatile.py @@ -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() From acad5c9d8badf380b1fcd55845eff72e0c3a2e7b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 2 Aug 2012 17:54:40 -0700 Subject: [PATCH 2/9] Added atomic cmpxchg. --- llvm/_core.cpp | 7 +++++++ llvm/core.py | 9 +++++++++ llvm/extra.cpp | 39 +++++++++++++++++++++++++++++++++++++++ llvm/extra.h | 8 ++++++++ llvm/wrap.h | 28 ++++++++++++++++++++++++++++ test/atomic.py | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 127 insertions(+) create mode 100644 test/atomic.py diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 821537e..d1100ea 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -740,6 +740,10 @@ _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) + /* Miscellaneous instructions */ _wrap_objobjintstr2obj(LLVMBuildGetResult, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) @@ -1647,6 +1651,9 @@ static PyMethodDef core_methods[] = { _method( LLVMBuildICmp ) _method( LLVMBuildFCmp ) + /* Atomics */ + _method( LLVMBuildAtomicCmpXchg ) + /* Miscellaneous instructions */ _method( LLVMBuildGetResult ) _method( LLVMBuildPhi ) diff --git a/llvm/core.py b/llvm/core.py index f1cade7..7ae22ea 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1996,6 +1996,15 @@ 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) #===----------------------------------------------------------------------=== # Memory buffer diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 858fbcf..0d71065 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -111,6 +111,45 @@ char *do_print(W obj) return strdup(buf.str().c_str()); } +LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, + LLVMValueRef cmp, LLVMValueRef val, + const char* ordering, int crossthread) +{ + using namespace llvm; + + AtomicOrdering ordering_enum; + + if ( strcmp(ordering, "unordered") == 0 ) + ordering_enum = Unordered; + else if ( strcmp(ordering, "monotonic") == 0 ) + ordering_enum = Monotonic; + else if ( strcmp(ordering, "acquire") == 0 ) + ordering_enum = Acquire; + else if ( strcmp(ordering, "release") == 0 ) + ordering_enum = Release; + else if ( strcmp(ordering, "acq_rel") == 0 ) + ordering_enum = AcquireRelease; + else if ( strcmp(ordering, "seq_cst") == 0 ) + ordering_enum = SequentiallyConsistent; + else + ordering_enum = NotAtomic; + + SynchronizationScope crossthread_enum; + switch( crossthread ){ + case 0: + crossthread_enum = SingleThread; + break; + default: + crossthread_enum = CrossThread; + } + + + Value * inst = unwrap(builder)->CreateAtomicCmpXchg( + unwrap(ptr), unwrap(cmp), unwrap(val), + ordering_enum, crossthread_enum); + return wrap(inst); +} + LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod) { using namespace llvm; diff --git a/llvm/extra.h b/llvm/extra.h index b0bacc8..b02c527 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -45,6 +45,14 @@ extern "C" { #endif + +/* + * Wraps IRBuilder::CreateAtomicCmpXchg + */ +LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, + LLVMValueRef cmp, LLVMValueRef val, + const char* ordering, int crossthread); + /* * Wraps new EngineBuilder */ diff --git a/llvm/wrap.h b/llvm/wrap.h index 754d9d0..f754b02 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -671,6 +671,34 @@ _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, intype3 arg3, intype4, const char *arg5, 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, intype2 arg2, intype3 arg3, arg4) diff --git a/test/atomic.py b/test/atomic.py new file mode 100644 index 0000000..7cbbf49 --- /dev/null +++ b/test/atomic.py @@ -0,0 +1,36 @@ +from llvm.core import * +import unittest + +test_these_orderings = filter(bool, map(lambda s:s.strip(), +''' +unordered +monotonic +acquire +release +acq_rel +seq_cst +'''.splitlines())) + +class TestAtomic(unittest.TestCase): + def test_atomic(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).split(' ')[-1]) + + + inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) + self.assertEqual('singlethread', str(inst).split(' ')[-2]) + +if __name__ == '__main__': + unittest.main() From fb72ab5c8d6feb69a47b6cabf5d99e13f2f75466 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 Aug 2012 10:14:09 -0700 Subject: [PATCH 3/9] Add the rest of atomic op. --- llvm/_core.cpp | 2 + llvm/core.py | 10 ++++- llvm/extra.cpp | 100 ++++++++++++++++++++++++++++++++++++------------- llvm/extra.h | 6 +++ llvm/wrap.h | 26 +++++++++++++ test/atomic.py | 48 +++++++++++++++++++++--- 6 files changed, 159 insertions(+), 33 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index d1100ea..7b0d31a 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -743,6 +743,7 @@ _wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLV /* Atomics */ _wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) +_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) /* Miscellaneous instructions */ @@ -1653,6 +1654,7 @@ static PyMethodDef core_methods[] = { /* Atomics */ _method( LLVMBuildAtomicCmpXchg ) + _method( LLVMBuildAtomicRMW ) /* Miscellaneous instructions */ _method( LLVMBuildGetResult ) diff --git a/llvm/core.py b/llvm/core.py index 7ae22ea..2219aa7 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2003,7 +2003,15 @@ class Builder(object): check_is_value(old) check_is_value(new) inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr, - ordering.lower(), int(bool(crossthread))) + 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) #===----------------------------------------------------------------------=== diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 0d71065..e36ef99 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -110,6 +110,76 @@ 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 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 LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val, @@ -117,36 +187,12 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, { using namespace llvm; - AtomicOrdering ordering_enum; - - if ( strcmp(ordering, "unordered") == 0 ) - ordering_enum = Unordered; - else if ( strcmp(ordering, "monotonic") == 0 ) - ordering_enum = Monotonic; - else if ( strcmp(ordering, "acquire") == 0 ) - ordering_enum = Acquire; - else if ( strcmp(ordering, "release") == 0 ) - ordering_enum = Release; - else if ( strcmp(ordering, "acq_rel") == 0 ) - ordering_enum = AcquireRelease; - else if ( strcmp(ordering, "seq_cst") == 0 ) - ordering_enum = SequentiallyConsistent; - else - ordering_enum = NotAtomic; - - SynchronizationScope crossthread_enum; - switch( crossthread ){ - case 0: - crossthread_enum = SingleThread; - break; - default: - crossthread_enum = CrossThread; - } - + 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), - ordering_enum, crossthread_enum); + atomic_order, sync_scope); return wrap(inst); } diff --git a/llvm/extra.h b/llvm/extra.h index b02c527..5a11d0b 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -45,6 +45,12 @@ extern "C" { #endif +/* + * Wraps IRBuilder::CreateAtomicRMW + */ +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op, + LLVMValueRef ptr, LLVMValueRef val, + const char* ordering, int crossthread); /* * Wraps IRBuilder::CreateAtomicCmpXchg diff --git a/llvm/wrap.h b/llvm/wrap.h index f754b02..15c90e9 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -699,6 +699,32 @@ _w ## func (PyObject *self, PyObject *args) \ 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, 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, arg4) diff --git a/test/atomic.py b/test/atomic.py index 7cbbf49..5e3d9b0 100644 --- a/test/atomic.py +++ b/test/atomic.py @@ -1,7 +1,7 @@ from llvm.core import * import unittest -test_these_orderings = filter(bool, map(lambda s:s.strip(), +test_these_orderings = list(filter(bool, map(lambda s:s.strip(), ''' unordered monotonic @@ -9,10 +9,25 @@ acquire release acq_rel seq_cst -'''.splitlines())) +'''.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(self): + def test_atomic_cmpxchg(self): mod = Module.new('mod') functype = Type.function(Type.void(), []) func = mod.add_function(functype, name='foo') @@ -26,11 +41,34 @@ class TestAtomic(unittest.TestCase): for ordering in test_these_orderings: inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) - self.assertEqual(ordering, str(inst).split(' ')[-1]) + self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) - self.assertEqual('singlethread', str(inst).split(' ')[-2]) + 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]) + if __name__ == '__main__': unittest.main() From 4d763680f6c7cebfd18de8aec99c9762360cd86f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 Aug 2012 10:28:17 -0700 Subject: [PATCH 4/9] Add easier atomic api --- llvm/core.py | 34 ++++++++++++++++++++++++++++++++++ test/atomic.py | 6 ++++++ 2 files changed, 40 insertions(+) diff --git a/llvm/core.py b/llvm/core.py index 2219aa7..5186c55 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2014,6 +2014,40 @@ class Builder(object): 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) + + #===----------------------------------------------------------------------=== # Memory buffer #===----------------------------------------------------------------------=== diff --git a/test/atomic.py b/test/atomic.py index 5e3d9b0..92be0e7 100644 --- a/test/atomic.py +++ b/test/atomic.py @@ -62,6 +62,7 @@ class TestAtomic(unittest.TestCase): 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]) @@ -70,5 +71,10 @@ class TestAtomic(unittest.TestCase): 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]) + if __name__ == '__main__': unittest.main() From 6ac0f3c3697abf3690e8036851336465d3c03d57 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 Aug 2012 11:56:59 -0700 Subject: [PATCH 5/9] Add atomic load/store --- llvm/_core.cpp | 4 ++++ llvm/core.py | 22 ++++++++++++++++++++++ llvm/extra.cpp | 29 +++++++++++++++++++++++++++++ llvm/extra.h | 13 +++++++++++++ llvm/wrap.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ test/atomic.py | 20 ++++++++++++++++++++ 6 files changed, 136 insertions(+) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 7b0d31a..7abee27 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -744,6 +744,8 @@ _wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLV /* Atomics */ _wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) _wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) +_wrap_objobjstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) +_wrap_objobjobjstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) /* Miscellaneous instructions */ @@ -1655,6 +1657,8 @@ static PyMethodDef core_methods[] = { /* Atomics */ _method( LLVMBuildAtomicCmpXchg ) _method( LLVMBuildAtomicRMW ) + _method( LLVMBuildAtomicLoad ) + _method( LLVMBuildAtomicStore ) /* Miscellaneous instructions */ _method( LLVMBuildGetResult ) diff --git a/llvm/core.py b/llvm/core.py index 5186c55..bdb1485 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2048,6 +2048,28 @@ class Builder(object): return self.atomic_rmw('umin', *args, **kwargs) + def atomic_load(self, ptr, ordering, crossthread=True, volatile=False, name=""): + check_is_value(ptr) + inst = _make_value(_core.LLVMBuildAtomicLoad( + self.ptr, ptr.ptr, 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, crossthread=True, + volatile=False): + check_is_value(value) + check_is_value(ptr) + inst = _make_value(_core.LLVMBuildAtomicStore( + self.ptr, ptr.ptr, value.ptr, + ordering.lower(), int(bool(crossthread)))) + if volatile: + inst.set_volatile(volatile) + return inst + #===----------------------------------------------------------------------=== # Memory buffer #===----------------------------------------------------------------------=== diff --git a/llvm/extra.cpp b/llvm/extra.cpp index e36ef99..ca5e0ea 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -181,6 +181,35 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname, return wrap(inst); } +LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, + 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); + + return wrap(inst); +} + +LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, + LLVMValueRef ptr, 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); + + StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr)); + + inst->setAtomic(atomic_order, sync_scope); + + return wrap(inst); +} + LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val, const char* ordering, int crossthread) diff --git a/llvm/extra.h b/llvm/extra.h index 5a11d0b..b773f19 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -45,6 +45,19 @@ extern "C" { #endif + +/* + * Wraps IRBuilder::CreateLoad, setAtomic + */ +LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, + const char* ordering, int crossthread); +/* + * Wraps IRBuilder::CreateStore, setAtomic + */ +LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, + LLVMValueRef ptr, LLVMValueRef val, + const char* ordering, int crossthread); + /* * Wraps IRBuilder::CreateAtomicRMW */ diff --git a/llvm/wrap.h b/llvm/wrap.h index 15c90e9..fec5b72 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -671,6 +671,54 @@ _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, 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, intype3, const char *arg4, 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 diff --git a/test/atomic.py b/test/atomic.py index 92be0e7..ad99525 100644 --- a/test/atomic.py +++ b/test/atomic.py @@ -76,5 +76,25 @@ class TestAtomic(unittest.TestCase): 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(' ')[-1]) + stored = bldr.atomic_store(loaded, ptr, ordering) + self.assertIn('store atomic', str(stored)) + self.assertEqual(ordering, str(stored).strip().split(' ')[-1]) + if __name__ == '__main__': unittest.main() + + From f479f85676f25006afa680662ae6e5c65875a8c9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 Aug 2012 12:30:01 -0700 Subject: [PATCH 6/9] Add memory fence --- llvm/_core.cpp | 2 ++ llvm/core.py | 5 +++++ llvm/extra.cpp | 11 +++++++++++ llvm/extra.h | 10 ++++++++-- llvm/wrap.h | 23 +++++++++++++++++++++++ test/atomic.py | 5 +++++ 6 files changed, 54 insertions(+), 2 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index 7abee27..c904ad1 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -746,6 +746,7 @@ _wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRe _wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) _wrap_objobjstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) _wrap_objobjobjstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) +_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef) /* Miscellaneous instructions */ @@ -1659,6 +1660,7 @@ static PyMethodDef core_methods[] = { _method( LLVMBuildAtomicRMW ) _method( LLVMBuildAtomicLoad ) _method( LLVMBuildAtomicStore ) + _method( LLVMBuildFence ) /* Miscellaneous instructions */ _method( LLVMBuildGetResult ) diff --git a/llvm/core.py b/llvm/core.py index bdb1485..962b018 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2070,6 +2070,11 @@ class Builder(object): 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 #===----------------------------------------------------------------------=== diff --git a/llvm/extra.cpp b/llvm/extra.cpp index ca5e0ea..cd6aeee 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -140,6 +140,17 @@ llvm::SynchronizationScope sync_scope_from_int(int crossthread) 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) diff --git a/llvm/extra.h b/llvm/extra.h index b773f19..9bd0ddb 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -47,12 +47,18 @@ extern "C" { /* - * Wraps IRBuilder::CreateLoad, setAtomic + * Wraps IRBuilder::CreateFence + */ +LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, + int crossthread); + +/* + * Wraps IRBuilder::CreateLoad, LoadInst::setAtomic */ LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, const char* ordering, int crossthread); /* - * Wraps IRBuilder::CreateStore, setAtomic + * Wraps IRBuilder::CreateStore, StoreInst::setAtomic */ LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef val, diff --git a/llvm/wrap.h b/llvm/wrap.h index fec5b72..9cebd74 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -694,6 +694,29 @@ _w ## func (PyObject *self, PyObject *args) \ return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4)); \ } + +/** + * Wrap LLVM functions of the type + * outtype func(intype1 arg1, const char *arg2, 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, arg5) diff --git a/test/atomic.py b/test/atomic.py index ad99525..dc4896d 100644 --- a/test/atomic.py +++ b/test/atomic.py @@ -90,10 +90,15 @@ class TestAtomic(unittest.TestCase): loaded = bldr.atomic_load(ptr, ordering) self.assertIn('load atomic', str(loaded)) self.assertEqual(ordering, str(loaded).strip().split(' ')[-1]) + stored = bldr.atomic_store(loaded, ptr, ordering) self.assertIn('store atomic', str(stored)) self.assertEqual(ordering, str(stored).strip().split(' ')[-1]) + fenced = bldr.fence(ordering) + self.assertEqual(['fence', ordering], str(fenced).strip().split(' ')) + + if __name__ == '__main__': unittest.main() From 5e15b2790982edf84016e0794713933e354beb92 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 3 Aug 2012 14:13:22 -0700 Subject: [PATCH 7/9] Atomic load/store must explicit define alignment. --- llvm/_core.cpp | 4 ++-- llvm/core.py | 11 +++++----- llvm/extra.cpp | 8 ++++++-- llvm/extra.h | 6 ++++-- llvm/wrap.h | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/atomic.py | 9 ++++++--- 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/llvm/_core.cpp b/llvm/_core.cpp index c904ad1..14143f2 100644 --- a/llvm/_core.cpp +++ b/llvm/_core.cpp @@ -744,8 +744,8 @@ _wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLV /* Atomics */ _wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) _wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) +_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) +_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) _wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef) /* Miscellaneous instructions */ diff --git a/llvm/core.py b/llvm/core.py index 962b018..47b3b8a 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2048,23 +2048,24 @@ class Builder(object): return self.atomic_rmw('umin', *args, **kwargs) - def atomic_load(self, ptr, ordering, crossthread=True, volatile=False, name=""): + 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, ordering.lower(), - int(bool(crossthread)))) + 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, crossthread=True, + 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, + self.ptr, ptr.ptr, value.ptr, int(align), ordering.lower(), int(bool(crossthread)))) if volatile: inst.set_volatile(volatile) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index cd6aeee..122d387 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -193,7 +193,8 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname, } LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - const char* ordering, int crossthread) + unsigned align, const char* ordering, + int crossthread) { using namespace llvm; AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); @@ -202,13 +203,15 @@ LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, 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, - const char* ordering, int crossthread) + unsigned align, const char* ordering, + int crossthread) { using namespace llvm; AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); @@ -217,6 +220,7 @@ LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr)); inst->setAtomic(atomic_order, sync_scope); + inst->setAlignment(align); return wrap(inst); } diff --git a/llvm/extra.h b/llvm/extra.h index 9bd0ddb..b13c80f 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -56,13 +56,15 @@ LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, * Wraps IRBuilder::CreateLoad, LoadInst::setAtomic */ LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - const char* ordering, int crossthread); + unsigned align, const char* ordering, + int crossthread); /* * Wraps IRBuilder::CreateStore, StoreInst::setAtomic */ LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread); + unsigned align, const char* ordering, + int crossthread); /* * Wraps IRBuilder::CreateAtomicRMW diff --git a/llvm/wrap.h b/llvm/wrap.h index 9cebd74..bceca87 100644 --- a/llvm/wrap.h +++ b/llvm/wrap.h @@ -695,6 +695,31 @@ _w ## func (PyObject *self, PyObject *args) \ } + +/** + * Wrap LLVM functions of the type + * outtype func(intype1 arg1, intype2 arg2, arg3, const char *arg4, 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, arg3) @@ -743,6 +768,34 @@ _w ## func (PyObject *self, PyObject *args) \ } + + +/** + * Wrap LLVM functions of the type + * outtype func(intype1 arg1, intype2 arg2, intype3, arg4, const char *arg5, 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, arg6) @@ -770,6 +823,7 @@ _w ## func (PyObject *self, PyObject *args) \ 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, arg6) diff --git a/test/atomic.py b/test/atomic.py index dc4896d..fd565cc 100644 --- a/test/atomic.py +++ b/test/atomic.py @@ -89,16 +89,19 @@ class TestAtomic(unittest.TestCase): 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(' ')[-1]) + 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(' ')[-1]) + 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() From 938763ef07cd0687854f0b02c8539310ba4cec91 Mon Sep 17 00:00:00 2001 From: "Bradley M. Froehle" Date: Tue, 7 Aug 2012 15:38:06 -0700 Subject: [PATCH 8/9] Fix broken testall.py (NameError: PASS_AGGRESSIVE_DCE) Commit 2d79cfa43 renamed PASS_AGGRESSIVE_DCE -> PASS_ADCE but missed an instance in one test. --- test/testall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testall.py b/test/testall.py index acf330b..ed7a8a1 100755 --- a/test/testall.py +++ b/test/testall.py @@ -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() From d3548e5377a88489c84ac75195768520c7b68e46 Mon Sep 17 00:00:00 2001 From: "Bradley M. Froehle" Date: Tue, 7 Aug 2012 15:56:05 -0700 Subject: [PATCH 9/9] test_uses: Fix unexpected keyword argument 'end' with `nosetests uses.py` Logging does not know about the keyword argument 'end'. The existing code works only because the default logging level prevents debug messages from running. When running the test under `nosetests` the debug messages are enabled leading to the error. --- test/uses.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/uses.py b/test/uses.py index 97040fa..1b13aa6 100755 --- a/test/uses.py +++ b/test/uses.py @@ -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)