Hello community, here is the log from the commit of package python-llvmlite for openSUSE:Factory checked in at 2018-04-24 15:33:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-llvmlite (Old) and /work/SRC/openSUSE:Factory/.python-llvmlite.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-llvmlite" Tue Apr 24 15:33:56 2018 rev:4 rq:600092 version:0.22.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-llvmlite/python-llvmlite.changes 2018-01-13 21:48:09.872628509 +0100 +++ /work/SRC/openSUSE:Factory/.python-llvmlite.new/python-llvmlite.changes 2018-04-24 15:33:58.744377715 +0200 @@ -1,0 +2,12 @@ +Fri Mar 23 15:28:15 UTC 2018 - [email protected] + +- Update to version 0.22.0 + * In this release, we have changed the locking strategy that + protects LLVM from race conditions. Before, the llvmlite user + (like Numba) was responsible for this locking. Now, llvmlite + imposes a global thread lock on all calls into the LLVM API. + This should be significantly less error prone. Future llvmlite + releases may manually exempt some functions from locking once + they are determined to be thread-safe. + +------------------------------------------------------------------- Old: ---- llvmlite-0.21.0.tar.gz New: ---- llvmlite-0.22.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-llvmlite.spec ++++++ --- /var/tmp/diff_new_pack.hdhTu2/_old 2018-04-24 15:33:59.552348483 +0200 +++ /var/tmp/diff_new_pack.hdhTu2/_new 2018-04-24 15:33:59.556348338 +0200 @@ -20,7 +20,7 @@ %bcond_without tests ExcludeArch: armv7l Name: python-llvmlite -Version: 0.21.0 +Version: 0.22.0 Release: 0 Summary: Lightweight wrapper around basic LLVM functionality License: BSD-2-Clause ++++++ llvmlite-0.21.0.tar.gz -> llvmlite-0.22.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/PKG-INFO new/llvmlite-0.22.0/PKG-INFO --- old/llvmlite-0.21.0/PKG-INFO 2017-12-08 17:20:53.000000000 +0100 +++ new/llvmlite-0.22.0/PKG-INFO 2018-02-19 21:15:34.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: llvmlite -Version: 0.21.0 +Version: 0.22.0 Summary: lightweight wrapper around basic LLVM functionality Home-page: http://llvmlite.pydata.org Author: Continuum Analytics, Inc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/ffi/executionengine.cpp new/llvmlite-0.22.0/ffi/executionengine.cpp --- old/llvmlite-0.21.0/ffi/executionengine.cpp 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/ffi/executionengine.cpp 2018-02-07 23:09:48.000000000 +0100 @@ -109,6 +109,18 @@ } API_EXPORT(void) +LLVMPY_RunStaticConstructors(LLVMExecutionEngineRef EE) +{ + return LLVMRunStaticConstructors(EE); +} + +API_EXPORT(void) +LLVMPY_RunStaticDestructors(LLVMExecutionEngineRef EE) +{ + return LLVMRunStaticDestructors(EE); +} + +API_EXPORT(void) LLVMPY_AddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *Addr) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/_version.py new/llvmlite-0.22.0/llvmlite/_version.py --- old/llvmlite-0.21.0/llvmlite/_version.py 2017-12-08 17:20:53.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/_version.py 2018-02-19 21:15:34.000000000 +0100 @@ -4,8 +4,8 @@ # unpacked source archive. Distribution tarballs contain a pre-generated copy # of this file. -version_version = '0.21.0' -version_full = 'b993afd8dcbcf07a60f145c6f25b0c9c96772c5d' +version_version = '0.22.0' +version_full = '46b4b5e288f3a175332ad68d8c3745c63fbb5701' def get_versions(default={}, verbose=False): return {'version': version_version, 'full': version_full} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/binding/executionengine.py new/llvmlite-0.22.0/llvmlite/binding/executionengine.py --- old/llvmlite-0.21.0/llvmlite/binding/executionengine.py 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/binding/executionengine.py 2018-02-07 23:09:48.000000000 +0100 @@ -93,6 +93,14 @@ and "usable" for execution. """ ffi.lib.LLVMPY_FinalizeObject(self) + + def run_static_constructors(self): + """Run static constructors which initialize module-level static objects.""" + ffi.lib.LLVMPY_RunStaticConstructors(self) + + def run_static_destructors(self): + """Run static destructors which perform module-level cleanup of static resources.""" + ffi.lib.LLVMPY_RunStaticDestructors(self) def remove_module(self, module): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/binding/ffi.py new/llvmlite-0.22.0/llvmlite/binding/ffi.py --- old/llvmlite-0.21.0/llvmlite/binding/ffi.py 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/binding/ffi.py 2018-02-07 16:56:44.000000000 +0100 @@ -1,5 +1,6 @@ import ctypes import os +import threading from .common import _decode_string, _is_shutting_down from ..utils import get_library_name @@ -30,6 +31,82 @@ LLVMSectionIteratorRef = _make_opaque_ref("LLVMSectionIterator") +class _lib_wrapper(object): + """Wrap libllvmlite with a lock such that only one thread may access it at + a time. + + This class duck-types a CDLL. + """ + __slots__ = ['_lib', '_fntab', '_lock'] + + def __init__(self, lib): + self._lib = lib + self._fntab = {} + # The reentrant lock is needed for callbacks that re-enter + # the Python interpreter. + self._lock = threading.RLock() + + def __getattr__(self, name): + try: + return self._fntab[name] + except KeyError: + # Lazily wraps new functions as they are requested + cfn = getattr(self._lib, name) + wrapped = _lib_fn_wrapper(self._lock, cfn) + self._fntab[name] = wrapped + return wrapped + + @property + def _name(self): + """The name of the library passed in the CDLL constructor. + + For duck-typing a ctypes.CDLL + """ + return self._lib._name + + @property + def _handle(self): + """The system handle used to access the library. + + For duck-typing a ctypes.CDLL + """ + return self._lib._handle + + +class _lib_fn_wrapper(object): + """Wraps and duck-types a ctypes.CFUNCTYPE to provide + automatic locking when the wrapped function is called. + + TODO: we can add methods to mark the function as threadsafe + and remove the locking-step on call when marked. + """ + __slots__ = ['_lock', '_cfn'] + + def __init__(self, lock, cfn): + self._lock = lock + self._cfn = cfn + + @property + def argtypes(self): + return self._cfn.argtypes + + @argtypes.setter + def argtypes(self, argtypes): + self._cfn.argtypes = argtypes + + @property + def restype(self): + return self._cfn.restype + + @restype.setter + def restype(self, restype): + self._cfn.restype = restype + + def __call__(self, *args, **kwargs): + with self._lock: + return self._cfn(*args, **kwargs) + + _lib_dir = os.path.dirname(__file__) if os.name == 'nt': @@ -50,6 +127,8 @@ raise e raise +lib = _lib_wrapper(lib) + class _DeadPointer(object): """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/ir/values.py new/llvmlite-0.22.0/llvmlite/ir/values.py --- old/llvmlite-0.21.0/llvmlite/ir/values.py 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/ir/values.py 2018-02-07 16:56:44.000000000 +0100 @@ -666,6 +666,48 @@ 'nocapture', 'nonnull', 'returned', 'signext', 'sret', 'zeroext']) + def __init__(self): + self._align = 0 + self._dereferenceable = 0 + self._dereferenceable_or_null = 0 + + @property + def align(self): + return self._align + + @align.setter + def align(self, val): + assert isinstance(val, six.integer_types) and val >= 0 + self._align = val + + @property + def dereferenceable(self): + return self._dereferenceable + + @dereferenceable.setter + def dereferenceable(self, val): + assert isinstance(val, six.integer_types) and val >= 0 + self._dereferenceable = val + + @property + def dereferenceable_or_null(self): + return self._dereferenceable_or_null + + @dereferenceable_or_null.setter + def dereferenceable_or_null(self, val): + assert isinstance(val, six.integer_types) and val >= 0 + self._dereferenceable_or_null = val + + def _to_list(self): + attrs = sorted(self) + if self.align: + attrs.append('align {0:d}'.format(self.align)) + if self.dereferenceable: + attrs.append('dereferenceable({0:d})'.format(self.dereferenceable)) + if self.dereferenceable_or_null: + attrs.append('dereferenceable_or_null({0:d})'.format(self.dereferenceable_or_null)) + return attrs + class _BaseArgument(NamedValue): def __init__(self, parent, typ, name=''): @@ -687,8 +729,9 @@ """ def __str__(self): - if self.attributes: - return "{0} {1} {2}".format(self.type, ' '.join(self.attributes), + attrs = self.attributes._to_list() + if attrs: + return "{0} {1} {2}".format(self.type, ' '.join(attrs), self.get_reference()) else: return "{0} {1}".format(self.type, self.get_reference()) @@ -700,8 +743,9 @@ """ def __str__(self): - if self.attributes: - return "{0} {1}".format(' '.join(self.attributes), self.type) + attrs = self.attributes._to_list() + if attrs: + return "{0} {1}".format(' '.join(attrs), self.type) else: return str(self.type) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/tests/test_binding.py new/llvmlite-0.22.0/llvmlite/tests/test_binding.py --- old/llvmlite-0.21.0/llvmlite/tests/test_binding.py 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/tests/test_binding.py 2018-02-07 23:09:48.000000000 +0100 @@ -123,6 +123,35 @@ }} """ +asm_global_ctors = r""" + ; ModuleID = "<string>" + target triple = "{triple}" + + @A = global i32 undef + + define void @ctor_A() + {{ + store i32 10, i32* @A + ret void + }} + + define void @dtor_A() + {{ + store i32 20, i32* @A + ret void + }} + + define i32 @foo() + {{ + %.2 = load i32, i32* @A + %.3 = add i32 %.2, 2 + ret i32 %.3 + }} + + @llvm.global_ctors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @ctor_A, i8* null}}] + @llvm.global_dtors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @dtor_A, i8* null}}] + """ + class BaseTest(TestCase): @@ -1093,6 +1122,32 @@ gv.initializer = ir.Constant(typ, [1]) +class TestGlobalConstructors(TestMCJit): + def test_global_ctors_dtors(self): + # test issue #303 + # (https://github.com/numba/llvmlite/issues/303) + mod = self.module(asm_global_ctors) + ee = self.jit(mod) + ee.finalize_object() + + ee.run_static_constructors() + + # global variable should have been initialized + ptr_addr = ee.get_global_value_address("A") + ptr_t = ctypes.POINTER(ctypes.c_int32) + ptr = ctypes.cast(ptr_addr, ptr_t) + self.assertEqual(ptr.contents.value, 10) + + foo_addr = ee.get_function_address("foo") + foo = ctypes.CFUNCTYPE(ctypes.c_int32)(foo_addr) + self.assertEqual(foo(), 12) + + ee.run_static_destructors() + + # destructor should have run + self.assertEqual(ptr.contents.value, 20) + + class TestGlobalVariables(BaseTest): def check_global_variable_linkage(self, linkage, has_undef=True): # This test default initializer on global variables with different diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/llvmlite-0.21.0/llvmlite/tests/test_ir.py new/llvmlite-0.22.0/llvmlite/tests/test_ir.py --- old/llvmlite-0.21.0/llvmlite/tests/test_ir.py 2017-12-08 17:02:59.000000000 +0100 +++ new/llvmlite-0.22.0/llvmlite/tests/test_ir.py 2018-02-07 16:56:44.000000000 +0100 @@ -133,11 +133,14 @@ # Now with parameter attributes func = self.function() func.args[0].add_attribute("zeroext") + func.args[1].attributes.dereferenceable = 5 + func.args[1].attributes.dereferenceable_or_null = 10 + func.args[3].attributes.align = 4 func.args[3].add_attribute("nonnull") func.return_value.add_attribute("noalias") asm = self.descr(func).strip() self.assertEqual(asm, - """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 %".2", double %".3", i32* nonnull %".4")""" + """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 dereferenceable(5) dereferenceable_or_null(10) %".2", double %".3", i32* nonnull align 4 %".4")""" ) def test_function_metadata(self):
