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() + +