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):


Reply via email to