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