Hello community,

here is the log from the commit of package python-llvmlite for openSUSE:Factory 
checked in at 2019-03-18 10:43:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-llvmlite (Old)
 and      /work/SRC/openSUSE:Factory/.python-llvmlite.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-llvmlite"

Mon Mar 18 10:43:34 2019 rev:12 rq:685824 version:0.28.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-llvmlite/python-llvmlite.changes  
2019-02-24 17:17:21.136429690 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-llvmlite.new.28833/python-llvmlite.changes   
    2019-03-18 10:43:38.299127976 +0100
@@ -1,0 +2,17 @@
+Sat Mar 16 22:33:01 UTC 2019 - Arun Persaud <[email protected]>
+
+- update to version 0.28.0:
+  * PR #322: Adding Vector Type
+  * PR #389: Add symbols from static object files
+  * PR #417: Add support for atomic loads/stores
+  * PR #422: Normalize replace_* behaviour and add docs
+  * PR #426: Fix pickling of IR functions and add tests
+  * PR #444: Setup manylinux1 buildscripts and CI
+  * PR #446: Document need for -p1 argument to patch command
+  * PR #448: Fix “SyntaxWarning: invalid escape sequence d”
+  * PR #449: Consolidate the two vector type PRs
+  * PR #452: Some adjustments to pr426
+  * PR #454: Truncate long label names when adding label suffix.
+  * PR #458: Add changelog info about v0.27.1
+
+-------------------------------------------------------------------

Old:
----
  llvmlite-0.27.1.tar.gz

New:
----
  llvmlite-0.28.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-llvmlite.spec ++++++
--- /var/tmp/diff_new_pack.1doora/_old  2019-03-18 10:43:38.863127369 +0100
+++ /var/tmp/diff_new_pack.1doora/_new  2019-03-18 10:43:38.863127369 +0100
@@ -20,7 +20,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define         llvm_major 7
 Name:           python-llvmlite
-Version:        0.27.1
+Version:        0.28.0
 Release:        0
 Summary:        Lightweight wrapper around basic LLVM functionality
 License:        BSD-2-Clause

++++++ llvmlite-0.27.1.tar.gz -> llvmlite-0.28.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/CHANGE_LOG 
new/llvmlite-0.28.0/CHANGE_LOG
--- old/llvmlite-0.27.1/CHANGE_LOG      2019-02-01 21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/CHANGE_LOG      2019-03-12 19:53:52.000000000 +0100
@@ -1,3 +1,23 @@
+v0.28.0
+-------
+
+This release adds a number of community contributed features, including
+support for vector types, as well as atomic loads and stores.
+
+* PR #322: Adding Vector Type
+* PR #389: Add symbols from static object files
+* PR #417: Add support for atomic loads/stores
+* PR #422: Normalize replace_* behaviour and add docs
+* PR #426: Fix pickling of IR functions and add tests
+* PR #444: Setup manylinux1 buildscripts and CI
+* PR #446: Document need for -p1 argument to patch command
+* PR #448: Fix "SyntaxWarning: invalid escape sequence \d"
+* PR #449: Consolidate the two vector type PRs
+* PR #452: Some adjustments to pr426
+* PR #454: Truncate long label names when adding label suffix.
+* PR #458: Add changelog info about v0.27.1
+
+
 v0.27.1
 -------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/conda-recipes/llvmlite/.label 
new/llvmlite-0.28.0/conda-recipes/llvmlite/.label
--- old/llvmlite-0.27.1/conda-recipes/llvmlite/.label   1970-01-01 
01:00:00.000000000 +0100
+++ new/llvmlite-0.28.0/conda-recipes/llvmlite/.label   2019-03-12 
19:53:52.000000000 +0100
@@ -0,0 +1 @@
+main
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/docs/source/admin-guide/install.rst 
new/llvmlite-0.28.0/docs/source/admin-guide/install.rst
--- old/llvmlite-0.27.1/docs/source/admin-guide/install.rst     2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/admin-guide/install.rst     2019-03-12 
19:53:52.000000000 +0100
@@ -77,7 +77,7 @@
 
 #. Download or git checkout the `llvmlite source code 
<https://github.com/numba/llvmlite>`_.
 
-#. Decompress the LLVM tar file and apply the following patches from the 
``llvmlite/conda-recipes/`` directory:
+#. Decompress the LLVM tar file and apply the following patches from the 
``llvmlite/conda-recipes/`` directory.  You can apply each patch using the 
Linux "patch -p1 -i {patch-file}"  command:
 
     #. ``llvm-lto-static.patch``: Fix issue with LTO shared library on Windows
     #. ``D47188-svml-VF.patch``: Add support for vectorized math functions via 
Intel SVML
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/llvmlite-0.27.1/docs/source/user-guide/binding/execution-engine.rst 
new/llvmlite-0.28.0/docs/source/user-guide/binding/execution-engine.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/binding/execution-engine.rst     
2019-02-01 21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/binding/execution-engine.rst     
2019-03-12 19:53:52.000000000 +0100
@@ -72,6 +72,15 @@
         releasing the resources owned by the module without
         destroying the execution engine.
 
+    * .. method:: add_object_file(object_file)
+
+        Add the symbols from the specified object file to the execution
+        engine.
+
+        * *object_file* str or :class:`ObjectFileRef`: a path to the object 
file
+            or a object file instance. Object file instance is not usable 
after this
+            call.
+
    * .. method:: set_object_cache(notify_func=None, getbuffer_func=None)
 
         Set the object cache callbacks for this engine.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/llvmlite-0.27.1/docs/source/user-guide/binding/index.rst 
new/llvmlite-0.28.0/docs/source/user-guide/binding/index.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/binding/index.rst        
2019-02-01 21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/binding/index.rst        
2019-03-12 19:53:52.000000000 +0100
@@ -27,6 +27,7 @@
    value-references
    type-references
    execution-engine
+   object-file
    optimization-passes
    analysis-utilities
    examples
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/llvmlite-0.27.1/docs/source/user-guide/binding/object-file.rst 
new/llvmlite-0.28.0/docs/source/user-guide/binding/object-file.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/binding/object-file.rst  
1970-01-01 01:00:00.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/binding/object-file.rst  
2019-03-12 19:53:52.000000000 +0100
@@ -0,0 +1,72 @@
+===========
+Object file
+===========
+
+.. currentmodule:: llvmlite.binding
+
+The object file is an abstraction of LLVM representation of
+the static object code files. This class provides methods to examine
+the contents of the object files. It also can be passed as parameter to
+:meth:`ExecutionEngine.add_object_file` to make the symbols available
+to the JIT.
+
+The ObjectFileRef class
+------------------------
+
+.. class:: ObjectFileRef
+
+    A wrapper around LLVM object file. The following methods and properties
+    are available:
+
+    * .. classmethod:: from_data(data):
+
+        Create an instance of ObjectFileRef from the provided binary data.
+
+    * .. classmethod:: from_path(path):
+
+        Create an instance of ObjectFileRef from the supplied filesystem
+        path. Raises IOError if the path does not exist.
+
+    * .. method:: sections:
+
+        Return an iterator to the sections objects consisting of the
+        instance of :class:`SectionIteratorRef`
+
+The SectionIteratorRef class
+----------------------------
+
+.. class:: SectionIteratorRef
+    A wrapper around the section class which provides information like
+    section name, type and size, etc.
+
+    * .. method:: name():
+
+        Get section name.
+
+    * .. method:: is_text():
+
+        Returns true when section is of type text.
+
+    * .. method:: size():
+
+        Get section size.
+
+    * .. method:: address():
+
+        Get section address.
+
+    * .. method:: data():
+
+        Get section contents.
+
+    * .. method:: is_end(object_file):
+
+        Return true if the section iterator is the last element of the
+        object_file.
+
+        * object_file: an instance of :class:`ObjectFileRef`
+
+    * .. method:: next():
+
+        Get the next section instance.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/llvmlite-0.27.1/docs/source/user-guide/ir/ir-builder.rst 
new/llvmlite-0.28.0/docs/source/user-guide/ir/ir-builder.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/ir/ir-builder.rst        
2019-02-01 21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/ir/ir-builder.rst        
2019-03-12 19:53:52.000000000 +0100
@@ -419,6 +419,27 @@
      can be of the same types as in :meth:`extract_value`.
 
 
+Vector operations
+-----------------
+
+* .. method:: IRBuilder.extract_element(vector, idx, name='')
+
+     Returns the *value* at position *idx*.
+
+* .. method:: IRBuilder.insert_element(vector, value, idx, name='')
+
+     Returns vector with ``vector[idx]`` replaced by ``value``.
+     The result is undefined if the idx is larger or equal the vector length.
+
+* .. method:: IRBuilder.shuffle_vector(vector1, vector2, mask, name='')
+
+     Constructs a permutation of elements from *vector1* and *vector2*.
+     Returns a new vector in the same length of *mask*.
+
+     * *vector1* and *vector2* must have the same element type.
+     * *mask* must be a constant vector of integer types.
+
+
 Memory
 -------
 
@@ -440,6 +461,18 @@
      be a Python integer specifying the guaranteed pointer
      alignment.
 
+* .. method:: IRBuilder.load_atomic(ptr, ordering, align, name='')
+
+     Load value from pointer *ptr* as an atomic operation with the given
+     *ordering*. *align* must be a Python integer specifying the guaranteed
+     pointer alignment.
+
+* .. method:: IRBuilder.store_atomic(value, ptr, ordering, align)
+
+     Store *value* to pointer *ptr* as an atomic operation with the given
+     *ordering*. *align* must be a Python integer specifying the guaranteed
+     pointer alignment.
+
 * .. method:: IRBuilder.gep(ptr, indices, inbounds=False, name='')
 
      The :ref:`getelementptr` instruction. Given a pointer *ptr*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/docs/source/user-guide/ir/types.rst 
new/llvmlite-0.28.0/docs/source/user-guide/ir/types.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/ir/types.rst     2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/ir/types.rst     2019-03-12 
19:53:52.000000000 +0100
@@ -124,6 +124,14 @@
    * *count* is a Python integer representing the number of
      elements.
 
+.. class:: VectorType(element, count)
+
+   The class for vector types.
+
+   * *element* is the type of every element.
+   * *count* is a Python integer representing the number of
+     elements.
+
 .. class:: LiteralStructType(elements, [packed=False])
 
    The class for literal struct types.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/docs/source/user-guide/ir/values.rst 
new/llvmlite-0.28.0/docs/source/user-guide/ir/values.rst
--- old/llvmlite-0.27.1/docs/source/user-guide/ir/values.rst    2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/docs/source/user-guide/ir/values.rst    2019-03-12 
19:53:52.000000000 +0100
@@ -346,6 +346,10 @@
         Add an instruction-specific metadata *name* pointing to the
         given metadata *node*---an :class:`MDValue`.
 
+   * .. method:: replace_usage(old, new)
+
+        Replace the operand *old* with the other instruction *new*.
+
    * .. attribute:: function
 
         The function that contains this instruction.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/ffi/build.py 
new/llvmlite-0.28.0/ffi/build.py
--- old/llvmlite-0.27.1/ffi/build.py    2019-02-01 21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/ffi/build.py    2019-03-12 19:53:52.000000000 +0100
@@ -59,7 +59,7 @@
         generators.append(os.environ.get("CMAKE_GENERATOR"))
 
     # Drop generators that are too old
-    vspat = re.compile('Visual Studio (\d+)')
+    vspat = re.compile(r'Visual Studio (\d+)')
     def drop_old_vs(g):
         m = vspat.match(g)
         if m is None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/ffi/executionengine.cpp 
new/llvmlite-0.28.0/ffi/executionengine.cpp
--- old/llvmlite-0.27.1/ffi/executionengine.cpp 2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/ffi/executionengine.cpp 2019-03-12 19:53:52.000000000 
+0100
@@ -1,15 +1,42 @@
 #include "core.h"
 
 #include "llvm-c/ExecutionEngine.h"
+#include "llvm-c/Object.h"
+
 
 #include "llvm/IR/Module.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Binary.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/JITEventListener.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/Support/Memory.h"
 
 #include <cstdio>
+#include <memory>
+
+namespace llvm {
 
+    // wrap/unwrap for LLVMTargetMachineRef.
+    // Ripped from lib/Target/TargetMachineC.cpp.
+
+    inline TargetMachine *unwrap(LLVMTargetMachineRef P) {
+        return reinterpret_cast<TargetMachine*>(P);
+    }
+    inline LLVMTargetMachineRef wrap(const TargetMachine *P) {
+    return
+        reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
+    }
+
+    // unwrap for LLVMObjectFileRef
+    // from Object/Object.cpp
+    namespace object {
+
+        inline OwningBinary<ObjectFile> *unwrap(LLVMObjectFileRef OF) {
+            return reinterpret_cast<OwningBinary<ObjectFile> *>(OF);
+        }
+    } // object
+} // llvm
 
 extern "C" {
 
@@ -45,21 +72,6 @@
     llvm::unwrap(EE)->finalizeObject();
 }
 
-
-// wrap/unwrap for LLVMTargetMachineRef.
-// Ripped from lib/Target/TargetMachineC.cpp.
-
-namespace llvm {
-    inline TargetMachine *unwrap(LLVMTargetMachineRef P) {
-      return reinterpret_cast<TargetMachine*>(P);
-    }
-    inline LLVMTargetMachineRef wrap(const TargetMachine *P) {
-      return
-        reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine*>(P));
-    }
-}
-
-
 static
 LLVMExecutionEngineRef
 create_execution_engine(LLVMModuleRef M,
@@ -173,6 +185,17 @@
     return result;
 }
 
+API_EXPORT(void)
+LLVMPY_MCJITAddObjectFile(LLVMExecutionEngineRef EE, LLVMObjectFileRef ObjF) {
+    using namespace llvm;
+    using namespace llvm::object;
+    auto engine = unwrap(EE);
+    auto object_file = unwrap(ObjF);
+    auto binary_tuple = object_file->takeBinary();
+
+    engine->addObjectFile({std::move(binary_tuple.first), 
std::move(binary_tuple.second)});
+}
+
 
 //
 // Object cache
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/ffi/object_file.cpp 
new/llvmlite-0.28.0/ffi/object_file.cpp
--- old/llvmlite-0.27.1/ffi/object_file.cpp     2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/ffi/object_file.cpp     2019-03-12 19:53:52.000000000 
+0100
@@ -18,7 +18,6 @@
       return reinterpret_cast<LLVMSectionIteratorRef>
         (const_cast<object::section_iterator*>(SI));
     }
-
 } // llvm
 
 extern "C" {
@@ -26,7 +25,7 @@
 API_EXPORT(LLVMObjectFileRef)
 LLVMPY_CreateObjectFile(const char* buf, const size_t n)
 {
-  return LLVMCreateObjectFile(LLVMCreateMemoryBufferWithMemoryRange(buf, n, 
"", false));
+  return LLVMCreateObjectFile(LLVMCreateMemoryBufferWithMemoryRangeCopy(buf, 
n, ""));
 }
 
 API_EXPORT(void)
@@ -65,6 +64,12 @@
   return LLVMGetSectionName(SI);
 }
 
+API_EXPORT(uint64_t)
+LLVMPY_GetSectionAddress(LLVMSectionIteratorRef SI)
+{
+    return LLVMGetSectionAddress(SI);
+}
+
 API_EXPORT(const char*)
 LLVMPY_GetSectionContents(LLVMSectionIteratorRef SI)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/_version.py 
new/llvmlite-0.28.0/llvmlite/_version.py
--- old/llvmlite-0.27.1/llvmlite/_version.py    2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/llvmlite/_version.py    2019-03-12 19:53:52.000000000 
+0100
@@ -9,8 +9,8 @@
 # versioneer-0.12 (https://github.com/warner/python-versioneer)
 
 # these strings will be replaced by git during git-archive
-git_refnames = " (tag: v0.27.1, release0.27)"
-git_full = "f008359c1f9ee5e8a6a98f2095ea460f09f57edb"
+git_refnames = " (tag: v0.28.0, release0.28)"
+git_full = "685b7b6941617f616f3f0b609e381af52da26782"
 
 # these strings are filled in when 'setup.py versioneer' creates _version.py
 tag_prefix = "v"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/binding/executionengine.py 
new/llvmlite-0.28.0/llvmlite/binding/executionengine.py
--- old/llvmlite-0.27.1/llvmlite/binding/executionengine.py     2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/llvmlite/binding/executionengine.py     2019-03-12 
19:53:52.000000000 +0100
@@ -93,11 +93,11 @@
         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)
@@ -143,6 +143,17 @@
                 return module
         return None
 
+    def add_object_file(self, obj_file):
+        """
+        Add object file to the jit. object_file can be instance of
+        :class:ObjectFile or a string representing file system path
+        """
+        if isinstance(obj_file, str):
+            obj_file = object_file.ObjectFileRef.from_path(obj_file)
+
+        ffi.lib.LLVMPY_MCJITAddObjectFile(self, obj_file)
+
+
     def set_object_cache(self, notify_func=None, getbuffer_func=None):
         """
         Set the object cache "notifyObjectCompiled" and "getBuffer"
@@ -269,6 +280,10 @@
 ]
 ffi.lib.LLVMPY_GetGlobalValueAddress.restype = c_uint64
 
+ffi.lib.LLVMPY_MCJITAddObjectFile.argtypes = [
+    ffi.LLVMExecutionEngineRef,
+    ffi.LLVMObjectFileRef
+]
 
 class _ObjectCacheData(Structure):
     _fields_ = [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/binding/object_file.py 
new/llvmlite-0.28.0/llvmlite/binding/object_file.py
--- old/llvmlite-0.27.1/llvmlite/binding/object_file.py 2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/llvmlite/binding/object_file.py 2019-03-12 
19:53:52.000000000 +0100
@@ -8,6 +8,8 @@
         return ffi.lib.LLVMPY_IsSectionText(self)
     def size(self):
         return ffi.lib.LLVMPY_GetSectionSize(self)
+    def address(self):
+        return ffi.lib.LLVMPY_GetSectionAddress(self)
     def data(self):
         return string_at(ffi.lib.LLVMPY_GetSectionContents(self), self.size())
     def is_end(self, object_file):
@@ -22,6 +24,12 @@
     def from_data(cls, data):
         return cls(ffi.lib.LLVMPY_CreateObjectFile(data, len(data)))
 
+    @classmethod
+    def from_path(cls, path):
+        with open(path, 'rb') as f:
+            data = f.read()
+        return cls(ffi.lib.LLVMPY_CreateObjectFile(data, len(data)))
+
     def sections(self):
         it = SectionIteratorRef(ffi.lib.LLVMPY_GetSections(self))
         while not it.is_end(self):
@@ -52,6 +60,9 @@
 ffi.lib.LLVMPY_GetSectionSize.argtypes = [ffi.LLVMSectionIteratorRef]
 ffi.lib.LLVMPY_GetSectionSize.restype  = c_uint64
 
+ffi.lib.LLVMPY_GetSectionAddress.argtypes = [ffi.LLVMSectionIteratorRef]
+ffi.lib.LLVMPY_GetSectionAddress.restype  = c_uint64
+
 ffi.lib.LLVMPY_GetSectionContents.argtypes = [ffi.LLVMSectionIteratorRef]
 ffi.lib.LLVMPY_GetSectionContents.restype  = c_char_p
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/ir/_utils.py 
new/llvmlite-0.28.0/llvmlite/ir/_utils.py
--- old/llvmlite-0.27.1/llvmlite/ir/_utils.py   2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/llvmlite/ir/_utils.py   2019-03-12 19:53:52.000000000 
+0100
@@ -37,6 +37,12 @@
 
 class _StrCaching(object):
 
+    def _clear_string_cache(self):
+        try:
+            del self.__cached_str
+        except AttributeError:
+            pass
+
     def __str__(self):
         try:
             return self.__cached_str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/ir/builder.py 
new/llvmlite-0.28.0/llvmlite/ir/builder.py
--- old/llvmlite-0.27.1/llvmlite/ir/builder.py  2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/llvmlite/ir/builder.py  2019-03-12 19:53:52.000000000 
+0100
@@ -134,6 +134,22 @@
     return wrap
 
 
+def _label_suffix(label, suffix):
+    """Returns (label + suffix) or a truncated version if it's too long.
+    Parameters
+    ----------
+    label : str
+        Label name
+    suffix : str
+        Label suffix
+    """
+    if len(label) > 50:
+        nhead = 25
+        return ''.join([label[:nhead], '..', suffix])
+    else:
+        return label + suffix
+
+
 class IRBuilder(object):
     def __init__(self, block=None):
         self._block = block
@@ -245,8 +261,8 @@
         for LLVM's optimizers to account for that.
         """
         bb = self.basic_block
-        bbif = self.append_basic_block(name=bb.name + '.if')
-        bbend = self.append_basic_block(name=bb.name + '.endif')
+        bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
+        bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
         br = self.cbranch(pred, bbif, bbend)
         if likely is not None:
             br.set_weights([99, 1] if likely else [1, 99])
@@ -273,9 +289,9 @@
                     # emit instructions for when the predicate is false
         """
         bb = self.basic_block
-        bbif = self.append_basic_block(name=bb.name + '.if')
-        bbelse = self.append_basic_block(name=bb.name + '.else')
-        bbend = self.append_basic_block(name=bb.name + '.endif')
+        bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
+        bbelse = self.append_basic_block(name=_label_suffix(bb.name, '.else'))
+        bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
         br = self.cbranch(pred, bbif, bbelse)
         if likely is not None:
             br.set_weights([99, 1] if likely else [1, 99])
@@ -480,7 +496,11 @@
         Bitwise integer complement:
             name = ~value
         """
-        return self.xor(value, values.Constant(value.type, -1), name=name)
+        if isinstance(value.type, types.VectorType):
+            rhs = values.Constant(value.type, (-1,) * value.type.count)
+        else:
+            rhs = values.Constant(value.type, -1)
+        return self.xor(value, rhs, name=name)
 
     def neg(self, value, name=''):
         """
@@ -707,6 +727,33 @@
         self._insert(st)
         return st
 
+    def load_atomic(self, ptr, ordering, align, name=''):
+        """
+        Load value from pointer, with optional guaranteed alignment:
+            name = *ptr
+        """
+        if not isinstance(ptr.type, types.PointerType):
+            raise TypeError("cannot load from value of type %s (%r): not a 
pointer"
+                            % (ptr.type, str(ptr)))
+        ld = instructions.LoadAtomicInstr(self.block, ptr, ordering, align, 
name)
+        self._insert(ld)
+        return ld
+
+    def store_atomic(self, value, ptr, ordering, align):
+        """
+        Store value to pointer, with optional guaranteed alignment:
+            *ptr = name
+        """
+        if not isinstance(ptr.type, types.PointerType):
+            raise TypeError("cannot store to value of type %s (%r): not a 
pointer"
+                            % (ptr.type, str(ptr)))
+        if ptr.type.pointee != value.type:
+            raise TypeError("cannot store %s to %s: mismatching types"
+                            % (value.type, ptr.type))
+        st = instructions.StoreAtomicInstr(self.block, value, ptr, ordering, 
align)
+        self._insert(st)
+        return st
+
 
     #
     # Terminators APIs
@@ -820,6 +867,39 @@
         self._insert(instr)
         return instr
 
+    # Vector Operations APIs
+
+    def extract_element(self, vector, idx, name=''):
+        """
+        Returns the value at position idx.
+        """
+        instr = instructions.ExtractElement(self.block, vector, idx, name=name)
+        self._insert(instr)
+        return instr
+
+    def insert_element(self, vector, value, idx, name=''):
+        """
+        Returns vector with vector[idx] replaced by value.
+        The result is undefined if the idx is larger or equal the vector 
length.
+        """
+        instr = instructions.InsertElement(self.block, vector, value, idx,
+                                           name=name)
+        self._insert(instr)
+        return instr
+
+    def shuffle_vector(self, vector1, vector2, mask, name=''):
+        """
+        Constructs a permutation of elements from *vector1* and *vector2*.
+        Returns a new vector in the same length of *mask*.
+
+        * *vector1* and *vector2* must have the same element type.
+        * *mask* must be a constant vector of integer types.
+        """
+        instr = instructions.ShuffleVector(self.block, vector1, vector2, mask,
+                                           name=name)
+        self._insert(instr)
+        return instr
+
     # Aggregate APIs
 
     def extract_value(self, agg, idx, name=''):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/ir/instructions.py 
new/llvmlite-0.28.0/llvmlite/ir/instructions.py
--- old/llvmlite-0.27.1/llvmlite/ir/instructions.py     2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/llvmlite/ir/instructions.py     2019-03-12 
19:53:52.000000000 +0100
@@ -6,7 +6,7 @@
 
 from . import types
 from .values import (Block, Function, Value, NamedValue, Constant,
-                     MetaDataArgument, MetaDataString, AttributeSet)
+                     MetaDataArgument, MetaDataString, AttributeSet, Undefined)
 from ._utils import _HasMetadata
 
 
@@ -44,6 +44,7 @@
             for op in self.operands:
                 ops.append(new if op is old else op)
             self.operands = tuple(ops)
+            self._clear_string_cache()
 
     def __repr__(self):
         return "<ir.%s %r of type '%s', opname %r, operands %r>" % (
@@ -310,7 +311,11 @@
             if flag not in self.VALID_FLAG:
                 raise ValueError("invalid flag %r for %s" % (flag, 
self.OPNAME))
         opname = self.OPNAME
-        super(CompareInstr, self).__init__(parent, types.IntType(1),
+        if isinstance(lhs.type, types.VectorType):
+            typ = types.VectorType(types.IntType(1), lhs.type.count)
+        else:
+            typ = types.IntType(1)
+        super(CompareInstr, self).__init__(parent, typ,
                                            opname, [lhs, rhs], flags=flags,
                                            name=name)
         self.op = op
@@ -424,6 +429,45 @@
             ))
 
 
+class LoadAtomicInstr(Instruction):
+    def __init__(self, parent, ptr, ordering, align, name=''):
+        super(LoadAtomicInstr, self).__init__(parent, ptr.type.pointee, "load 
atomic",
+                                              [ptr], name=name)
+        self.ordering = ordering
+        self.align = align
+
+    def descr(self, buf):
+        [val] = self.operands
+        buf.append("load atomic {0}, {1} {2} {3}, align {4}{5}\n".format(
+            val.type.pointee,
+            val.type,
+            val.get_reference(),
+            self.ordering,
+            self.align,
+            self._stringify_metadata(leading_comma=True),
+            ))
+
+
+class StoreAtomicInstr(Instruction):
+    def __init__(self, parent, val, ptr, ordering, align):
+        super(StoreAtomicInstr, self).__init__(parent, types.VoidType(), 
"store atomic",
+                                               [val, ptr])
+        self.ordering = ordering
+        self.align = align
+
+    def descr(self, buf):
+        val, ptr = self.operands
+        buf.append("store atomic {0} {1}, {2} {3} {4}, align {5}{6}\n".format(
+            val.type,
+            val.get_reference(),
+            ptr.type,
+            ptr.get_reference(),
+            self.ordering,
+            self.align,
+            self._stringify_metadata(leading_comma=True),
+            ))
+
+
 class AllocaInstr(Instruction):
     def __init__(self, parent, typ, count, name):
         operands = [count] if count else ()
@@ -502,6 +546,70 @@
         self.incomings = [((new if val is old else val), blk)
                           for (val, blk) in self.incomings]
 
+class ExtractElement(Instruction):
+    def __init__(self, parent, vector, index, name=''):
+        if not isinstance(vector.type, types.VectorType):
+            raise TypeError("vector needs to be of VectorType.")
+        if not isinstance(index.type, types.IntType):
+            raise TypeError("index needs to be of IntType.")
+        typ = vector.type.element
+        super(ExtractElement, self).__init__(parent, typ, "extractelement",
+                                           [vector, index], name=name)
+
+    def descr(self, buf):
+        operands = ", ".join("{0} {1}".format(
+                   op.type, op.get_reference()) for op in self.operands)
+        buf.append("{opname} {operands}\n".format(
+                   opname = self.opname, operands = operands))
+
+class InsertElement(Instruction):
+    def __init__(self, parent, vector, value, index, name=''):
+        if not isinstance(vector.type, types.VectorType):
+            raise TypeError("vector needs to be of VectorType.")
+        if not value.type == vector.type.element:
+            raise TypeError("value needs to be of type % not %."
+                            % (vector.type.element, value.type))
+        if not isinstance(index.type, types.IntType):
+            raise TypeError("index needs to be of IntType.")
+        typ = vector.type
+        super(InsertElement, self).__init__(parent, typ, "insertelement",
+                                           [vector, value, index], name=name)
+
+    def descr(self, buf):
+        operands = ", ".join("{0} {1}".format(
+                   op.type, op.get_reference()) for op in self.operands)
+        buf.append("{opname} {operands}\n".format(
+                   opname = self.opname, operands = operands))
+
+class ShuffleVector(Instruction):
+    def __init__(self, parent, vector1, vector2, mask, name=''):
+        if not isinstance(vector1.type, types.VectorType):
+            raise TypeError("vector1 needs to be of VectorType.")
+        if vector2 != Undefined:
+            if vector2.type != vector1.type:
+                raise TypeError("vector2 needs to be " +
+                                "Undefined or of the same type as vector1.")
+        if (not isinstance(mask, Constant) or
+            not isinstance(mask.type, types.VectorType) or
+            mask.type.element != types.IntType(32)):
+            raise TypeError("mask needs to be a constant i32 vector.")
+        typ = types.VectorType(vector1.type.element, mask.type.count)
+        index_range = range(vector1.type.count
+                            if vector2 == Undefined
+                            else 2 * vector1.type.count)
+        if not all(ii.constant in index_range for ii in mask.constant):
+            raise IndexError(
+                "mask values need to be in {0}".format(index_range),
+            )
+        super(ShuffleVector, self).__init__(parent, typ, "shufflevector",
+                                           [vector1, vector2, mask], name=name)
+
+    def descr(self, buf):
+        buf.append("shufflevector {0} {1}\n".format(
+                   ", ".join("{0} {1}".format(op.type, op.get_reference())
+                             for op in self.operands),
+                   self._stringify_metadata(leading_comma=True),
+                   ))
 
 class ExtractValue(Instruction):
     def __init__(self, parent, agg, indices, name=''):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/ir/types.py 
new/llvmlite-0.28.0/llvmlite/ir/types.py
--- old/llvmlite-0.27.1/llvmlite/ir/types.py    2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/llvmlite/ir/types.py    2019-03-12 19:53:52.000000000 
+0100
@@ -334,6 +334,57 @@
         else:
             raise IndexError(item)
 
+class VectorType(Type):
+    """
+    The type for vectors of primitive data items (e.g. "<f32 x 4>").
+    """
+
+    def __init__(self, element, count):
+        self.element = element
+        self.count = count
+
+    @property
+    def elements(self):
+        return _Repeat(self.element, self.count)
+
+    def __len__(self):
+        return self.count
+
+    def _to_string(self):
+        return "<%d x %s>" % (self.count, self.element)
+
+    def __eq__(self, other):
+        if isinstance(other, VectorType):
+            return self.element == other.element and self.count == other.count
+
+    def __hash__(self):
+        # TODO: why does this not take self.element/self.count into account?
+        return hash(VectorType)
+
+    def __copy__(self):
+        return self
+
+    def format_constant(self, value):
+        itemstring = ", " .join(["{0} {1}".format(x.type, x.get_reference())
+                                 for x in value])
+        return "<{0}>".format(itemstring)
+
+    def wrap_constant_value(self, values):
+        from . import Value, Constant
+        if not isinstance(values, (list, tuple)):
+            if isinstance(values, Constant):
+                if values.type != self.element:
+                    raise TypeError("expected % for %"
+                                    % (self.element, values.type))
+                return (values, ) * self.count
+            return (Constant(self.element, values), ) * self.count
+        if len(values) != len(self):
+            raise ValueError("wrong constant size for %s: got %d elements"
+                             % (self, len(values)))
+        return [Constant(ty, val) if not isinstance(val, Value) else val
+                for ty, val in zip(self.elements, values)]
+
+
 
 class Aggregate(Type):
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/ir/values.py 
new/llvmlite-0.28.0/llvmlite/ir/values.py
--- old/llvmlite-0.27.1/llvmlite/ir/values.py   2019-02-01 21:16:16.000000000 
+0100
+++ new/llvmlite-0.28.0/llvmlite/ir/values.py   2019-03-12 19:53:52.000000000 
+0100
@@ -103,6 +103,12 @@
     """
     'undef': a value for undefined values.
     """
+    def __new__(cls):
+        try:
+            return Undefined
+        except NameError:
+            return object.__new__(_Undefined)
+
 
 Undefined = _Undefined()
 
@@ -116,9 +122,7 @@
         assert isinstance(typ, types.Type)
         assert not isinstance(typ, types.VoidType)
         self.type = typ
-        if isinstance(constant, (list, tuple)):
-            # Recursively wrap aggregate constants
-            constant = typ.wrap_constant_value(constant)
+        constant = typ.wrap_constant_value(constant)
         self.constant = constant
 
     def _to_string(self):
@@ -546,9 +550,10 @@
         'sanitize_memory', 'sanitize_thread', 'ssp',
         'sspreg', 'sspstrong', 'uwtable'])
 
-    def __init__(self):
+    def __init__(self, args=()):
         self._alignstack = 0
         self._personality = None
+        super(FunctionAttributes, self).__init__(args)
 
     @property
     def alignstack(self):
@@ -672,10 +677,11 @@
                         'nocapture', 'nonnull', 'returned', 'signext',
                         'sret', 'zeroext'])
 
-    def __init__(self):
+    def __init__(self, args=()):
         self._align = 0
         self._dereferenceable = 0
         self._dereferenceable_or_null = 0
+        super(ArgumentAttributes, self).__init__(args)
 
     @property
     def align(self):
@@ -800,6 +806,7 @@
                 instr.replace_usage(old, new)
 
 
+
 class BlockAddress(Value):
     """
     The address of a basic block.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/tests/test_binding.py 
new/llvmlite-0.28.0/llvmlite/tests/test_binding.py
--- old/llvmlite-0.27.1/llvmlite/tests/test_binding.py  2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/llvmlite/tests/test_binding.py  2019-03-12 
19:53:52.000000000 +0100
@@ -12,6 +12,7 @@
 import sys
 import unittest
 from contextlib import contextmanager
+from tempfile import mkstemp
 
 from llvmlite import six, ir
 from llvmlite import binding as llvm
@@ -1313,6 +1314,20 @@
 
 
 class TestObjectFile(BaseTest):
+
+    mod_asm = """
+        ;ModuleID = <string>
+        target triple = "{triple}"
+
+        declare i32 @sum(i32 %.1, i32 %.2)
+
+        define i32 @sum_twice(i32 %.1, i32 %.2) {{
+            %.3 = call i32 @sum(i32 %.1, i32 %.2)
+            %.4 = call i32 @sum(i32 %.3, i32 %.3)
+            ret i32 %.4
+        }}
+    """
+
     def test_object_file(self):
         target_machine = self.target_machine()
         mod = self.module()
@@ -1320,15 +1335,61 @@
         obj = llvm.ObjectFileRef.from_data(obj_bin)
         # Check that we have a text section, and that she has a name and data
         has_text = False
+        last_address = -1
         for s in obj.sections():
             if s.is_text():
                 has_text = True
                 self.assertIsNotNone(s.name())
                 self.assertTrue(s.size() > 0)
                 self.assertTrue(len(s.data()) > 0)
+                self.assertIsNotNone(s.address())
+                self.assertTrue(last_address < s.address())
+                last_address = s.address()
                 break
         self.assertTrue(has_text)
 
+    def test_add_object_file(self):
+        target_machine = self.target_machine()
+        mod = self.module()
+        obj_bin = target_machine.emit_object(mod)
+        obj = llvm.ObjectFileRef.from_data(obj_bin)
+
+        jit = llvm.create_mcjit_compiler(self.module(self.mod_asm),
+            target_machine)
+
+        jit.add_object_file(obj)
+
+        sum_twice = CFUNCTYPE(c_int, c_int, c_int)(
+            jit.get_function_address("sum_twice"))
+
+        self.assertEqual(sum_twice(2, 3), 10)
+
+    def test_add_object_file_from_filesystem(self):
+        target_machine = self.target_machine()
+        mod = self.module()
+        obj_bin = target_machine.emit_object(mod)
+        temp_desc, temp_path = mkstemp()
+
+        try:
+            try:
+                f = os.fdopen(temp_desc, "wb")
+                f.write(obj_bin)
+                f.flush()
+            finally:
+                f.close()
+
+            jit = llvm.create_mcjit_compiler(self.module(self.mod_asm),
+                target_machine)
+
+            jit.add_object_file(temp_path)
+        finally:
+            os.unlink(temp_path)
+
+        sum_twice = CFUNCTYPE(c_int, c_int, c_int)(
+            jit.get_function_address("sum_twice"))
+
+        self.assertEqual(sum_twice(2, 3), 10)
+
 
 if __name__ == "__main__":
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/llvmlite-0.27.1/llvmlite/tests/test_ir.py 
new/llvmlite-0.28.0/llvmlite/tests/test_ir.py
--- old/llvmlite-0.27.1/llvmlite/tests/test_ir.py       2019-02-01 
21:16:16.000000000 +0100
+++ new/llvmlite-0.28.0/llvmlite/tests/test_ir.py       2019-03-12 
19:53:52.000000000 +0100
@@ -56,6 +56,15 @@
     def assert_valid_ir(self, mod):
         llvm.parse_assembly(str(mod))
 
+    def assert_pickle_correctly(self, irobject):
+        """Assert that the IR object pickles and unpickles correctly.
+        The IR string is equal and that their type is equal
+        """
+        newobject = pickle.loads(pickle.dumps(irobject, protocol=-1))
+        self.assertIs(irobject.__class__, newobject.__class__)
+        self.assertEqual(str(irobject), str(newobject))
+        return newobject
+
     def module(self):
         return ir.Module()
 
@@ -129,6 +138,8 @@
         self.assertEqual(asm,
             ("declare %s alwaysinline optsize alignstack(16) "
              "personality i8 (...)* @\"__gxx_personality_v0\"") % self.proto)
+        # Check pickling
+        self.assert_pickle_correctly(func)
 
     def test_function_attributes(self):
         # Now with parameter attributes
@@ -143,6 +154,8 @@
         self.assertEqual(asm,
             """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 
dereferenceable(5) dereferenceable_or_null(10) %".2", double %".3", i32* 
nonnull align 4 %".4")"""
             )
+        # Check pickling
+        self.assert_pickle_correctly(func)
 
     def test_function_metadata(self):
         # Now with function metadata
@@ -153,6 +166,8 @@
         self.assertEqual(asm,
             """declare i32 @"my_func"(i32 %".1", i32 %".2", double %".3", i32* 
%".4") !dbg !0"""
             )
+        # Check pickling
+        self.assert_pickle_correctly(func)
 
     def test_define(self):
         # A simple definition
@@ -193,6 +208,10 @@
         powi2 = module.declare_intrinsic('llvm.powi', [dbl])
         self.assertIs(powi, powi2)
 
+    def test_pickling(self):
+        fn = self.function()
+        self.assert_pickle_correctly(fn)
+
 
 class TestIR(TestBase):
 
@@ -466,6 +485,10 @@
             @"g" = internal global i32 123, align 16
             """)
 
+    def test_pickle(self):
+        mod = self.module()
+        self.assert_pickle_correctly(mod)
+
 
 class TestBlock(TestBase):
 
@@ -489,6 +512,12 @@
         d = builder.sub(a, b, 'd')
         builder.mul(d, b, 'e')
         f = ir.Instruction(block, a.type, 'sdiv', (c, b), 'f')
+        self.check_block(block, """\
+            my_block:
+                %"c" = add i32 %".1", %".2"
+                %"d" = sub i32 %".1", %".2"
+                %"e" = mul i32 %"d", %".2"
+            """)
         block.replace(d, f)
         self.check_block(block, """\
             my_block:
@@ -637,6 +666,24 @@
                 %"d" = xor i32 %".2", -1
             """)
 
+    def test_replace_operand(self):
+        block = self.block(name='my_block')
+        builder = ir.IRBuilder(block)
+        a, b = builder.function.args[:2]
+        undef1 = ir.Constant(ir.IntType(32), ir.Undefined)
+        undef2 = ir.Constant(ir.IntType(32), ir.Undefined)
+        c = builder.add(undef1, undef2, 'c')
+        self.check_block(block, """\
+            my_block:
+                %"c" = add i32 undef, undef
+            """)
+        c.replace_usage(undef1, a)
+        c.replace_usage(undef2, b)
+        self.check_block(block, """\
+            my_block:
+                %"c" = add i32 %".1", %".2"
+            """)
+
     def test_integer_comparisons(self):
         block = self.block(name='my_block')
         builder = ir.IRBuilder(block)
@@ -768,6 +815,11 @@
         self.assertEqual(h.type, ir.VoidType())
         i = builder.load(c, 'i', align=1)
         self.assertEqual(i.type, int32)
+        # Atomics
+        j = builder.store_atomic(b, c, ordering="seq_cst", align=4)
+        self.assertEqual(j.type, ir.VoidType())
+        k = builder.load_atomic(c, ordering="seq_cst", align=4, name='k')
+        self.assertEqual(k.type, int32)
         # Not pointer types
         with self.assertRaises(TypeError):
             builder.store(b, a)
@@ -788,6 +840,8 @@
                 %"g" = load i32, i32* %"c"
                 store i32 %".2", i32* %"c", align 1
                 %"i" = load i32, i32* %"c", align 1
+                store atomic i32 %".2", i32* %"c" seq_cst, align 4
+                %"k" = load atomic i32, i32* %"c" seq_cst, align 4
             """)
 
     def test_gep(self):
@@ -1165,6 +1219,64 @@
                 call void @"llvm.assume"(i1 %"c")
             """)
 
+    def test_vector_ops(self):
+        block = self.block(name='insert_block')
+        builder = ir.IRBuilder(block)
+        a, b = builder.function.args[:2]
+        a.name = 'a'
+        b.name = 'b'
+
+        vecty = ir.VectorType(a.type, 2)
+        vec = ir.Constant(vecty, ir.Undefined)
+        idxty = ir.IntType(32)
+        vec = builder.insert_element(vec, a, idxty(0), name='vec1')
+        vec = builder.insert_element(vec, b, idxty(1), name='vec2')
+
+        self.check_block(block, """\
+            insert_block:
+                %"vec1" = insertelement <2 x i32> <i32 undef, i32 undef>, i32 
%"a", i32 0
+                %"vec2" = insertelement <2 x i32> %"vec1", i32 %"b", i32 1
+            """)
+
+        block = builder.append_basic_block("shuffle_block")
+        builder.branch(block)
+        builder.position_at_end(block)
+
+        mask = ir.Constant(vecty, [1, 0])
+        shuff = builder.shuffle_vector(vec, vec, mask, name='shuf')
+
+        self.check_block(block, """\
+            shuffle_block:
+                %"shuf" = shufflevector <2 x i32> %"vec2", <2 x i32> %"vec2", 
<2 x i32> <i32 1, i32 0>
+            """)
+
+        block = builder.append_basic_block("add_block")
+        builder.branch(block)
+        builder.position_at_end(block)
+
+        vadd = builder.add(vec, vec, name='sum')
+
+        self.check_block(block, """\
+            add_block:
+                %"sum" = add <2 x i32> %"vec2", %"vec2"
+            """)
+
+        block = builder.append_basic_block("extract_block")
+        builder.branch(block)
+        builder.position_at_end(block)
+
+        c = builder.extract_element(vec, idxty(0), name='ex1')
+        d = builder.extract_element(vec, idxty(1), name='ex2')
+
+        self.check_block(block, """\
+            extract_block:
+              %"ex1" = extractelement <2 x i32> %"vec2", i32 0
+              %"ex2" = extractelement <2 x i32> %"vec2", i32 1
+            """)
+
+        builder.ret(builder.add(c, d))
+        self.assert_valid_ir(builder.module)
+
     def test_bitreverse(self):
         block = self.block(name='my_block')
         builder = ir.IRBuilder(block)
@@ -1429,6 +1541,34 @@
                 br label %"one.endif"
             """)
 
+
+    def test_if_then_long_label(self):
+        full_label = 'Long'*20
+        block = self.block(name=full_label)
+        builder = ir.IRBuilder(block)
+        z = ir.Constant(int1, 0)
+        a = builder.add(z, z, 'a')
+        with builder.if_then(a) as bbend:
+            b = builder.add(z, z, 'b')
+            with builder.if_then(b) as bbend:
+                c = builder.add(z, z, 'c')
+        builder.ret_void()
+        self.check_func_body(builder.function, """\
+            {full_label}:
+                %"a" = add i1 0, 0
+                br i1 %"a", label %"{label}.if", label %"{label}.endif"
+            {label}.if:
+                %"b" = add i1 0, 0
+                br i1 %"b", label %"{label}.if.if", label %"{label}.if.endif"
+            {label}.endif:
+                ret void
+            {label}.if.if:
+                %"c" = add i1 0, 0
+                br label %"{label}.if.endif"
+            {label}.if.endif:
+                br label %"{label}.endif"
+            """.format(full_label=full_label, label=full_label[:25] + '..'))
+
     def test_if_then_likely(self):
         def check(likely):
             block = self.block(name='one')
@@ -1606,10 +1746,7 @@
     def test_pickling(self):
         types = self.assorted_types()
         for ty in types:
-            data = pickle.dumps(ty, protocol=-1)
-            newty = pickle.loads(data)
-            self.assertIs(newty.__class__, ty.__class__)
-            self.assertEqual(str(newty), str(ty))
+            newty = self.assert_pickle_correctly(ty)
             if self.has_logical_equality(ty):
                 self.assertEqual(newty, ty)
 
@@ -1753,6 +1890,11 @@
         td = llvm.create_target_data("e-m:e-i64:64-f80:128-n8:16:32:64-S128")
         self.assertEqual(mytype.get_abi_size(td, context=context), 4)
 
+    def test_vector(self):
+        context = ir.Context()
+        vecty = ir.VectorType(ir.IntType(32), 8)
+        self.assertEqual(str(vecty), "<8 x i32>")
+
 
 c32 = lambda i: ir.Constant(int32, i)
 
@@ -1819,6 +1961,14 @@
         with self.assertRaises(ValueError):
             ir.Constant(ir.ArrayType(int32, 3), (5, 6))
 
+    def test_vector(self):
+        vecty = ir.VectorType(ir.IntType(32), 8)
+        vals = [1, 2, 4, 3, 8, 6, 9, 7]
+        vec = ir.Constant(vecty, vals)
+        vec_repr = "<8 x i32> <{}>".format(
+            ', '.join(map('i32 {}'.format, vals)))
+        self.assertEqual(str(vec), vec_repr)
+
     def test_structs(self):
         st1 = ir.LiteralStructType((flt, int1))
         st2 = ir.LiteralStructType((int32, st1))
@@ -1849,6 +1999,11 @@
         with self.assertRaises(ValueError):
             ir.Constant(st2, (4, 5, 6))
 
+    def test_undefined_literal_struct_pickling(self):
+        i8 = ir.IntType(8)
+        st = ir.Constant(ir.LiteralStructType([i8, i8]), ir.Undefined)
+        self.assert_pickle_correctly(st)
+
     def test_type_instantiaton(self):
         """
         Instantiating a type should create a constant.
@@ -1958,5 +2113,13 @@
         self.assertEqual(call.callee, bar)
 
 
+class TestSingleton(TestBase):
+    def test_undefined(self):
+        self.assertIs(ir.Undefined, ir.values._Undefined())
+        self.assertIs(ir.Undefined, copy.copy(ir.Undefined))
+        self.assertIs(ir.Undefined, copy.deepcopy(ir.Undefined))
+        self.assert_pickle_correctly(ir.Undefined)
+
+
 if __name__ == '__main__':
     unittest.main()


Reply via email to