Add atomic load/store
This commit is contained in:
parent
4d763680f6
commit
6ac0f3c369
6 changed files with 136 additions and 0 deletions
|
|
@ -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 )
|
||||
|
|
|
|||
22
llvm/core.py
22
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
|
||||
#===----------------------------------------------------------------------===
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
13
llvm/extra.h
13
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
|
||||
*/
|
||||
|
|
|
|||
48
llvm/wrap.h
48
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, <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, 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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue