Atomic load/store must explicit define alignment.
This commit is contained in:
parent
f479f85676
commit
5e15b27909
6 changed files with 78 additions and 14 deletions
|
|
@ -744,8 +744,8 @@ _wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLV
|
||||||
/* Atomics */
|
/* Atomics */
|
||||||
_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
||||||
_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
||||||
_wrap_objobjstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef)
|
_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef)
|
||||||
_wrap_objobjobjstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef)
|
||||||
_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef)
|
_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef)
|
||||||
|
|
||||||
/* Miscellaneous instructions */
|
/* Miscellaneous instructions */
|
||||||
|
|
|
||||||
11
llvm/core.py
11
llvm/core.py
|
|
@ -2048,23 +2048,24 @@ class Builder(object):
|
||||||
return self.atomic_rmw('umin', *args, **kwargs)
|
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)
|
check_is_value(ptr)
|
||||||
inst = _make_value(_core.LLVMBuildAtomicLoad(
|
inst = _make_value(_core.LLVMBuildAtomicLoad(
|
||||||
self.ptr, ptr.ptr, ordering.lower(),
|
self.ptr, ptr.ptr, int(align),
|
||||||
int(bool(crossthread))))
|
ordering.lower(), int(bool(crossthread))))
|
||||||
if volatile:
|
if volatile:
|
||||||
inst.set_volatile(volatile)
|
inst.set_volatile(volatile)
|
||||||
if inst:
|
if inst:
|
||||||
inst.name = name
|
inst.name = name
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
def atomic_store(self, value, ptr, ordering, crossthread=True,
|
def atomic_store(self, value, ptr, ordering, align=1, crossthread=True,
|
||||||
volatile=False):
|
volatile=False):
|
||||||
check_is_value(value)
|
check_is_value(value)
|
||||||
check_is_value(ptr)
|
check_is_value(ptr)
|
||||||
inst = _make_value(_core.LLVMBuildAtomicStore(
|
inst = _make_value(_core.LLVMBuildAtomicStore(
|
||||||
self.ptr, ptr.ptr, value.ptr,
|
self.ptr, ptr.ptr, value.ptr, int(align),
|
||||||
ordering.lower(), int(bool(crossthread))))
|
ordering.lower(), int(bool(crossthread))))
|
||||||
if volatile:
|
if volatile:
|
||||||
inst.set_volatile(volatile)
|
inst.set_volatile(volatile)
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,8 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname,
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
|
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
|
||||||
const char* ordering, int crossthread)
|
unsigned align, const char* ordering,
|
||||||
|
int crossthread)
|
||||||
{
|
{
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
|
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));
|
LoadInst * inst = unwrap(builder)->CreateLoad(unwrap(ptr));
|
||||||
|
|
||||||
inst->setAtomic(atomic_order, sync_scope);
|
inst->setAtomic(atomic_order, sync_scope);
|
||||||
|
inst->setAlignment(align);
|
||||||
|
|
||||||
return wrap(inst);
|
return wrap(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
|
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
|
||||||
LLVMValueRef ptr, LLVMValueRef val,
|
LLVMValueRef ptr, LLVMValueRef val,
|
||||||
const char* ordering, int crossthread)
|
unsigned align, const char* ordering,
|
||||||
|
int crossthread)
|
||||||
{
|
{
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
AtomicOrdering atomic_order = atomic_ordering_from_string(ordering);
|
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));
|
StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr));
|
||||||
|
|
||||||
inst->setAtomic(atomic_order, sync_scope);
|
inst->setAtomic(atomic_order, sync_scope);
|
||||||
|
inst->setAlignment(align);
|
||||||
|
|
||||||
return wrap(inst);
|
return wrap(inst);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,15 @@ LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering,
|
||||||
* Wraps IRBuilder::CreateLoad, LoadInst::setAtomic
|
* Wraps IRBuilder::CreateLoad, LoadInst::setAtomic
|
||||||
*/
|
*/
|
||||||
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
|
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr,
|
||||||
const char* ordering, int crossthread);
|
unsigned align, const char* ordering,
|
||||||
|
int crossthread);
|
||||||
/*
|
/*
|
||||||
* Wraps IRBuilder::CreateStore, StoreInst::setAtomic
|
* Wraps IRBuilder::CreateStore, StoreInst::setAtomic
|
||||||
*/
|
*/
|
||||||
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
|
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder,
|
||||||
LLVMValueRef ptr, LLVMValueRef val,
|
LLVMValueRef ptr, LLVMValueRef val,
|
||||||
const char* ordering, int crossthread);
|
unsigned align, const char* ordering,
|
||||||
|
int crossthread);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wraps IRBuilder::CreateAtomicRMW
|
* Wraps IRBuilder::CreateAtomicRMW
|
||||||
|
|
|
||||||
54
llvm/wrap.h
54
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, <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
|
* Wrap LLVM functions of the type
|
||||||
* outtype func(intype1 arg1, const char *arg2, <unsigned/signed int> arg3)
|
* outtype func(intype1 arg1, const char *arg2, <unsigned/signed int> arg3)
|
||||||
|
|
@ -743,6 +768,34 @@ _w ## func (PyObject *self, PyObject *args) \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Wrap LLVM functions of the type
|
||||||
* outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
|
* outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
|
||||||
|
|
@ -770,6 +823,7 @@ _w ## func (PyObject *self, PyObject *args) \
|
||||||
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5, arg6)); \
|
return ctor_ ## outtype ( func (arg1, arg2, arg3, arg4, arg5, arg6)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap LLVM functions of the type
|
* Wrap LLVM functions of the type
|
||||||
* outtype func(intype1 arg1, const char* arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
|
* outtype func(intype1 arg1, const char* arg2, intype3 arg3, intype4, const char *arg5, <unsigned/signed int> arg6)
|
||||||
|
|
|
||||||
|
|
@ -89,16 +89,19 @@ class TestAtomic(unittest.TestCase):
|
||||||
for ordering in test_these_orderings:
|
for ordering in test_these_orderings:
|
||||||
loaded = bldr.atomic_load(ptr, ordering)
|
loaded = bldr.atomic_load(ptr, ordering)
|
||||||
self.assertIn('load atomic', str(loaded))
|
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)
|
stored = bldr.atomic_store(loaded, ptr, ordering)
|
||||||
self.assertIn('store atomic', str(stored))
|
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)
|
fenced = bldr.fence(ordering)
|
||||||
self.assertEqual(['fence', ordering], str(fenced).strip().split(' '))
|
self.assertEqual(['fence', ordering], str(fenced).strip().split(' '))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue