diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3a05aa8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +llvm/_version.py export-subst diff --git a/.gitignore b/.gitignore index 6d0cc2b..6d6296f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ build _build *.pyc +*.so /llvm/_intrinsic_ids.py +llvm_ +newbinding/api/* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f4474f7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: python + +python: + - "2.6" + - "2.7" + - "3.2" + - "3.3" + +branches: + only: + - master + +install: + - wget "http://repo.continuum.io/pkgs/free/linux-64/llvm-3.2-0.tar.bz2" + - tar -xjf llvm-3.2-0.tar.bz2 + - PATH+=":`pwd`/bin" + - export LD_LIBRARY_PATH="`pwd`/lib" + - export LLVM_CONFIG_PATH="`pwd`/bin/llvm-config" + - $LLVM_CONFIG_PATH --cflags # test llvm-config + - export LLVMPY_DYNLINK=1 + - python setup.py install -q + +script: cd ~; python -c "import sys;import llvm;sys.exit(0 if llvm.test() == 0 else 1)" + diff --git a/CHANGELOG b/CHANGELOG index 396ce0e..45d6a5f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,14 +1,88 @@ +2014-04-28 0.12.5: +--------------------- + * Fixes memory leaks (#92) + * Fixes tarball (#99) -0.7, in progress: +2014-03-20 0.12.4: +--------------------- + * Add dylib_import_library and friends + * Fix BasicBlock downcast + * Module hashing + * Fix test script +2014-02-18 0.12.3: +--------------------- + * Fix deprecation message for py2.6 + * Fix llvm_cbuilder for using deprecated_alloca + * Merged PR #88 by cantora + * Merged PR #94 by cgohlke + +2014-02-04 0.12.2: +--------------------- + * enhance wrapper efficiency by moving some capsule code into C++ + * fix unclosed file handler in avx_support + * multiple-dimension insert_value, extract_value + * various minor fixes + +2013-11-11 0.12.1: +--------------------- + * various bug fixes + +2013-08-28 0.12.0: +--------------------- + * update to LLVM 3.3 and maintain compatibility with LLVM 3.2 + * add LLRT for minimal support for 64-bit divmod on 32-bit platform + * start to adopt MCJIT (not quite usable on win32) + * various bug fixes + +2013-03-05 0.11.1: +-------------------- + * fix test when cc is not available + * fix Python 3 division (Hernan Grecco) (Issue #59) + * add relocation enums and add reloc argument for TargetMachine + + +2013-03-01 0.11.0: +-------------------- + * fix Python 3 support on Windows + * New llvm binding + + +2013-02-01 0.10.2: +-------------------- + * change default to link dynamically to LLVM use: + $ export LLVMPY_DYNLINK=0 # link statically + $ export LLVMPY_DYNLINK=1 # link dynamically + $ unset LLVMPY_DYNLINK # tries to link dynamically if LLVM shared + # objects are found and statically otherwise + * fix llpython for Python 2.6 support + + +2013-01-25 0.10.1: +-------------------- + * fix support for Python 2.6 + + +2013-01-18 0.10.0: +-------------------- + * Add LLVM 3.2 support. + * New TargetData class. + * Fixed windows issue (Issue #42). + * Add ExecutionEngine.add_global_mapping and .get_pointer_to_global. + * Improved TargetMachine class and added code-model constants (CM_*). + * Added llvm.passes.build_pass_managers as a simpler way to build PassManagers. + + +in progress, 0.7: +----------------- * Add llvm.core.Argument.alignment property. * Migrate to LLVM 2.8. * Fix ffi link issue on darwin (Albert Mietus) (Issue #29). * LLVM tutorial ported (Max Shawabkeh) (Issue #33). -0.6, 31-Aug-2010: - +2010-08-31 0.6: +----------------- * Add and remove function attributes (Krzysztof Goj) (Issue #21). * Wrap fadd,fsub,fmul (Aaron S Lav) (Issue #31). * Migrate to LLVM 2.7. @@ -27,16 +101,16 @@ * Migrate to LLVM 2.5. -0.5, 22-Nov-2008: - +2008-11-22 0.5: +----------------- * Added vicmp, vfcmp instructions and constant expressions. * Builds on FreeBSD. * Updated documentation. * Migrate to LLVM 2.4. -0.4, 21-Nov-2008: - +2008-11-21 0.4: +----------------- * Code cleanup, added license headers. * Added llvm.core.load_library_permanently() (Issue #12). * Fix comparison using != (Issue #11). @@ -45,8 +119,8 @@ * Added viewCFG methods to Function (Paulo Silva). -0.3, 8-Sep-2008: - +2008-09-08 0.3: +----------------- * Passes added. * Assembly support: create modules from .ll files. * Various bug fixes. @@ -58,13 +132,13 @@ * Updated documentation. -0.2.1, 18-Jun-2008: - +2008-06-28 0.2.1: +------------------- * Build cleanly with LLVM 2.3 and 2.3svn. -0.2, 15-Jun-2008: - +2008-06-15 0.2: +----------------- * Independent package, need not be unpacked into llvm/bindings. * Fixed ownership issues with Module/ModuleProvider. * Modules, values and types can be stringified, to get their LLVM @@ -79,7 +153,6 @@ * Lots of cleanup. -0.1, 10-May-2008: - - * Initial release. - +2008-05-10 0.1: +----------------- + * Initial release diff --git a/MANIFEST.in b/MANIFEST.in index ec22b21..25a211d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,6 @@ -include CHANGELOG LICENSE README setup.py MANIFEST.in +include CHANGELOG LICENSE README.rst setup.py MANIFEST.in versioneer.py recursive-include llvm * +recursive-include llvmpy * recursive-include www * recursive-include test * +recursive-include tools * diff --git a/README.rst b/README.rst index ae8eaa1..a1abf84 100644 --- a/README.rst +++ b/README.rst @@ -10,26 +10,54 @@ http://www.llvmpy.org Versions -------- -This package has only been tested with LLVM 3.1, and Python 2.7, (not Python 3.x). +This package has been tested with LLVM 3.2, Python 2.6, 2.7 and 3.3. +Other Python versions may work. Quickstart ---------- -1. Get 3.1 version of LLVM, build it. Make sure ``--enable-pic`` is passed to - LLVM's ``configure``. +1. Get and extract LLVM 3.2 source tarball from + `llvm.org `_. Then, ``cd`` into + the extracted directory. -2. Get llvm-py and install it:: +2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``. + + **Note**: Without the ``--enable-optimized`` flag, debug build will be + selected. Unless you are developing LLVM or llvmpy, it is recommended + that the flag is used to reduce build time and binary size. + + **Note**: Use prefix to select the installation path. It is recommended + to separate your custom build from the default system package. Please + replace ``LLVM_INSTALL_PATH`` with your own path. + +3. Run ``REQUIRES_RTTI=1 make install`` to build and install. + + **Note**: With LLVM 3.2, the default build configuration has C++ RTTI + disabled. However, llvmpy requires RTTI. + + **Note**: Use ``make -j2 install`` to enable concurrent build. + Replace ``2`` with the actual number of processor you have. + +4. Get llvm-py and install it:: $ git clone git@github.com:llvmpy/llvmpy.git $ cd llvmpy - $ python setup.py install + $ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install Run the tests:: $ python -c "import llvm; llvm.test()" -3. See documentation at 'http://www.llvmpy.org/pages.html' and examples +5. See documentation at 'http://www.llvmpy.org' and examples under 'test'. + +Common Build Problems +--------------------- + +1. If llvmpy cannot be imported due to "undefined symbol: + _ZTIN4llvm24PassRegistrationListenerE", it is because RTTI is not enabled + when building LLVM. "_ZTIN4llvm24PassRegistrationListenerE" is the typeinfo + of PassRegistrationListener class. LICENSE ------- diff --git a/README_LLVM_CBUILDER.md b/README_LLVM_CBUILDER.md new file mode 100644 index 0000000..da180c4 --- /dev/null +++ b/README_LLVM_CBUILDER.md @@ -0,0 +1,144 @@ +LLVM CBuilder +============= + +A few short examples: +(TODO: add more later) + +```python +from llvm.core import * +from llvm_cbuilder import * +import llvm_cbuilder.shortnames as C +``` + +```python +class Square(CDefinition): + _name_ = 'square' + _retty_ = C.double + _argtys_ = [ ('x', C.double) ] + + def body(self, x): + y = x * x + self.ret(y) +``` + +```python +m = Module.new('my_module') +llvm_square = Square()(m) +print(m) +``` + +``` +; ModuleID = 'my_module' + +define double @square(double %x) { +decl: + %0 = fmul double %x, %x + ret double %0 +} +``` + + +```python +class IsPrime(CDefinition): + _name_ = 'isprime' + _retty_ = C.int + _argtys_ = [('x', C.int)] + + def body(self, x): + false = zero = self.constant(C.int, 0) + true = one = self.constant(C.int, 1) + + two = self.constant(C.int, 2) + + with self.ifelse( x <= two ) as ifelse: + with ifelse.then(): + self.ret(true) + + with self.ifelse( (x % two) == zero ) as ifelse: + with ifelse.then(): + self.ret(false) + + idx = self.var(C.int, 3, name='idx') + + with self.loop() as loop: + with loop.condition() as setcond: + setcond( idx < x ) + + with loop.body(): + with self.ifelse( (x % idx ) == zero ) as ifelse: + with ifelse.then(): + self.ret(false) + idx += two + + self.ret(true) +``` + + + +``` +define i32 @isprime(i32 %x) { +decl: + %0 = icmp sle i32 %x, 2 + br i1 %0, label %if.then, label %if.end + +if.then: ; preds = %loop.body, %loop.cond, %if.end, %decl + %merge = phi i32 [ 1, %decl ], [ 0, %if.end ], [ 1, %loop.cond ], [ 0, %loop.body ] + ret i32 %merge + +if.end: ; preds = %decl + %1 = srem i32 %x, 2 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %if.then, label %if.end4 + +if.end4: ; preds = %if.end + br label %loop.cond + +loop.cond: ; preds = %if.end7, %if.end4 + %idx.0 = phi i32 [ 3, %if.end4 ], [ %6, %if.end7 ] + %3 = icmp slt i32 %idx.0, %x + br i1 %3, label %loop.body, label %if.then + +loop.body: ; preds = %loop.cond + %4 = srem i32 %x, %idx.0 + %5 = icmp eq i32 %4, 0 + br i1 %5, label %if.then, label %if.end7 + +if.end7: ; preds = %loop.body + %6 = add i32 %idx.0, 2 + br label %loop.cond +} + +; ModuleID = 'my_module' + +define i32 @isprime(i32 %x) { +decl: + %0 = icmp sle i32 %x, 2 + br i1 %0, label %if.then, label %if.end + +if.then: ; preds = %loop.body, %loop.cond, %if.end, %decl + %merge = phi i32 [ 1, %decl ], [ 0, %if.end ], [ 1, %loop.cond ], [ 0, %loop.body ] + ret i32 %merge + +if.end: ; preds = %decl + %1 = srem i32 %x, 2 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %if.then, label %if.end4 + +if.end4: ; preds = %if.end + br label %loop.cond + +loop.cond: ; preds = %if.end7, %if.end4 + %idx.0 = phi i32 [ 3, %if.end4 ], [ %6, %if.end7 ] + %3 = icmp slt i32 %idx.0, %x + br i1 %3, label %loop.body, label %if.then + +loop.body: ; preds = %loop.cond + %4 = srem i32 %x, %idx.0 + %5 = icmp eq i32 %4, 0 + br i1 %5, label %if.then, label %if.end7 + +if.end7: ; preds = %loop.body + %6 = add i32 %idx.0, 2 + br label %loop.cond +} +``` diff --git a/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat new file mode 100644 index 0000000..e9177c5 --- /dev/null +++ b/buildscripts/condarecipe/bld.bat @@ -0,0 +1,6 @@ +set LLVMPY_DYNLINK=0 +set INCLUDE=%LIBRARY_INC% +set LIBPATH=%LIBRARY_LIB% +set LIB=%LIBRARY_LIB% +%PYTHON% setup.py install +if errorlevel 1 exit 1 diff --git a/buildscripts/condarecipe/build.sh b/buildscripts/condarecipe/build.sh new file mode 100644 index 0000000..5c98fde --- /dev/null +++ b/buildscripts/condarecipe/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +if [[ (`uname` == Linux) && (`uname -m` != armv6l) ]] +then + export CC=gcc + #gcc44 + export CXX=g++ + #g++44 +fi + +export LLVMPY_DYNLINK=$DISTRO_BUILD + +$PYTHON setup.py install diff --git a/buildscripts/condarecipe/meta.yaml b/buildscripts/condarecipe/meta.yaml new file mode 100644 index 0000000..4612840 --- /dev/null +++ b/buildscripts/condarecipe/meta.yaml @@ -0,0 +1,28 @@ +package: + name: llvmpy + version: 99.9.9 + +source: + git_url: git@github.com:llvmpy/llvmpy.git +# git_tag: 0.12.0 + +requirements: + build: + - llvm + - python + #- chrpath [linux] + run: + - llvm [unix] + - python + +test: + imports: + - llvm + - llvmpy + - llvmpy._api + - llvmpy._capsule + - llpython + - llvm_array + - llvm_cbuilder + + diff --git a/buildscripts/condarecipe/run_test.py b/buildscripts/condarecipe/run_test.py new file mode 100644 index 0000000..682b8d4 --- /dev/null +++ b/buildscripts/condarecipe/run_test.py @@ -0,0 +1,22 @@ +import sys +import platform +import llvm + +from llvm.core import Module +from llvm.ee import EngineBuilder +from llvm.utils import check_intrinsics + +m = Module.new('fjoidajfa') +eb = EngineBuilder.new(m) +target = eb.select_target() + +print('target.triple=%r' % target.triple) +if sys.platform == 'darwin': + s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]] + assert target.triple.startswith(s + '-apple-darwin') + +assert llvm.test(verbosity=2, run_isolated=False) == 0 +#check_intrinsics.main() + +print('llvm.__version__: %s' % llvm.__version__) +#assert llvm.__version__ == '0.12.0' diff --git a/docs/gh-pages.py b/docs/gh-pages.py index d9c8614..3ee5d20 100755 --- a/docs/gh-pages.py +++ b/docs/gh-pages.py @@ -30,7 +30,7 @@ from subprocess import Popen, PIPE, CalledProcessError, check_call pages_dir = 'gh-pages' html_dir = '_build/html' pdf_dir = '_build/latex' -pages_repo = 'git@github.com:llvmpy/llvmpy-doc.git' +pages_repo = 'https://github.com/llvmpy/llvmpy-doc.git' #----------------------------------------------------------------------------- # Functions @@ -86,7 +86,7 @@ if __name__ == '__main__': tag = sh2('git describe --exact-match') except CalledProcessError: tag = "dev" # Fallback - + startdir = os.getcwdu() if not os.path.exists(pages_dir): # init the repo diff --git a/docs/source/conf.py b/docs/source/conf.py index b7a7342..701ef80 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,12 +11,23 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys, os, glob # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +#sys.path.insert(0, os.path.abspath('../..')) + +# Support sphinx.ext.autodoc to extract docstrings from modules without installing +# complete package. +# The python modules depend on _core, so we must build entire package first though. +built_lib = glob.glob('../../build/lib.*-%d.%d/' % sys.version_info[:2]) +if not built_lib: + sys.stderr.write("WARNING: To build complete documentation you must build " + "package first\n") +else: + # lib dir has platform suffix + sys.path.insert(0, os.path.abspath(built_lib[0])) # -- General configuration ----------------------------------------------------- @@ -25,7 +36,7 @@ import sys, os # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.mathjax'] +extensions = ['sphinx.ext.mathjax', 'sphinx.ext.autodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -41,16 +52,22 @@ master_doc = 'index' # General information about the project. project = u'llvmpy' -copyright = u'2012, Mahadevan R (2008-2010), Continuum Analytics (2012)' +copyright = u'2013, Mahadevan R (2008-2010), Continuum Analytics (2012-2013)' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. -version = '0.8' -# The full version, including alpha/beta/rc tags. -release = '0.8.2' +try: + import llvm + version_strs = llvm.__version__.split('.') + # The short X.Y version. + version = '.'.join(version_strs[:2]) + # The full version, including alpha/beta/rc tags. + release = '%s.%s' % (version, '-'.join(version_strs[2].split('-')[:2])) +except ImportError: + version = 'unknown-version' + release = 'unknown-release' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/doc/core.rst b/docs/source/doc/core.rst new file mode 100644 index 0000000..a3b94b6 --- /dev/null +++ b/docs/source/doc/core.rst @@ -0,0 +1,9 @@ +******************************** +llvm.core +******************************** + +.. toctree:: + :titlesonly: + :glob: + + llvm.core.* \ No newline at end of file diff --git a/docs/source/doc/examples/JITTutorial2.rst b/docs/source/doc/examples/JITTutorial2.rst index a9a9979..6e76150 100644 --- a/docs/source/doc/examples/JITTutorial2.rst +++ b/docs/source/doc/examples/JITTutorial2.rst @@ -1,5 +1,5 @@ A More Complicated Function -==================== +=========================== .. code-block:: python diff --git a/docs/source/doc/getting_started.rst b/docs/source/doc/getting_started.rst index 47e465a..53c2982 100644 --- a/docs/source/doc/getting_started.rst +++ b/docs/source/doc/getting_started.rst @@ -26,7 +26,7 @@ Both LLVM and llvmpy are distributed under (different) permissive open source licenses. llvmpy uses the `new BSD license `_. More information is available -`here `_. +`here `_. Platforms --------- @@ -38,12 +38,11 @@ supported, for a variety of reasons. Versions -------- -llvmpy 0.8.2 requires version 3.1 of LLVM. It may not work with +llvmpy 0.11.2 uses LLVM 3.2 (or at least 3.1). It may not work with previous versions. -llvmpy has been built and tested with Python 2.7. It should work with -earlier versions. It has not been tried with Python 3.x (patches -welcome). +llvmpy has been built and tested with Python 2.7 and 3.2. It should work with +earlier versions. Installation @@ -66,22 +65,6 @@ It does not matter which compiler LLVM itself was built with (``g++``, ``llvm-g++`` or any other); llvmpy can be built with any compiler. It has been tried only with gcc/g++ though. - -LLVM and ``--enable-pic`` -------------------------- - -The result of an LLVM build is a set of static libraries and object -files. The llvmpy contains an extension package that is built into a -shared object (\_core.so) which links to these static libraries and -object files. It is therefore required that the LLVM libraries and -object files be built with the ``-fPIC`` option (generate position -independent code). Be sure to use the ``--enable-pic`` option while -configuring LLVM (default is no PIC), like this: - -.. code-block:: bash - - $ ~/llvm ./configure --enable-pic --enable-optimized - llvm-config ----------- @@ -99,13 +82,34 @@ is different from that of 'root', so even if ``llvm-config`` is in your Steps ----- -Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to -LLVM's 'configure'. +1. Get and extract LLVM 3.2 source tarball from + `llvm.org `_. Then, ``cd`` into + the extracted directory. -Get llvmpy and install it: +2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``. + **Note**: Without the ``--enable-optimized`` flag, debug build will be + selected. Unless you are developing LLVM or llvmpy, it is recommended + that the flag is used to reduce build time and binary size. + + **Note**: Use prefix to select the installation path. It is recommended + to separate your custom build from the default system package. Please + replace ``LLVM_INSTALL_PATH`` with your own path. -.. code-block:: bash +3. Run ``REQUIRES_RTTI=1 make`` to build. - $ git clone git@github.com:numba/llvmpy.git - $ cd llvmpy $ python setup.py install + **Note**: With LLVM 3.2, the default build configuration has C++ RTTI + disabled. However, llvmpy requires RTTI. + +4. Get llvm-py and install it:: + + $ git clone git@github.com:llvmpy/llvmpy.git + $ cd llvmpy + $ LLVM_CONFIG_PATH=LLVM_INSTALL_PATH/bin/llvm-config python setup.py install + + Run the tests:: + + $ python -c "import llvm; llvm.test()" + +5. See documentation at 'http://www.llvmpy.org' and examples + under 'test'. diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst index 7b1c3a6..ae4b80d 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl1.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl1.rst @@ -6,7 +6,7 @@ Written by `Chris Lattner `_ and `Max Shawabkeh `_ Introduction -========= +============ Welcome to the "Implementing a language with LLVM" tutorial. This tutorial runs through the implementation of a simple language, showing @@ -115,13 +115,13 @@ following simple example computes `Fibonacci numbers `_: -.. code-block:: python +.. code-block:: text # Compute the x'th fibonacci number. - def fib(x): - if x < 3: + def fib(x) + if x < 3 return 1 - else: + else return fib(x-1)+fib(x-2) # This expression will compute the 40th number. @@ -226,7 +226,7 @@ the line. # Regular expressions that tokens and comments of our language. REGEX_NUMBER = re.compile('[0-9]+(?:.[0-9]+)?') - REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]\ *') + REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]*') REGEX_COMMENT = re.compile('#.*') diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl2.rst b/docs/source/doc/kaleidoscope/PythonLangImpl2.rst index 8c915db..a375512 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl2.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl2.rst @@ -772,7 +772,7 @@ Lexer # Regular expressions that tokens and comments of our language. REGEX_NUMBER = re.compile('[0-9]+(?:\.[0-9]+)?') - REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9] *') + REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]*') REGEX_COMMENT = re.compile('#.*') def Tokenize(string): @@ -811,7 +811,7 @@ Lexer yield CharacterToken(string[0]) string = string[1:] - yield EOFToken() + yield EOFToken() diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl3.rst b/docs/source/doc/kaleidoscope/PythonLangImpl3.rst index 5719bb2..15ec212 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl3.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl3.rst @@ -1058,7 +1058,7 @@ Main driver code. '+': 20, '-': 20, '*': 40 - } + } # Run the main "interpreter loop". while True: diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst index 5a096da..33edba2 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl5.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl5.rst @@ -217,7 +217,8 @@ Kaleidoscope looks something like this: br i1 %ifcond, label %then, label %else then: ; preds = %entry - %calltmp1 = call double @bar() + %calltmp = call double @foo() + br label %ifcont else: ; preds = %entry %calltmp1 = call double @bar() diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst index 2e98cef..8ff31d4 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl6.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl6.rst @@ -847,7 +847,7 @@ Lexer # Regular expressions that tokens and comments of our language. REGEX_NUMBER = re.compile('[0-9]+(?:\.[0-9]+)?') - REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9] *') + REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]*') REGEX_COMMENT = re.compile('#.*') def Tokenize(string): diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index d3dfb74..dee1c31 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst @@ -121,8 +121,8 @@ to talk about how LLVM represents stack variables. In LLVM, all memory accesses are explicit with load/store instructions, and it is carefully designed not to have (or need) an "address-of" operator. Notice how the type of the @G/@H global variables is actually -"i32\ *" even though the variable is defined as "i32". What this means -is that @G defines* space* for an i32 in the global data area, but its +"i32\*" even though the variable is defined as "i32". What this means +is that @G defines *space* for an i32 in the global data area, but its *name* actually refers to the address for that space. Stack variables work the same way, except that instead of being declared with global variable definitions, they are declared with the `LLVM alloca @@ -133,11 +133,11 @@ instruction `_: define i32 @example() { entry: - %X = alloca i32 ; type of %X is i32 *. + %X = alloca i32 ; type of %X is i32* ... - %tmp = load i32* %X ; load the stack value %X from the stack. - %tmp2 = add i32 %tmp, 1 ; increment it store i32 %tmp2, - i32* %X ; store it back + %tmp = load i32* %X ; load the stack value %X from the stack + %tmp2 = add i32 %tmp, 1 ; increment it + store i32 %tmp2, i32* %X ; store it back ... @@ -295,7 +295,7 @@ variables is a useful thing regardless of whether you will be mutating them. Here's a motivating example that shows how we could use these: -.. code-block:: +.. code-block:: none # Define ':' for sequencing: as a low-precedence operator that ignores operands # and just returns the RHS. @@ -352,7 +352,7 @@ function that ensures that the allocas are created in the entry block of the function: -.. code-block:: +.. code-block:: python # Creates an alloca instruction in the entry block of the function. This is used # for mutable variables. @@ -475,7 +475,7 @@ It is interesting to see what the code looks like before and after the mem2reg optimization runs. For example, this is the before/after code for our recursive fib function. Before the optimization: -.. code-block:: +.. code-block:: llvm define double @fib(double %x) { entry: @@ -515,7 +515,7 @@ still just make the PHI. Here is the code after the mem2reg pass runs: -.. code-block:: +.. code-block:: llvm define double @fib(double %x) { entry: @@ -651,7 +651,7 @@ Now that we have an assignment operator, we can mutate loop variables and arguments. For example, we can now run code like this: -.. code-block:: +.. code-block:: none # Function to print a double. extern printd(x) @@ -1000,7 +1000,7 @@ Lexer # Regular expressions that tokens and comments of our language. REGEX_NUMBER = re.compile('[0-9]+(?:\.[0-9]+)?') - REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9] *') + REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9] *') REGEX_COMMENT = re.compile('#.*') def Tokenize(string): diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst index dd4abc1..eb13dd0 100644 --- a/docs/source/doc/kaleidoscope/PythonLangImpl8.rst +++ b/docs/source/doc/kaleidoscope/PythonLangImpl8.rst @@ -1,6 +1,6 @@ -************************************************* +*************************************************** Chapter 8: Conclusion and other useful LLVM tidbits -************************************************* +*************************************************** Written by Chris Lattner @@ -106,7 +106,7 @@ generating LLVM IR. These are some of the more subtle things that may not be obv but are very useful if you want to take advantage of LLVM's capabilities. Properties of the LLVM IR -======================== +========================= We have a couple common questions about code in the LLVM IR form - let's just get these out of the way right now, shall we? @@ -164,7 +164,7 @@ This can make sense for specialized domains such as an in-kernel language. -------------- Safety Guarantees ----------------- +----------------- Many of the languages above are also "safe" languages: it is impossible for a program written in Java to corrupt its address space and @@ -236,7 +236,7 @@ you desire in your front-end, on the language-specific AST. -------------- Tips and Tricks -============== +=============== There is a variety of useful tips and tricks that you come to know after working on/with LLVM that aren't obvious at first glance. diff --git a/docs/source/doc/llpython/articles.rst b/docs/source/doc/llpython/articles.rst new file mode 100644 index 0000000..ff7669c --- /dev/null +++ b/docs/source/doc/llpython/articles.rst @@ -0,0 +1,10 @@ +LLPython Articles +================= + +.. toctree:: + :titlesonly: + :maxdepth: 1 + + intro_llpython.rst + nobitey_dev.rst + ctmp_in_llpython.rst diff --git a/docs/source/doc/llpython/ctmp_in_llpython.rst b/docs/source/doc/llpython/ctmp_in_llpython.rst new file mode 100644 index 0000000..53f63bf --- /dev/null +++ b/docs/source/doc/llpython/ctmp_in_llpython.rst @@ -0,0 +1,5 @@ +Compile-time Metaprogramming in LLPython +======================================== + +In this article, we discuss how LLPython supports compile-time +metaprogramming. diff --git a/docs/source/doc/llpython/index.rst b/docs/source/doc/llpython/index.rst new file mode 100644 index 0000000..43ea17a --- /dev/null +++ b/docs/source/doc/llpython/index.rst @@ -0,0 +1,9 @@ +LLPython Documentation +====================== + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + articles.rst + reference.rst diff --git a/docs/source/doc/llpython/intro_llpython.rst b/docs/source/doc/llpython/intro_llpython.rst new file mode 100644 index 0000000..47c0c2a --- /dev/null +++ b/docs/source/doc/llpython/intro_llpython.rst @@ -0,0 +1,46 @@ +==================== +Introducing LLPython +==================== + +In this article, we introduce the llpython package. The primary goal +of the llpython package is to provide a Python dialect/subset that +maps directly to LLVM code. LLPython differs from its originating +LLVM translator, Numba, in the following aspects: + + * LLPython code is not intended to work in Python if not translated + and wrapped. + * The LLPython translator only uses LLVM types. + * LLPython is explicitly typed, and does not support type inference. + LLPython does not support implicit casts, all casts must be explicit. + * LLPython supports code that directly calls the C API, the Python C + API, and the llvm.core.Builder methods. + +Additionally, we designed the sub-package to have the following +engineering properties: + + * Usable from Python 2.7, and 3.X. At the time of writing, we plan + to support Python 2.6. + * Clean from Numba dependencies (other than llvmpy), and can be used + as a standalone code generator without a full Numba installation. + * Provides a series of Python bytecode passes that can be easily + used by other projects. + + +LLPython Origins +================ + +We developed LLPython with the initial goal of simplifying writing +LLVM code. + + +LLPython Internals +================== + +In this section, we describe the various passes performed by the +LLPython translator. + + +Conclusions +=========== + +LLPython is neat. diff --git a/docs/source/doc/llpython/llpython.byte_control.rst b/docs/source/doc/llpython/llpython.byte_control.rst new file mode 100644 index 0000000..e851dac --- /dev/null +++ b/docs/source/doc/llpython/llpython.byte_control.rst @@ -0,0 +1,6 @@ +===================== +llpython.byte_control +===================== + +.. automodule:: llpython.byte_control + :members: diff --git a/docs/source/doc/llpython/llpython.byte_flow.rst b/docs/source/doc/llpython/llpython.byte_flow.rst new file mode 100644 index 0000000..783a54b --- /dev/null +++ b/docs/source/doc/llpython/llpython.byte_flow.rst @@ -0,0 +1,6 @@ +================== +llpython.byte_flow +================== + +.. automodule:: llpython.byte_flow + :members: diff --git a/docs/source/doc/llpython/llpython.byte_translator.rst b/docs/source/doc/llpython/llpython.byte_translator.rst new file mode 100644 index 0000000..2a5993c --- /dev/null +++ b/docs/source/doc/llpython/llpython.byte_translator.rst @@ -0,0 +1,6 @@ +======================== +llpython.byte_translator +======================== + +.. automodule:: llpython.byte_translator + :members: diff --git a/docs/source/doc/llpython/llpython.bytecode_visitor.rst b/docs/source/doc/llpython/llpython.bytecode_visitor.rst new file mode 100644 index 0000000..3479ff7 --- /dev/null +++ b/docs/source/doc/llpython/llpython.bytecode_visitor.rst @@ -0,0 +1,6 @@ +========================= +llpython.bytecode_visitor +========================= + +.. automodule:: llpython.bytecode_visitor + :members: diff --git a/docs/source/doc/llpython/llpython.bytetype.rst b/docs/source/doc/llpython/llpython.bytetype.rst new file mode 100644 index 0000000..81efe83 --- /dev/null +++ b/docs/source/doc/llpython/llpython.bytetype.rst @@ -0,0 +1,6 @@ +================= +llpython.bytetype +================= + +.. automodule:: llpython.bytetype + :members: diff --git a/docs/source/doc/llpython/llpython.control_flow.rst b/docs/source/doc/llpython/llpython.control_flow.rst new file mode 100644 index 0000000..c9aee7d --- /dev/null +++ b/docs/source/doc/llpython/llpython.control_flow.rst @@ -0,0 +1,6 @@ +===================== +llpython.control_flow +===================== + +.. automodule:: llpython.control_flow + :members: diff --git a/docs/source/doc/llpython/llpython.gen_bytecode_visitor.rst b/docs/source/doc/llpython/llpython.gen_bytecode_visitor.rst new file mode 100644 index 0000000..2bc19db --- /dev/null +++ b/docs/source/doc/llpython/llpython.gen_bytecode_visitor.rst @@ -0,0 +1,6 @@ +============================= +llpython.gen_bytecode_visitor +============================= + +.. automodule:: llpython.gen_bytecode_visitor + :members: diff --git a/docs/source/doc/llpython/llpython.nobitey.rst b/docs/source/doc/llpython/llpython.nobitey.rst new file mode 100644 index 0000000..59e052d --- /dev/null +++ b/docs/source/doc/llpython/llpython.nobitey.rst @@ -0,0 +1,6 @@ +================ +llpython.nobitey +================ + +.. automodule:: llpython.nobitey + :members: diff --git a/docs/source/doc/llpython/llpython.opcode_util.rst b/docs/source/doc/llpython/llpython.opcode_util.rst new file mode 100644 index 0000000..0fa5387 --- /dev/null +++ b/docs/source/doc/llpython/llpython.opcode_util.rst @@ -0,0 +1,6 @@ +==================== +llpython.opcode_util +==================== + +.. automodule:: llpython.opcode_util + :members: diff --git a/docs/source/doc/llpython/llpython.phi_injector.rst b/docs/source/doc/llpython/llpython.phi_injector.rst new file mode 100644 index 0000000..3db3863 --- /dev/null +++ b/docs/source/doc/llpython/llpython.phi_injector.rst @@ -0,0 +1,6 @@ +===================== +llpython.phi_injector +===================== + +.. automodule:: llpython.phi_injector + :members: diff --git a/docs/source/doc/llpython/llpython.pyaddfunc.rst b/docs/source/doc/llpython/llpython.pyaddfunc.rst new file mode 100644 index 0000000..39e0de7 --- /dev/null +++ b/docs/source/doc/llpython/llpython.pyaddfunc.rst @@ -0,0 +1,6 @@ +================== +llpython.pyaddfunc +================== + +.. automodule:: llpython.pyaddfunc + :members: diff --git a/docs/source/doc/llpython/llpython.rst b/docs/source/doc/llpython/llpython.rst new file mode 100644 index 0000000..87fd3d5 --- /dev/null +++ b/docs/source/doc/llpython/llpython.rst @@ -0,0 +1,6 @@ +======== +llpython +======== + +.. automodule:: llpython + :members: diff --git a/docs/source/doc/llpython/nobitey_dev.rst b/docs/source/doc/llpython/nobitey_dev.rst new file mode 100644 index 0000000..be7b4d8 --- /dev/null +++ b/docs/source/doc/llpython/nobitey_dev.rst @@ -0,0 +1,5 @@ +nobitey: Using ctypes and llvmpy to Bypass ctypes +================================================= + +In this article, we show how nobitey uses llvmpy to eliminate the +ctypes call overhead. diff --git a/docs/source/doc/llpython/reference.rst b/docs/source/doc/llpython/reference.rst new file mode 100644 index 0000000..7818100 --- /dev/null +++ b/docs/source/doc/llpython/reference.rst @@ -0,0 +1,21 @@ +LLPython Module Reference +========================= + +Contents: + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + llpython.rst + llpython.bytecode_visitor.rst + llpython.byte_control.rst + llpython.byte_flow.rst + llpython.byte_translator.rst + llpython.bytetype.rst + llpython.control_flow.rst + llpython.gen_bytecode_visitor.rst + llpython.nobitey.rst + llpython.opcode_util.rst + llpython.phi_injector.rst + llpython.pyaddfunc.rst diff --git a/docs/source/doc/llvm.core.Argument.rst b/docs/source/doc/llvm.core.Argument.rst index 2481665..a2ffbfa 100644 --- a/docs/source/doc/llvm.core.Argument.rst +++ b/docs/source/doc/llvm.core.Argument.rst @@ -56,3 +56,10 @@ Add an attribute ``attr`` to the argument, from the set listed above. ~~~~~~~~~~~~~~~~~~~~~~~~~~ Remove the attribute ``attr`` of the argument. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Argument + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.ArrayType.rst b/docs/source/doc/llvm.core.ArrayType.rst index f8b5e0c..3a4e645 100644 --- a/docs/source/doc/llvm.core.ArrayType.rst +++ b/docs/source/doc/llvm.core.ArrayType.rst @@ -28,3 +28,10 @@ A ``Type`` object representing the type of the element of the array. [read-only] The number of elements in the array. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.ArrayType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.BasicBlock.rst b/docs/source/doc/llvm.core.BasicBlock.rst index 74806a6..eb10be3 100644 --- a/docs/source/doc/llvm.core.BasicBlock.rst +++ b/docs/source/doc/llvm.core.BasicBlock.rst @@ -42,3 +42,10 @@ The parent function of this basicblock. ~~~~~~~~~~~~~~~~ A list of instructions in this basicblock. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.BasicBlock + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Builder.rst b/docs/source/doc/llvm.core.Builder.rst index 1e90908..24b9361 100644 --- a/docs/source/doc/llvm.core.Builder.rst +++ b/docs/source/doc/llvm.core.Builder.rst @@ -409,3 +409,10 @@ positioned. ~~~~~~~~~ Deprecated. Same as ``basic_block`` + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Builder + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Constant.rst b/docs/source/doc/llvm.core.Constant.rst index 4f2ed08..3822046 100644 --- a/docs/source/doc/llvm.core.Constant.rst +++ b/docs/source/doc/llvm.core.Constant.rst @@ -4,6 +4,9 @@ | title: Constant (llvm.core) | +-------------------------------+ +llvm.core.Constant +================== + ``Constant``-s represents constants that appear within the code. The values of such objects are known at creation time. Constants can be created from Python constants. A constant expression is also a constant @@ -23,331 +26,338 @@ some examples: tr = Type.float() - r1 = Constant.real(tr, "3.141592") # create from a string r2 = - Constant.real(tr, 1.61803399) # create from a Python float {% - endhighlight %} - - # llvm.core.Constant - - This will become a table of contents (this text will be scraped). - {:toc} - - Static factory methods - ---------------------- - - ``null(ty)`` - ~~~~~~~~~~~~ - - A null value (all zeros) of type ``ty`` - - ``all_ones(ty)`` - ~~~~~~~~~~~~~~~~ - - All 1's value of type ``ty`` - - ``undef(ty)`` - ~~~~~~~~~~~~~ - - An undefined value of type ``ty`` - - ``int(ty, value)`` - ~~~~~~~~~~~~~~~~~~ - - Integer of type ``ty``, with value ``value`` (a Python int or long) - - ``int_signextend(ty, value)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Integer of signed type ``ty`` (use for signed types) - - ``real(ty, value)`` - ~~~~~~~~~~~~~~~~~~~ - - Floating point value of type ``ty``, with value ``value`` (a Python - float) - - ``stringz(value)`` - ~~~~~~~~~~~~~~~~~~ - - A null-terminated string. ``value`` is a Python string - - ``string(value)`` - ~~~~~~~~~~~~~~~~~ - - As ``string(ty)``, but not null terminated - - ``array(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~ - - Array of type ``ty``, initialized with ``consts`` (an iterable yielding - ``Constant`` objects of the appropriate type) - - ``struct(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~~ - - Struct (unpacked) of type ``ty``, initialized with ``consts`` (an - iterable yielding ``Constant`` objects of the appropriate type) - - ``packed_struct(ty, consts)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - As ``struct(ty, consts)`` but packed - - ``vector(consts)`` - ~~~~~~~~~~~~~~~~~~ - - Vector, initialized with ``consts`` (an iterable yielding ``Constant`` - objects of the appropriate type) - - ``sizeof(ty)`` - ~~~~~~~~~~~~~~ - - Constant value representing the sizeof the type ``ty`` - - Methods - ------- - - The following operations on constants are supported. For more details on - any operation, consult the `Constant - Expressions `_ - section of the LLVM Language Reference. - - ``k.neg()`` - ~~~~~~~~~~~ - - negation, same as ``0 - k`` - - ``k.not_()`` - ~~~~~~~~~~~~ - - 1's complement of ``k``. Note trailing underscore. - - ``k.add(k2)`` - ~~~~~~~~~~~~~ - - ``k + k2``, where ``k`` and ``k2`` are integers. - - ``k.fadd(k2)`` - ~~~~~~~~~~~~~~ - - ``k + k2``, where ``k`` and ``k2`` are floating-point. - - ``k.sub(k2)`` - ~~~~~~~~~~~~~ - - ``k - k2``, where ``k`` and ``k2`` are integers. - - ``k.fsub(k2)`` - ~~~~~~~~~~~~~~ - - ``k - k2``, where ``k`` and ``k2`` are floating-point. - - ``k.mul(k2)`` - ~~~~~~~~~~~~~ - - ``k * k2``, where ``k`` and ``k2`` are integers. - - ``k.fmul(k2)`` - ~~~~~~~~~~~~~~ - - ``k * k2``, where ``k`` and ``k2`` are floating-point. - - ``k.udiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of unsigned division of ``k`` with ``k2`` - - ``k.sdiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of signed division of ``k`` with ``k2`` - - ``k.fdiv(k2)`` - ~~~~~~~~~~~~~~ - - Quotient of floating point division of ``k`` with ``k2`` - - ``k.urem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of unsigned division of ``k`` with ``k2`` - - ``k.srem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of signed division of ``k`` with ``k2`` - - ``k.frem(k2)`` - ~~~~~~~~~~~~~~ - - Reminder of floating point division of ``k`` with ``k2`` - - ``k.and_(k2)`` - ~~~~~~~~~~~~~~ - - Bitwise and of ``k`` and ``k2``. Note trailing underscore. - - ``k.or_(k2)`` - ~~~~~~~~~~~~~ - - Bitwise or of ``k`` and ``k2``. Note trailing underscore. - - ``k.xor(k2)`` - ~~~~~~~~~~~~~ - - Bitwise exclusive-or of ``k`` and ``k2``. - - ``k.icmp(icmp, k2)`` - ~~~~~~~~~~~~~~~~~~~~ - - Compare ``k`` with ``k2`` using the predicate ``icmp``. See - `here `_ for list of predicates for integer - operands. - - ``k.fcmp(fcmp, k2)`` - ~~~~~~~~~~~~~~~~~~~~ - - Compare ``k`` with ``k2`` using the predicate ``fcmp``. See - `here `_ for list of predicates for real - operands. - - ``k.shl(k2)`` - ~~~~~~~~~~~~~ - - Shift ``k`` left by ``k2`` bits. - - ``k.lshr(k2)`` - ~~~~~~~~~~~~~~ - - Shift ``k`` logically right by ``k2`` bits (new bits are 0s). - - ``k.ashr(k2)`` - ~~~~~~~~~~~~~~ - - Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as - previous sign bit). - - ``k.gep(indices)`` - ~~~~~~~~~~~~~~~~~~ - - GEP, see `LLVM docs `_. - - ``k.trunc(ty)`` - ~~~~~~~~~~~~~~~ - - Truncate ``k`` to a type ``ty`` of lower bitwidth. - - ``k.sext(ty)`` - ~~~~~~~~~~~~~~ - - Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending - the sign bit. - - ``k.zext(ty)`` - ~~~~~~~~~~~~~~ - - Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are - 0s. - - ``k.fptrunc(ty)`` - ~~~~~~~~~~~~~~~~~ - - Truncate floating point constant ``k`` to floating point type ``ty`` of - lower size than k's. - - ``k.fpext(ty)`` - ~~~~~~~~~~~~~~~ - - Extend floating point constant ``k`` to floating point type ``ty`` of - higher size than k's. - - ``k.uitofp(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert an unsigned integer constant ``k`` to floating point constant of - type ``ty``. - - ``k.sitofp(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a signed integer constant ``k`` to floating point constant of - type ``ty``. - - ``k.fptoui(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a floating point constant ``k`` to an unsigned integer constant - of type ``ty``. - - ``k.fptosi(ty)`` - ~~~~~~~~~~~~~~~~ - - Convert a floating point constant ``k`` to a signed integer constant of - type ``ty``. - - ``k.ptrtoint(ty)`` - ~~~~~~~~~~~~~~~~~~ - - Convert a pointer constant ``k`` to an integer constant of type ``ty``. - - ``k.inttoptr(ty)`` - ~~~~~~~~~~~~~~~~~~ - - Convert an integer constant ``k`` to a pointer constant of type ``ty``. - - ``k.bitcast(ty)`` - ~~~~~~~~~~~~~~~~~ - - Convert ``k`` to a (equal-width) constant of type ``ty``. - - ``k.select(cond,k2,k3)`` - ~~~~~~~~~~~~~~~~~~~~~~~~ - - Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1, - else with ``k3``. - - ``k.extract_element(idx)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Extract value at ``idx`` (integer constant) from a vector constant - ``k``. - - ``k.insert_element(k2,idx)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Insert value ``k2`` (scalar constant) at index ``idx`` (integer - constant) of vector constant ``k``. - - ``k.shuffle_vector(k2,mask)`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Shuffle vector constant ``k`` based on vector constants ``k2`` and - ``mask``. - - -------------- - - # Other Constant Classes - The following subclasses of ``Constant`` do not provide additional - methods, **they serve only to provide richer type information.** - - Subclass \| LLVM C++ Class \| Remarks \| - ---------\|----------------\|---------\| ``ConstantExpr`` \| - ``llvmConstantExpr`` \| A constant expression \| - ``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero - constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer - constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point - constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array - constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A - structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \| - A vector constant \| ``ConstantPointerNull``\ \| - ``llvmConstantPointerNull``\ \| All-zero pointer constant \| - ``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of - LLVM IR \| - - These types are helpful in ``isinstance`` checks, like so: - - {% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) # - int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = { - k1, k1 }; - - assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray) - + r1 = Constant.real(tr, "3.141592") # create from a string + r2 = Constant.real(tr, 1.61803399) # create from a Python float + + +# llvm.core.Constant +- This will become a table of contents (this text will be scraped). +{:toc} + + +Static factory methods +---------------------- + +``null(ty)`` +~~~~~~~~~~~~ + +A null value (all zeros) of type ``ty`` + +``all_ones(ty)`` +~~~~~~~~~~~~~~~~ + +All 1's value of type ``ty`` + +``undef(ty)`` +~~~~~~~~~~~~~ + +An undefined value of type ``ty`` + +``int(ty, value)`` +~~~~~~~~~~~~~~~~~~ + +Integer of type ``ty``, with value ``value`` (a Python int or long) + +``int_signextend(ty, value)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Integer of signed type ``ty`` (use for signed types) + +``real(ty, value)`` +~~~~~~~~~~~~~~~~~~~ + +Floating point value of type ``ty``, with value ``value`` (a Python +float) + +``stringz(value)`` +~~~~~~~~~~~~~~~~~~ + +A null-terminated string. ``value`` is a Python string + +``string(value)`` +~~~~~~~~~~~~~~~~~ + +As ``string(ty)``, but not null terminated + +``array(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~ + +Array of type ``ty``, initialized with ``consts`` (an iterable yielding +``Constant`` objects of the appropriate type) + +``struct(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~~ + +Struct (unpacked) of type ``ty``, initialized with ``consts`` (an +iterable yielding ``Constant`` objects of the appropriate type) + +``packed_struct(ty, consts)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As ``struct(ty, consts)`` but packed + +``vector(consts)`` +~~~~~~~~~~~~~~~~~~ + +Vector, initialized with ``consts`` (an iterable yielding ``Constant`` +objects of the appropriate type) + +``sizeof(ty)`` +~~~~~~~~~~~~~~ + +Constant value representing the sizeof the type ``ty`` + +Methods +------- + +The following operations on constants are supported. For more details on +any operation, consult the `Constant +Expressions `_ +section of the LLVM Language Reference. + +``k.neg()`` +~~~~~~~~~~~ + +negation, same as ``0 - k`` + +``k.not_()`` +~~~~~~~~~~~~ + +1's complement of ``k``. Note trailing underscore. + +``k.add(k2)`` +~~~~~~~~~~~~~ + +``k + k2``, where ``k`` and ``k2`` are integers. + +``k.fadd(k2)`` +~~~~~~~~~~~~~~ + +``k + k2``, where ``k`` and ``k2`` are floating-point. + +``k.sub(k2)`` +~~~~~~~~~~~~~ + +``k - k2``, where ``k`` and ``k2`` are integers. + +``k.fsub(k2)`` +~~~~~~~~~~~~~~ + +``k - k2``, where ``k`` and ``k2`` are floating-point. + +``k.mul(k2)`` +~~~~~~~~~~~~~ + +``k * k2``, where ``k`` and ``k2`` are integers. + +``k.fmul(k2)`` +~~~~~~~~~~~~~~ + +``k * k2``, where ``k`` and ``k2`` are floating-point. + +``k.udiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of unsigned division of ``k`` with ``k2`` + +``k.sdiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of signed division of ``k`` with ``k2`` + +``k.fdiv(k2)`` +~~~~~~~~~~~~~~ + +Quotient of floating point division of ``k`` with ``k2`` + +``k.urem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of unsigned division of ``k`` with ``k2`` + +``k.srem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of signed division of ``k`` with ``k2`` + +``k.frem(k2)`` +~~~~~~~~~~~~~~ + +Reminder of floating point division of ``k`` with ``k2`` + +``k.and_(k2)`` +~~~~~~~~~~~~~~ + +Bitwise and of ``k`` and ``k2``. Note trailing underscore. + +``k.or_(k2)`` +~~~~~~~~~~~~~ + +Bitwise or of ``k`` and ``k2``. Note trailing underscore. + +``k.xor(k2)`` +~~~~~~~~~~~~~ + +Bitwise exclusive-or of ``k`` and ``k2``. + +``k.icmp(icmp, k2)`` +~~~~~~~~~~~~~~~~~~~~ + +Compare ``k`` with ``k2`` using the predicate ``icmp``. See +`here `_ for list of predicates for integer +operands. + +``k.fcmp(fcmp, k2)`` +~~~~~~~~~~~~~~~~~~~~ + +Compare ``k`` with ``k2`` using the predicate ``fcmp``. See +`here `_ for list of predicates for real +operands. + +``k.shl(k2)`` +~~~~~~~~~~~~~ + +Shift ``k`` left by ``k2`` bits. + +``k.lshr(k2)`` +~~~~~~~~~~~~~~ + +Shift ``k`` logically right by ``k2`` bits (new bits are 0s). + +``k.ashr(k2)`` +~~~~~~~~~~~~~~ + +Shift ``k`` arithmetically right by ``k2`` bits (new bits are same as +previous sign bit). + +``k.gep(indices)`` +~~~~~~~~~~~~~~~~~~ + +GEP, see `LLVM docs `_. + +``k.trunc(ty)`` +~~~~~~~~~~~~~~~ + +Truncate ``k`` to a type ``ty`` of lower bitwidth. + +``k.sext(ty)`` +~~~~~~~~~~~~~~ + +Sign extend ``k`` to a type ``ty`` of higher bitwidth, while extending +the sign bit. + +``k.zext(ty)`` +~~~~~~~~~~~~~~ + +Sign extend ``k`` to a type ``ty`` of higher bitwidth, all new bits are +0s. + +``k.fptrunc(ty)`` +~~~~~~~~~~~~~~~~~ + +Truncate floating point constant ``k`` to floating point type ``ty`` of +lower size than k's. + +``k.fpext(ty)`` +~~~~~~~~~~~~~~~ + +Extend floating point constant ``k`` to floating point type ``ty`` of +higher size than k's. + +``k.uitofp(ty)`` +~~~~~~~~~~~~~~~~ + +Convert an unsigned integer constant ``k`` to floating point constant of +type ``ty``. + +``k.sitofp(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a signed integer constant ``k`` to floating point constant of +type ``ty``. + +``k.fptoui(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a floating point constant ``k`` to an unsigned integer constant +of type ``ty``. + +``k.fptosi(ty)`` +~~~~~~~~~~~~~~~~ + +Convert a floating point constant ``k`` to a signed integer constant of +type ``ty``. + +``k.ptrtoint(ty)`` +~~~~~~~~~~~~~~~~~~ + +Convert a pointer constant ``k`` to an integer constant of type ``ty``. + +``k.inttoptr(ty)`` +~~~~~~~~~~~~~~~~~~ + +Convert an integer constant ``k`` to a pointer constant of type ``ty``. + +``k.bitcast(ty)`` +~~~~~~~~~~~~~~~~~ + +Convert ``k`` to a (equal-width) constant of type ``ty``. + +``k.select(cond,k2,k3)`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +Replace value with ``k2`` if the 1-bit integer constant ``cond`` is 1, +else with ``k3``. + +``k.extract_element(idx)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Extract value at ``idx`` (integer constant) from a vector constant +``k``. + +``k.insert_element(k2,idx)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Insert value ``k2`` (scalar constant) at index ``idx`` (integer +constant) of vector constant ``k``. + +``k.shuffle_vector(k2,mask)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Shuffle vector constant ``k`` based on vector constants ``k2`` and +``mask``. + +-------------- + +# Other Constant Classes +The following subclasses of ``Constant`` do not provide additional +methods, **they serve only to provide richer type information.** + +Subclass \| LLVM C++ Class \| Remarks \| +---------\|----------------\|---------\| ``ConstantExpr`` \| +``llvmConstantExpr`` \| A constant expression \| +``ConstantAggregateZero``\ \| ``llvmConstantAggregateZero``\ \| All-zero +constant \| ``ConstantInt``\ \| ``llvmConstantInt``\ \| An integer +constant \| ``ConstantFP``\ \| ``llvmConstantFP``\ \| A floating-point +constant \| ``ConstantArray``\ \| ``llvmConstantArray``\ \| An array +constant \| ``ConstantStruct``\ \| ``llvmConstantStruct``\ \| A +structure constant \| ``ConstantVector``\ \| ``llvmConstantVector``\ \| +A vector constant \| ``ConstantPointerNull``\ \| +``llvmConstantPointerNull``\ \| All-zero pointer constant \| +``UndefValue``\ \| ``llvmUndefValue``\ \| corresponds to ``undef`` of +LLVM IR \| + +These types are helpful in ``isinstance`` checks, like so: + +{% highlight python %} ti = Type.int(32) k1 = Constant.int(ti, 42) # +int32_t k1 = 42; k2 = Constant.array(ti, [k1, k1]) # int32_t k2[] = { +k1, k1 }; + +assert isinstance(k1, ConstantInt) assert isinstance(k2, ConstantArray) + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Constant + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Function.rst b/docs/source/doc/llvm.core.Function.rst index 1d6070c..cda101e 100644 --- a/docs/source/doc/llvm.core.Function.rst +++ b/docs/source/doc/llvm.core.Function.rst @@ -149,3 +149,10 @@ function bodies. Verifies the function. See `LLVM docs `_. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Function + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.FunctionType.rst b/docs/source/doc/llvm.core.FunctionType.rst index 8d40009..7b728a8 100644 --- a/docs/source/doc/llvm.core.FunctionType.rst +++ b/docs/source/doc/llvm.core.FunctionType.rst @@ -46,3 +46,10 @@ the function. Used like this: Type.int(), Type.int() ] ) for arg in func_type.args: assert arg.kind == TYPE_INTEGER assert arg == Type.int() assert func_type.arg_count == len(func_type.args) + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.FunctionType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.GlobalValue.rst b/docs/source/doc/llvm.core.GlobalValue.rst index 70dee7b..a5c2383 100644 --- a/docs/source/doc/llvm.core.GlobalValue.rst +++ b/docs/source/doc/llvm.core.GlobalValue.rst @@ -95,3 +95,9 @@ A power-of-2 integer indicating the boundary to align to. The module object to which this global belongs to. + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.GlobalValue + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.GlobalVariable.rst b/docs/source/doc/llvm.core.GlobalVariable.rst index 392a6a0..1ba69d8 100644 --- a/docs/source/doc/llvm.core.GlobalVariable.rst +++ b/docs/source/doc/llvm.core.GlobalVariable.rst @@ -4,6 +4,9 @@ | title: GlobalVariable (llvm.core) | +-------------------------------------+ +llvm.core.GlobalVariable +======================== + Global variables (``llvm.core.GlobalVariable``) are subclasses of `llvm.core.GlobalValue `_ and represent module-level variables. These can have optional initializers and can be @@ -37,3 +40,10 @@ class, or by using the static method ``GlobalVariable.new``. # list all global variables in a module for gv in module_obj.global_variables: print gv.name, "of type", gv.type + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.GlobalVariable + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Instruction.rst b/docs/source/doc/llvm.core.Instruction.rst index 95aeb81..67c43f0 100644 --- a/docs/source/doc/llvm.core.Instruction.rst +++ b/docs/source/doc/llvm.core.Instruction.rst @@ -240,3 +240,10 @@ Properties The predicate of the compare instruction, one of the ``ICMP_*`` or ``FCMP_*`` constants. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Instruction + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.IntegerType.rst b/docs/source/doc/llvm.core.IntegerType.rst index f62907c..6f1e2b1 100644 --- a/docs/source/doc/llvm.core.IntegerType.rst +++ b/docs/source/doc/llvm.core.IntegerType.rst @@ -21,3 +21,10 @@ Properties [read-only] The width of the integer type, in number of bits. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.IntegerType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Module.rst b/docs/source/doc/llvm.core.Module.rst index 3dbd5c8..75cc174 100644 --- a/docs/source/doc/llvm.core.Module.rst +++ b/docs/source/doc/llvm.core.Module.rst @@ -4,16 +4,26 @@ | title: Module (llvm.core) | +-----------------------------+ +llvm.core.Module +================ + Modules are top-level container objects. You need to create a module object first, before you can add global variables, aliases or functions. Modules are created using the static method ``Module.new``: - .. code-block:: python #!/usr/bin/env python - from llvm import \* from llvm.core import \* + from llvm import * + from llvm.core import * # create a module my_module = Module.new('my_module') + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Module + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.PointerType.rst b/docs/source/doc/llvm.core.PointerType.rst index a869fba..cc65139 100644 --- a/docs/source/doc/llvm.core.PointerType.rst +++ b/docs/source/doc/llvm.core.PointerType.rst @@ -29,3 +29,10 @@ The address space of the pointer. A `Type `_ object representing the type of the value pointed to. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.PointerType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.StructType.rst b/docs/source/doc/llvm.core.StructType.rst index e69de29..f3b0786 100644 --- a/docs/source/doc/llvm.core.StructType.rst +++ b/docs/source/doc/llvm.core.StructType.rst @@ -0,0 +1,8 @@ +llvm.core.StructType +==================== + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.StructType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Type.rst b/docs/source/doc/llvm.core.Type.rst index 58883d7..b1eb354 100644 --- a/docs/source/doc/llvm.core.Type.rst +++ b/docs/source/doc/llvm.core.Type.rst @@ -126,3 +126,10 @@ Example: assert Type.int().kind == TYPE_INTEGER assert Type.void().kind == TYPE_VOID + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Type + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.User.rst b/docs/source/doc/llvm.core.User.rst index 0762729..12d40c5 100644 --- a/docs/source/doc/llvm.core.User.rst +++ b/docs/source/doc/llvm.core.User.rst @@ -37,3 +37,10 @@ The list of operands (values, of type The number of operands that this value referes to. Same as ``len(uses.operands)`` but faster if you just want the count. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.User + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.Value.rst b/docs/source/doc/llvm.core.Value.rst index fdff4cc..081d328 100644 --- a/docs/source/doc/llvm.core.Value.rst +++ b/docs/source/doc/llvm.core.Value.rst @@ -63,3 +63,10 @@ representation. ``Value`` objects can be compared for equality. Internally, this converts both arguments into their LLVM assembly representations and compares the resultant strings. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.Value + :members: + :undoc-members: diff --git a/docs/source/doc/llvm.core.VectorType.rst b/docs/source/doc/llvm.core.VectorType.rst index 19b98e6..a18f6ea 100644 --- a/docs/source/doc/llvm.core.VectorType.rst +++ b/docs/source/doc/llvm.core.VectorType.rst @@ -29,3 +29,10 @@ element of the vector. [read-only] The number of elements in the vector. + + +Automatically Generated Documentation +------------------------------------- +.. autoclass:: llvm.core.VectorType + :members: + :undoc-members: diff --git a/docs/source/doc/llvm_cbuilder.rst b/docs/source/doc/llvm_cbuilder.rst new file mode 100644 index 0000000..c8623c2 --- /dev/null +++ b/docs/source/doc/llvm_cbuilder.rst @@ -0,0 +1,12 @@ +llvm_cbuilder +============= + +llvm_cbuilder is a set of Python-contexts you can use to write C-like +constructs in Python which generates llvmpy code directly. + +Similar to llpython it allows you to build llvm IR without using the +llvmpy interface directly. + +Look in the llvm_cbuilder tests directory for examples of use. + + diff --git a/docs/source/doc/llvm_concepts.rst b/docs/source/doc/llvm_concepts.rst index c642994..8690e49 100644 --- a/docs/source/doc/llvm_concepts.rst +++ b/docs/source/doc/llvm_concepts.rst @@ -28,6 +28,7 @@ follow these steps: - add a *basic block* to the function - using a helper object called an *instruction builder*, add two instructions into the basic block: + - an instruction to add the two arguments and store the result into a temporary variable - a return diff --git a/docs/source/doc/llvmcore.rst b/docs/source/doc/llvmcore.rst new file mode 100644 index 0000000..a3b94b6 --- /dev/null +++ b/docs/source/doc/llvmcore.rst @@ -0,0 +1,9 @@ +******************************** +llvm.core +******************************** + +.. toctree:: + :titlesonly: + :glob: + + llvm.core.* \ No newline at end of file diff --git a/docs/source/doc/llvmee.rst b/docs/source/doc/llvmee.rst new file mode 100644 index 0000000..2145502 --- /dev/null +++ b/docs/source/doc/llvmee.rst @@ -0,0 +1,9 @@ +******************************** +llvm.ee +******************************** + +.. toctree:: + :titlesonly: + :glob: + + llvm.ee.* \ No newline at end of file diff --git a/docs/source/doc/llvmpasses.rst b/docs/source/doc/llvmpasses.rst new file mode 100644 index 0000000..0931467 --- /dev/null +++ b/docs/source/doc/llvmpasses.rst @@ -0,0 +1,9 @@ +******************************** +llvm.passes +******************************** + +.. toctree:: + :titlesonly: + :glob: + + llvm.passes.* \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index fbca2ec..fbf5c8b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -3,8 +3,8 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Documentation for llvmpy -================= +llvmpy +====== Contents: @@ -13,11 +13,16 @@ Contents: :maxdepth: 2 doc/userguide.rst + doc/llvm_cbuilder.rst + doc/llpython/index.rst doc/examples.rst + doc/llvmcore.rst + doc/llvmee.rst + doc/llvmpasses.rst Indices and tables -================== +------------------ * :ref:`genindex` * :ref:`modindex` diff --git a/example/vector_instr.py b/example/vector_instr.py new file mode 100644 index 0000000..e49d06a --- /dev/null +++ b/example/vector_instr.py @@ -0,0 +1,152 @@ +''' +This example shows: +1) how to use vector instructions +2) how to take advantage of LLVM loop vectorization to transform scalar + operations to vector operations +''' + +from __future__ import print_function +import llvm.core as lc +import llvm.ee as le +import llvm.passes as lp +from ctypes import CFUNCTYPE, POINTER, c_int, c_float + +def build_manual_vector(): + mod = lc.Module.new('manual.vector') + intty = lc.Type.int(32) + vecty = lc.Type.vector(lc.Type.float(), 4) + aryty = lc.Type.pointer(lc.Type.float()) + fnty = lc.Type.function(lc.Type.void(), [aryty, aryty, aryty, intty]) + fn = mod.add_function(fnty, name='vector_add') + bbentry = fn.append_basic_block('entry') + bbloopcond = fn.append_basic_block('loop.cond') + bbloopbody = fn.append_basic_block('loop.body') + bbexit = fn.append_basic_block('exit') + builder = lc.Builder.new(bbentry) + + # populate function body + in1, in2, out, size = fn.args + ZERO = lc.Constant.null(intty) + loopi_ptr = builder.alloca(intty) + builder.store(ZERO, loopi_ptr) + + builder.branch(bbloopcond) + builder.position_at_end(bbloopcond) + + loopi = builder.load(loopi_ptr) + loopcond = builder.icmp(lc.ICMP_ULT, loopi, size) + + builder.cbranch(loopcond, bbloopbody, bbexit) + builder.position_at_end(bbloopbody) + + vecaryty = lc.Type.pointer(vecty) + in1asvec = builder.bitcast(builder.gep(in1, [loopi]), vecaryty) + in2asvec = builder.bitcast(builder.gep(in2, [loopi]), vecaryty) + outasvec = builder.bitcast(builder.gep(out, [loopi]), vecaryty) + + vec1 = builder.load(in1asvec) + vec2 = builder.load(in2asvec) + + vecout = builder.fadd(vec1, vec2) + + builder.store(vecout, outasvec) + + next = builder.add(loopi, lc.Constant.int(intty, 4)) + builder.store(next, loopi_ptr) + + builder.branch(bbloopcond) + builder.position_at_end(bbexit) + + builder.ret_void() + + return mod, fn + + +def build_auto_vector(): + mod = lc.Module.new('auto.vector') + # Loop vectorize is sensitive to the size of the index size(!?) + intty = lc.Type.int(tuple.__itemsize__ * 8) + aryty = lc.Type.pointer(lc.Type.float()) + fnty = lc.Type.function(lc.Type.void(), [aryty, aryty, aryty, intty]) + fn = mod.add_function(fnty, name='vector_add') + bbentry = fn.append_basic_block('entry') + bbloopcond = fn.append_basic_block('loop.cond') + bbloopbody = fn.append_basic_block('loop.body') + bbexit = fn.append_basic_block('exit') + builder = lc.Builder.new(bbentry) + + # populate function body + in1, in2, out, size = fn.args + in1.add_attribute(lc.ATTR_NO_ALIAS) + in2.add_attribute(lc.ATTR_NO_ALIAS) + out.add_attribute(lc.ATTR_NO_ALIAS) + ZERO = lc.Constant.null(intty) + loopi_ptr = builder.alloca(intty) + builder.store(ZERO, loopi_ptr) + + builder.branch(bbloopcond) + builder.position_at_end(bbloopcond) + + loopi = builder.load(loopi_ptr) + loopcond = builder.icmp(lc.ICMP_ULT, loopi, size) + + builder.cbranch(loopcond, bbloopbody, bbexit) + builder.position_at_end(bbloopbody) + + in1elem = builder.load(builder.gep(in1, [loopi])) + in2elem = builder.load(builder.gep(in2, [loopi])) + + outelem = builder.fadd(in1elem, in2elem) + + builder.store(outelem, builder.gep(out, [loopi])) + + next = builder.add(loopi, lc.Constant.int(intty, 1)) + builder.store(next, loopi_ptr) + + builder.branch(bbloopcond) + builder.position_at_end(bbexit) + + builder.ret_void() + + return mod, fn + +def example(title, module_builder, opt): + print(title.center(80, '=')) + mod, fn = module_builder() + + eb = le.EngineBuilder.new(mod).opt(3) + if opt: + print('opt') + tm = eb.select_target() + pms = lp.build_pass_managers(mod=mod, tm=tm, opt=3, loop_vectorize=True, + fpm=False) + pms.pm.run(mod) + + print(mod) + print(mod.to_native_assembly()) + + engine = eb.create() + ptr = engine.get_pointer_to_function(fn) + + callable = CFUNCTYPE(None, POINTER(c_float), POINTER(c_float), + POINTER(c_float), c_int)(ptr) + + N = 20 + in1 = (c_float * N)(*range(N)) + in2 = (c_float * N)(*range(N)) + out = (c_float * N)() + + print('in1: ', list(in1)) + print('in1: ', list(in2)) + + callable(in1, in2, out, N) + + print('out', list(out)) + + +def main(): + example('manual vector function', build_manual_vector, False) + example('auto vector function', build_auto_vector, True) + +if __name__ == '__main__': + main() diff --git a/llpython/__init__.py b/llpython/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llpython/byte_control.py b/llpython/byte_control.py new file mode 100644 index 0000000..8ca407e --- /dev/null +++ b/llpython/byte_control.py @@ -0,0 +1,125 @@ +# ______________________________________________________________________ +from __future__ import absolute_import +import opcode +from . import opcode_util +import pprint + +from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin +from .control_flow import ControlFlowGraph + +# ______________________________________________________________________ + +class ControlFlowBuilder (BenignBytecodeVisitorMixin, BasicBlockVisitor): + '''Visitor responsible for traversing a bytecode basic block map and + building a control flow graph (CFG). + + The primary purpose of this transformation is to create a CFG, + which is used by later transformers for dataflow analysis. + ''' + def visit (self, flow, nargs = 0, *args, **kws): + '''Given a bytecode flow, and an optional number of arguments, + return a :py:class:`llpython.control_flow.ControlFlowGraph` + instance describing the full control flow of the bytecode + flow.''' + self.nargs = nargs + ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws) + del self.nargs + return ret_val + + def enter_blocks (self, blocks): + super(ControlFlowBuilder, self).enter_blocks(blocks) + self.blocks = blocks + self.block_list = list(blocks.keys()) + self.block_list.sort() + self.cfg = ControlFlowGraph() + self.loop_stack = [] + for block in self.block_list: + self.cfg.add_block(block, blocks[block]) + + def exit_blocks (self, blocks): + super(ControlFlowBuilder, self).exit_blocks(blocks) + assert self.blocks == blocks + self.cfg.compute_dataflow() + self.cfg.update_for_ssa() + ret_val = self.cfg + del self.loop_stack + del self.cfg + del self.block_list + del self.blocks + return ret_val + + def enter_block (self, block): + self.block = block + assert block in self.cfg.blocks + if block == 0: + for local_index in range(self.nargs): + self.op_STORE_FAST(0, opcode.opmap['STORE_FAST'], local_index) + return True + + def _get_next_block (self, block): + return self.block_list[self.block_list.index(block) + 1] + + def exit_block (self, block): + assert block == self.block + del self.block + i, op, arg = self.blocks[block][-1] + opname = opcode.opname[op] + if op in opcode.hasjabs: + self.cfg.add_edge(block, arg) + elif op in opcode.hasjrel: + self.cfg.add_edge(block, i + arg + 3) + elif opname == 'BREAK_LOOP': + loop_i, _, loop_arg = self.loop_stack[-1] + self.cfg.add_edge(block, loop_i + loop_arg + 3) + elif opname != 'RETURN_VALUE': + self.cfg.add_edge(block, self._get_next_block(block)) + if op in opcode_util.hascbranch: + self.cfg.add_edge(block, self._get_next_block(block)) + + def op_LOAD_FAST (self, i, op, arg, *args, **kws): + self.cfg.blocks_reads[self.block].add(arg) + return super(ControlFlowBuilder, self).op_LOAD_FAST(i, op, arg, *args, + **kws) + + def op_STORE_FAST (self, i, op, arg, *args, **kws): + self.cfg.writes_local(self.block, i, arg) + return super(ControlFlowBuilder, self).op_STORE_FAST(i, op, arg, *args, + **kws) + + def op_SETUP_LOOP (self, i, op, arg, *args, **kws): + self.loop_stack.append((i, op, arg)) + return super(ControlFlowBuilder, self).op_SETUP_LOOP(i, op, arg, *args, + **kws) + + def op_POP_BLOCK (self, i, op, arg, *args, **kws): + self.loop_stack.pop() + return super(ControlFlowBuilder, self).op_POP_BLOCK(i, op, arg, *args, + **kws) + +# ______________________________________________________________________ + +def build_cfg (func): + '''Given a Python function, create a bytecode flow, visit the flow + object, and return a control flow graph.''' + co_obj = opcode_util.get_code_object(func) + return ControlFlowBuilder().visit(opcode_util.build_basic_blocks(co_obj), + co_obj.co_argcount) + +# ______________________________________________________________________ +# Main (self-test) routine + +def main (*args, **kws): + from tests import llfuncs + if not args: + args = ('doslice',) + for arg in args: + build_cfg(getattr(llfuncs, arg)).pprint() + +# ______________________________________________________________________ + +if __name__ == "__main__": + import sys + main(*sys.argv[1:]) + +# ______________________________________________________________________ +# End of byte_control.py diff --git a/llpython/byte_flow.py b/llpython/byte_flow.py new file mode 100644 index 0000000..197c839 --- /dev/null +++ b/llpython/byte_flow.py @@ -0,0 +1,266 @@ +# ______________________________________________________________________ +from __future__ import absolute_import +import dis +import opcode + +from .bytecode_visitor import BasicBlockVisitor +from . import opcode_util + +# ______________________________________________________________________ + +class BytecodeFlowBuilder (BasicBlockVisitor): + '''Transforms a CFG into a bytecode "flow tree". + + The flow tree is a Python dictionary, described loosely by the + following set of productions: + + * `flow_tree` ``:=`` ``{`` `blocks` ``*`` ``}`` + * `blocks` ``:=`` `block_index` ``:`` ``[`` `bytecode_tree` ``*`` ``]`` + * `bytecode_tree` ``:=`` ``(`` `opcode_index` ``,`` `opcode` ``,`` + `opname` ``,`` `arg` ``,`` ``[`` `bytecode_tree` ``*`` ``]`` ``)`` + + The primary purpose of this transformation is to simulate the + value stack, removing it and any stack-specific opcodes.''' + + def __init__ (self, *args, **kws): + super(BytecodeFlowBuilder, self).__init__(*args, **kws) + om_items = opcode_util.OPCODE_MAP.items() + self.opmap = dict((opcode.opmap[opname], (opname, pops, pushes, stmt)) + for opname, (pops, pushes, stmt) in om_items + if opname in opcode.opmap) + + def _visit_op (self, i, op, arg, opname, pops, pushes, appends): + assert pops is not None, ('%s not well defined in opcode_util.' + 'OPCODE_MAP' % opname) + if pops: + if pops < 0: + pops = arg - pops - 1 + assert pops <= len(self.stack), ("Stack underflow at instruction " + "%d (%s)!" % (i, opname)) + stk_args = self.stack[-pops:] + del self.stack[-pops:] + else: + stk_args = [] + ret_val = (i, op, opname, arg, stk_args) + if pushes: + self.stack.append(ret_val) + if appends: + self.block.append(ret_val) + return ret_val + + def _op (self, i, op, arg): + opname, pops, pushes, appends = self.opmap[op] + return self._visit_op(i, op, arg, opname, pops, pushes, appends) + + def visit_cfg (self, cfg): + self.cfg = cfg + ret_val = self.visit(cfg.blocks) + del self.cfg + return ret_val + + def enter_blocks (self, blocks): + labels = list(blocks.keys()) + labels.sort() + self.blocks = dict((index, []) + for index in labels) + self.loop_stack = [] + self.stacks = {} + + def exit_blocks (self, blocks): + ret_val = self.blocks + del self.stacks + del self.loop_stack + del self.blocks + return ret_val + + def enter_block (self, block): + self.block_no = block + self.block = self.blocks[block] + in_blocks = self.cfg.blocks_in[block] + if len(in_blocks) == 0: + self.stack = [] + else: + pred_stack = None + for pred in in_blocks: + if pred in self.stacks: + pred_stack = self.stacks[pred] + break + if pred_stack is not None: + self.stack = pred_stack[:] + else: + raise NotImplementedError() + + def exit_block (self, block): + assert self.block_no == block + self.stacks[block] = self.stack + del self.stack + del self.block + del self.block_no + + op_BINARY_ADD = _op + op_BINARY_AND = _op + op_BINARY_DIVIDE = _op + op_BINARY_FLOOR_DIVIDE = _op + op_BINARY_LSHIFT = _op + op_BINARY_MODULO = _op + op_BINARY_MULTIPLY = _op + op_BINARY_OR = _op + op_BINARY_POWER = _op + op_BINARY_RSHIFT = _op + op_BINARY_SUBSCR = _op + op_BINARY_SUBTRACT = _op + op_BINARY_TRUE_DIVIDE = _op + op_BINARY_XOR = _op + + def op_BREAK_LOOP (self, i, op, arg): + loop_i, _, loop_arg = self.loop_stack[-1] + assert arg is None + return self._op(i, op, loop_i + loop_arg + 3) + + #op_BUILD_CLASS = _op + op_BUILD_LIST = _op + op_BUILD_MAP = _op + op_BUILD_SLICE = _op + op_BUILD_TUPLE = _op + op_CALL_FUNCTION = _op + op_CALL_FUNCTION_KW = _op + op_CALL_FUNCTION_VAR = _op + op_CALL_FUNCTION_VAR_KW = _op + op_COMPARE_OP = _op + #op_CONTINUE_LOOP = _op + op_DELETE_ATTR = _op + op_DELETE_FAST = _op + op_DELETE_GLOBAL = _op + op_DELETE_NAME = _op + op_DELETE_SLICE = _op + op_DELETE_SUBSCR = _op + + def op_DUP_TOP (self, i, op, arg): + self.stack.append(self.stack[-1]) + + def op_DUP_TOPX (self, i, op, arg): + self.stack += self.stack[-arg:] + + #op_END_FINALLY = _op + op_EXEC_STMT = _op + #op_EXTENDED_ARG = _op + op_FOR_ITER = _op + op_GET_ITER = _op + op_IMPORT_FROM = _op + op_IMPORT_NAME = _op + op_IMPORT_STAR = _op + op_INPLACE_ADD = _op + op_INPLACE_AND = _op + op_INPLACE_DIVIDE = _op + op_INPLACE_FLOOR_DIVIDE = _op + op_INPLACE_LSHIFT = _op + op_INPLACE_MODULO = _op + op_INPLACE_MULTIPLY = _op + op_INPLACE_OR = _op + op_INPLACE_POWER = _op + op_INPLACE_RSHIFT = _op + op_INPLACE_SUBTRACT = _op + op_INPLACE_TRUE_DIVIDE = _op + op_INPLACE_XOR = _op + op_JUMP_ABSOLUTE = _op + op_JUMP_FORWARD = _op + + def op_JUMP_IF_FALSE (self, i, op, arg): + opname, _, _, _ = self.opmap[op] + ret_val = (i, op, opname, arg, [self.stack[-1]]) + self.block.append(ret_val) + return ret_val + + op_JUMP_IF_TRUE = op_JUMP_IF_FALSE + op_LIST_APPEND = _op + op_LOAD_ATTR = _op + op_LOAD_CLOSURE = _op + op_LOAD_CONST = _op + op_LOAD_DEREF = _op + op_LOAD_FAST = _op + op_LOAD_GLOBAL = _op + op_LOAD_LOCALS = _op + op_LOAD_NAME = _op + op_MAKE_CLOSURE = _op + op_MAKE_FUNCTION = _op + op_NOP = _op + + def op_POP_BLOCK (self, i, op, arg): + self.loop_stack.pop() + return self._op(i, op, arg) + + op_POP_JUMP_IF_FALSE = _op + op_POP_JUMP_IF_TRUE = _op + op_POP_TOP = _op + op_PRINT_EXPR = _op + op_PRINT_ITEM = _op + op_PRINT_ITEM_TO = _op + op_PRINT_NEWLINE = _op + op_PRINT_NEWLINE_TO = _op + op_RAISE_VARARGS = _op + op_RETURN_VALUE = _op + + def op_ROT_FOUR (self, i, op, arg): + self.stack[-4:] = (self.stack[-1], self.stack[-4], self.stack[-3], + self.stack[-2]) + + def op_ROT_THREE (self, i, op, arg): + self.stack[-3:] = (self.stack[-1], self.stack[-3], self.stack[-2]) + + def op_ROT_TWO (self, i, op, arg): + self.stack[-2:] = (self.stack[-1], self.stack[-2]) + + #op_SETUP_EXCEPT = _op + #op_SETUP_FINALLY = _op + + def op_SETUP_LOOP (self, i, op, arg): + self.loop_stack.append((i, op, arg)) + self.block.append((i, op, self.opnames[op], arg, [])) + + op_SLICE = _op + #op_STOP_CODE = _op + op_STORE_ATTR = _op + op_STORE_DEREF = _op + op_STORE_FAST = _op + op_STORE_GLOBAL = _op + op_STORE_MAP = _op + op_STORE_NAME = _op + op_STORE_SLICE = _op + op_STORE_SUBSCR = _op + op_UNARY_CONVERT = _op + op_UNARY_INVERT = _op + op_UNARY_NEGATIVE = _op + op_UNARY_NOT = _op + op_UNARY_POSITIVE = _op + op_UNPACK_SEQUENCE = _op + #op_WITH_CLEANUP = _op + op_YIELD_VALUE = _op + +# ______________________________________________________________________ + +def build_flow (func): + '''Given a Python function, return a bytecode flow tree for that + function.''' + import byte_control + cfg = byte_control.build_cfg(func) + return BytecodeFlowBuilder().visit_cfg(cfg) + +# ______________________________________________________________________ +# Main (self-test) routine + +def main (*args): + import pprint + from tests import llfuncs + if not args: + args = ('doslice',) + for arg in args: + pprint.pprint(build_flow(getattr(llfuncs, arg))) + +# ______________________________________________________________________ + +if __name__ == '__main__': + import sys + main(*sys.argv[1:]) + +# ______________________________________________________________________ +# End of byte_flow.py diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py new file mode 100644 index 0000000..a6e5864 --- /dev/null +++ b/llpython/byte_translator.py @@ -0,0 +1,612 @@ +# ______________________________________________________________________ +'''Defines a bytecode based LLVM translator for llpython code. +''' +# ______________________________________________________________________ +# Module imports +from __future__ import absolute_import +import opcode +import types +import logging + +import llvm.core as lc + +from . import opcode_util +from . import bytetype +from .bytecode_visitor import BytecodeFlowVisitor +from .byte_flow import BytecodeFlowBuilder +from .byte_control import ControlFlowBuilder +from .phi_injector import PhiInjector, synthetic_opname + +# ______________________________________________________________________ +# Module data + +logger = logging.getLogger(__name__) + +# XXX Stolen from numba.translate: + +_compare_mapping_float = {'>':lc.FCMP_OGT, + '<':lc.FCMP_OLT, + '==':lc.FCMP_OEQ, + '>=':lc.FCMP_OGE, + '<=':lc.FCMP_OLE, + '!=':lc.FCMP_ONE} + +_compare_mapping_sint = {'>':lc.ICMP_SGT, + '<':lc.ICMP_SLT, + '==':lc.ICMP_EQ, + '>=':lc.ICMP_SGE, + '<=':lc.ICMP_SLE, + '!=':lc.ICMP_NE} + +# XXX Stolen from numba.llvm_types: + +class LLVMCaster (object): + def build_pointer_cast(_, builder, lval1, lty2): + return builder.bitcast(lval1, lty2) + + def build_int_cast(_, builder, lval1, lty2, unsigned = False): + width1 = lval1.type.width + width2 = lty2.width + ret_val = lval1 + if width2 > width1: + if unsigned: + ret_val = builder.zext(lval1, lty2) + else: + ret_val = builder.sext(lval1, lty2) + elif width2 < width1: + ret_val = builder.trunc(lval1, lty2) + return ret_val + + def build_float_ext(_, builder, lval1, lty2): + return builder.fpext(lval1, lty2) + + def build_float_trunc(_, builder, lval1, lty2): + return builder.fptrunc(lval1, lty2) + + def build_int_to_float_cast(_, builder, lval1, lty2, unsigned = False): + ret_val = None + if unsigned: + ret_val = builder.uitofp(lval1, lty2) + else: + ret_val = builder.sitofp(lval1, lty2) + return ret_val + + def build_int_to_ptr_cast(_, builder, lval1, lty2): + return builder.inttoptr(lval1, lty2) + + def build_float_to_int_cast(_, builder, lval1, lty2, unsigned = False): + ret_val = None + if unsigned: + ret_val = builder.fptoui(lval1, lty2) + else: + ret_val = builder.fptosi(lval1, lty2) + return ret_val + + CAST_MAP = { + lc.TYPE_POINTER : build_pointer_cast, + lc.TYPE_INTEGER: build_int_cast, + (lc.TYPE_FLOAT, lc.TYPE_DOUBLE) : build_float_ext, + (lc.TYPE_DOUBLE, lc.TYPE_FLOAT) : build_float_trunc, + (lc.TYPE_INTEGER, lc.TYPE_FLOAT) : build_int_to_float_cast, + (lc.TYPE_INTEGER, lc.TYPE_DOUBLE) : build_int_to_float_cast, + (lc.TYPE_INTEGER, lc.TYPE_POINTER) : build_int_to_ptr_cast, + (lc.TYPE_FLOAT, lc.TYPE_INTEGER) : build_float_to_int_cast, + (lc.TYPE_DOUBLE, lc.TYPE_INTEGER) : build_float_to_int_cast, + + } + + @classmethod + def build_cast(cls, builder, lval1, lty2, *args, **kws): + ret_val = lval1 + lty1 = lval1.type + lkind1 = lty1.kind + lkind2 = lty2.kind + + if lkind1 == lkind2: + + if lkind1 in cls.CAST_MAP: + ret_val = cls.CAST_MAP[lkind1](cls, builder, lval1, lty2, + *args, **kws) + else: + raise NotImplementedError(lkind1) + else: + map_index = (lkind1, lkind2) + if map_index in cls.CAST_MAP: + ret_val = cls.CAST_MAP[map_index](cls, builder, lval1, lty2, + *args, **kws) + else: + raise NotImplementedError(lkind1, lkind2) + return ret_val + +# ______________________________________________________________________ +# Class definitions + +class LLVMTranslator (BytecodeFlowVisitor): + '''Transformer responsible for visiting a set of bytecode flow + trees, emitting LLVM code. + + Unlike other translators in :py:mod:`llpython`, this + incorporates the full transformation chain, starting with + :py:class:`llpython.byte_flow.BytecodeFlowBuilder`, then + :py:class:`llpython.byte_control.ControlFlowBuilder`, and + then :py:class:`llpython.phi_injector.PhiInjector`.''' + + def __init__ (self, llvm_module = None, *args, **kws): + '''Constructor for LLVMTranslator.''' + super(LLVMTranslator, self).__init__(*args, **kws) + if llvm_module is None: + llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),)) + self.llvm_module = llvm_module + self.bytecode_flow_builder = BytecodeFlowBuilder() + self.control_flow_builder = ControlFlowBuilder() + self.phi_injector = PhiInjector() + + def translate (self, function, llvm_type = None, llvm_function = None, + env = None): + '''Translate a function to the given LLVM function type. + + If no type is given, then assume the function is of LLVM type + "void ()". + + The optional env parameter allows extension of the global + environment.''' + if llvm_type is None: + if llvm_function is None: + llvm_type = lc.Type.function(bytetype.lvoid, ()) + else: + llvm_type = llvm_function.type.pointee + if env is None: + env = {} + else: + env = env.copy() + env.update((name, method) + for name, method in lc.Builder.__dict__.items() + if not name.startswith('_')) + env.update((name, value) + for name, value in bytetype.__dict__.items() + if not name.startswith('_')) + self.loop_stack = [] + self.llvm_type = llvm_type + self.target_function_name = env.get('target_function_name', + function.__name__) + self.function = function + self.code_obj = opcode_util.get_code_object(function) + func_globals = getattr(function, 'func_globals', + getattr(function, '__globals__', {})).copy() + func_globals.update(env) + self.globals = func_globals + nargs = self.code_obj.co_argcount + self.cfg = self.control_flow_builder.visit( + opcode_util.build_basic_blocks(self.code_obj), nargs) + self.cfg.blocks = self.bytecode_flow_builder.visit_cfg(self.cfg) + self.llvm_function = llvm_function + flow = self.phi_injector.visit_cfg(self.cfg, nargs) + ret_val = self.visit(flow) + del self.cfg + del self.globals + del self.code_obj + del self.target_function_name + del self.function + del self.llvm_type + del self.loop_stack + return ret_val + + def enter_flow_object (self, flow): + super(LLVMTranslator, self).enter_flow_object(flow) + if self.llvm_function is None: + self.llvm_function = self.llvm_module.add_function( + self.llvm_type, self.target_function_name) + self.llvm_blocks = {} + self.llvm_definitions = {} + self.pending_phis = {} + for block in self.block_list: + if 0 in self.cfg.blocks_reaching[block]: + bb = self.llvm_function.append_basic_block( + 'BLOCK_%d' % (block,)) + self.llvm_blocks[block] = bb + + def exit_flow_object (self, flow): + super(LLVMTranslator, self).exit_flow_object(flow) + ret_val = self.llvm_function + del self.pending_phis + del self.llvm_definitions + del self.llvm_blocks + if __debug__ and logger.getEffectiveLevel() < logging.DEBUG: + logger.debug(str(ret_val)) + return ret_val + + def enter_block (self, block): + ret_val = False + if block in self.llvm_blocks: + self.llvm_block = self.llvm_blocks[block] + self.builder = lc.Builder.new(self.llvm_block) + ret_val = True + return ret_val + + def exit_block (self, block): + bb_instrs = self.llvm_block.instructions + if ((len(bb_instrs) == 0) or + (not bb_instrs[-1].is_terminator)): + out_blocks = list(self.cfg.blocks_out[block]) + assert len(out_blocks) == 1 + self.builder.branch(self.llvm_blocks[out_blocks[0]]) + del self.llvm_block + del self.builder + + def visit_synthetic_op (self, i, op, arg, *args, **kws): + method = getattr(self, 'op_%s' % (synthetic_opname[op],)) + return method(i, op, arg, *args, **kws) + + def op_REF_ARG (self, i, op, arg, *args, **kws): + return [self.llvm_function.args[arg]] + + def op_BUILD_PHI (self, i, op, arg, *args, **kws): + phi_type = None + incoming = [] + pending = [] + for child_arg in arg: + child_block, _, child_opname, child_arg, _ = child_arg + assert child_opname == 'REF_DEF' + if child_arg in self.llvm_definitions: + child_def = self.llvm_definitions[child_arg] + if phi_type is None: + phi_type = child_def.type + incoming.append((child_block, child_def)) + else: + pending.append((child_arg, child_block)) + phi = self.builder.phi(phi_type) + for block_index, defn in incoming: + phi.add_incoming(defn, self.llvm_blocks[block_index]) + for defn_index, block_index in pending: + if defn_index not in self.pending_phis: + self.pending_phis[defn_index] = [] + self.pending_phis[defn_index].append((phi, block_index)) + return [phi] + + def op_DEFINITION (self, i, op, def_index, *args, **kws): + assert len(args) == 1 + arg = args[0] + if def_index in self.pending_phis: + for phi, block_index in self.pending_phis[def_index]: + phi.add_incoming(arg, self.llvm_blocks[block_index]) + self.llvm_definitions[def_index] = arg + return args + + def op_REF_DEF (self, i, op, arg, *args, **kws): + return [self.llvm_definitions[arg]] + + def op_BINARY_ADD (self, i, op, arg, *args, **kws): + arg1, arg2 = args + if arg1.type.kind == lc.TYPE_INTEGER: + ret_val = [self.builder.add(arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.fadd(arg1, arg2)] + elif arg1.type.kind == lc.TYPE_POINTER: + ret_val = [self.builder.gep(arg1, [arg2])] + else: + raise NotImplementedError("LLVMTranslator.op_BINARY_ADD for %r" % + (args,)) + return ret_val + + def op_BINARY_AND (self, i, op, arg, *args, **kws): + return [self.builder.and_(args[0], args[1])] + + def op_BINARY_DIVIDE (self, i, op, arg, *args, **kws): + arg1, arg2 = args + if arg1.type.kind == lc.TYPE_INTEGER: + ret_val = [self.builder.sdiv(arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.fdiv(arg1, arg2)] + else: + raise NotImplementedError("LLVMTranslator.op_BINARY_DIVIDE for %r" + % (args,)) + return ret_val + + def op_BINARY_FLOOR_DIVIDE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_BINARY_FLOOR_DIVIDE") + + def op_BINARY_LSHIFT (self, i, op, arg, *args, **kws): + return [self.builder.shl(args[0], args[1])] + + def op_BINARY_MODULO (self, i, op, arg, *args, **kws): + arg1, arg2 = args + if arg1.type.kind == lc.TYPE_INTEGER: + ret_val = [self.builder.srem(arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.frem(arg1, arg2)] + else: + raise NotImplementedError("LLVMTranslator.op_BINARY_MODULO for %r" + % (args,)) + return ret_val + + def op_BINARY_MULTIPLY (self, i, op, arg, *args, **kws): + arg1, arg2 = args + if arg1.type.kind == lc.TYPE_INTEGER: + ret_val = [self.builder.mul(arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.fmul(arg1, arg2)] + else: + raise NotImplementedError("LLVMTranslator.op_BINARY_MULTIPLY for " + "%r" % (args,)) + return ret_val + + def op_BINARY_OR (self, i, op, arg, *args, **kws): + return [self.builder.or_(args[0], args[1])] + + def op_BINARY_POWER (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_BINARY_POWER") + + def op_BINARY_RSHIFT (self, i, op, arg, *args, **kws): + return [self.builder.lshr(args[0], args[1])] + + def op_BINARY_SUBSCR (self, i, op, arg, *args, **kws): + arr_val = args[0] + index_vals = args[1:] + ret_val = gep_result = self.builder.gep(arr_val, index_vals) + if (gep_result.type.kind == lc.TYPE_POINTER and + gep_result.type.pointee.kind != lc.TYPE_POINTER): + ret_val = self.builder.load(gep_result) + return [ret_val] + + def op_BINARY_SUBTRACT (self, i, op, arg, *args, **kws): + arg1, arg2 = args + if arg1.type.kind == lc.TYPE_INTEGER: + ret_val = [self.builder.sub(arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.fsub(arg1, arg2)] + else: + raise NotImplementedError("LLVMTranslator.op_BINARY_SUBTRACT for " + "%r" % (args,)) + return ret_val + + op_BINARY_TRUE_DIVIDE = op_BINARY_DIVIDE + + def op_BINARY_XOR (self, i, op, arg, *args, **kws): + return [self.builder.xor(args[0], args[1])] + + def op_BREAK_LOOP (self, i, op, arg, *args, **kws): + return [self.builder.branch(self.llvm_blocks[arg])] + + def op_BUILD_SLICE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_BUILD_SLICE") + + def op_BUILD_TUPLE (self, i, op, arg, *args, **kws): + return args + + def op_CALL_FUNCTION (self, i, op, arg, *args, **kws): + fn = args[0] + args = args[1:] + fn_name = getattr(fn, '__name__', None) + if isinstance(fn, (types.FunctionType, types.MethodType)): + ret_val = [fn(self.builder, *args)] + elif isinstance(fn, lc.Value): + ret_val = [self.builder.call(fn, args)] + elif isinstance(fn, lc.Type): + if isinstance(fn, lc.FunctionType): + ret_val = [self.builder.call( + self.llvm_module.get_or_insert_function(fn, fn_name), + args)] + else: + assert len(args) == 1 + ret_val = [LLVMCaster.build_cast(self.builder, args[0], fn)] + else: + raise NotImplementedError("Don't know how to call %s() (%r @ %d)!" + % (fn_name, fn, i)) + return ret_val + + def op_CALL_FUNCTION_KW (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_KW") + + def op_CALL_FUNCTION_VAR (self, i, op, arg, *args, **kws): + args = list(args) + var_args = list(args.pop()) + args.extend(var_args) + return self.op_CALL_FUNCTION(i, op, arg, *args, **kws) + + def op_CALL_FUNCTION_VAR_KW (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_VAR_KW") + + def op_COMPARE_OP (self, i, op, arg, *args, **kws): + arg1, arg2 = args + cmp_kind = opcode.cmp_op[arg] + if isinstance(arg1.type, lc.IntegerType): + ret_val = [self.builder.icmp(_compare_mapping_sint[cmp_kind], + arg1, arg2)] + elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + ret_val = [self.builder.fcmp(_compare_mapping_float[cmp_kind], + arg1, arg2)] + else: + raise NotImplementedError('Comparison of type %r' % (arg1.type,)) + return ret_val + + def op_CONTINUE_LOOP (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_CONTINUE_LOOP") + + def op_DELETE_ATTR (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_DELETE_ATTR") + + def op_DELETE_SLICE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_DELETE_SLICE") + + def op_FOR_ITER (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_FOR_ITER") + + def op_GET_ITER (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_GET_ITER") + + op_INPLACE_ADD = op_BINARY_ADD + op_INPLACE_AND = op_BINARY_AND + op_INPLACE_DIVIDE = op_BINARY_DIVIDE + op_INPLACE_FLOOR_DIVIDE = op_BINARY_FLOOR_DIVIDE + op_INPLACE_LSHIFT = op_BINARY_LSHIFT + op_INPLACE_MODULO = op_BINARY_MODULO + op_INPLACE_MULTIPLY = op_BINARY_MULTIPLY + op_INPLACE_OR = op_BINARY_OR + op_INPLACE_POWER = op_BINARY_POWER + op_INPLACE_RSHIFT = op_BINARY_RSHIFT + op_INPLACE_SUBTRACT = op_BINARY_SUBTRACT + op_INPLACE_TRUE_DIVIDE = op_BINARY_TRUE_DIVIDE + op_INPLACE_XOR = op_BINARY_XOR + + def op_JUMP_ABSOLUTE (self, i, op, arg, *args, **kws): + return [self.builder.branch(self.llvm_blocks[arg])] + + def op_JUMP_FORWARD (self, i, op, arg, *args, **kws): + return [self.builder.branch(self.llvm_blocks[i + arg + 3])] + + def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): + cond = args[0] + block_false = self.llvm_blocks[i + 3 + arg] + block_true = self.llvm_blocks[i + 3] + return [self.builder.cbranch(cond, block_true, block_false)] + # raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") + + def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP") + + def op_JUMP_IF_TRUE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE") + + def op_JUMP_IF_TRUE_OR_POP (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE_OR_POP") + + def op_LOAD_ATTR (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_LOAD_ATTR") + + def op_LOAD_CONST (self, i, op, arg, *args, **kws): + py_val = self.code_obj.co_consts[arg] + if isinstance(py_val, int): + ret_val = [lc.Constant.int(bytetype.lc_int, py_val)] + elif isinstance(py_val, float): + ret_val = [lc.Constant.double(py_val)] + elif py_val == None: + ret_val = [None] + else: + raise NotImplementedError('Constant converstion for %r' % + (py_val,)) + return ret_val + + def op_LOAD_DEREF (self, i, op, arg, *args, **kws): + name = self.code_obj.co_freevars[arg] + ret_val = self.globals[name] + if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): + ret_val.__name__ = name + return [ret_val] + + def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws): + name = self.code_obj.co_names[arg] + ret_val = self.globals[name] + if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): + ret_val.__name__ = name + return [ret_val] + + def op_POP_BLOCK (self, i, op, arg, *args, **kws): + self.loop_stack.pop() + return [self.builder.branch(self.llvm_blocks[i + 1])] + + def op_POP_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): + return [self.builder.cbranch(args[0], self.llvm_blocks[i + 3], + self.llvm_blocks[arg])] + + def op_POP_JUMP_IF_TRUE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_POP_JUMP_IF_TRUE") + + def op_POP_TOP (self, i, op, arg, *args, **kws): + return args + + def op_RETURN_VALUE (self, i, op, arg, *args, **kws): + if args[0] is None: + ret_val = [self.builder.ret_void()] + else: + ret_val = [self.builder.ret(args[0])] + return ret_val + + def op_SETUP_LOOP (self, i, op, arg, *args, **kws): + self.loop_stack.append((i, arg)) + return [self.builder.branch(self.llvm_blocks[i + 3])] + + def op_SLICE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_SLICE") + + def op_STORE_ATTR (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_STORE_ATTR") + + def op_STORE_SLICE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_STORE_SLICE") + + def op_STORE_SUBSCR (self, i, op, arg, *args, **kws): + store_val, arr_val, index_val = args + dest_addr = self.builder.gep(arr_val, [index_val]) + return [self.builder.store(store_val, dest_addr)] + + def op_UNARY_CONVERT (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT") + + def op_UNARY_INVERT (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_UNARY_INVERT") + + def op_UNARY_NEGATIVE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_UNARY_NEGATIVE") + + def op_UNARY_NOT (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_UNARY_NOT") + + def op_UNARY_POSITIVE (self, i, op, arg, *args, **kws): + raise NotImplementedError("LLVMTranslator.op_UNARY_POSITIVE") + +# ______________________________________________________________________ + +def translate_function (func, lltype, llvm_module = None, **kws): + '''Given a function and an LLVM function type, emit LLVM code for + that function using a new LLVMTranslator instance.''' + translator = LLVMTranslator(llvm_module) + ret_val = translator.translate(func, lltype, env = kws) + return ret_val + +# ______________________________________________________________________ + +def translate_into_function (py_function, llvm_function, **kws): + translator = LLVMTranslator(llvm_function.module) + ret_val = translator.translate(py_function, llvm_function = llvm_function, + env = kws) + return ret_val + +# ______________________________________________________________________ + +def llpython (lltype, llvm_module = None, **kws): + '''Decorator version of translate_function().''' + def _llpython (func): + return translate_function(func, lltype, llvm_module, **kws) + return _llpython + +# ______________________________________________________________________ + +def llpython_into (llvm_function, **kws): + def _llpython_into (func): + return translate_into_function(llvm_function, func, **kws) + return _llpython_into + +# ______________________________________________________________________ +# Main (self-test) routine + +def main (*args): + from tests import llfuncs, llfunctys + if not args: + args = ('doslice',) + elif 'all' in args: + args = [llfunc + for llfunc in dir(llfuncs) if not llfunc.startswith('_')] + llvm_module = lc.Module.new('test_module') + for arg in args: + translate_function(getattr(llfuncs, arg), getattr(llfunctys, arg), + llvm_module) + print(llvm_module) + +# ______________________________________________________________________ + +if __name__ == '__main__': + import sys + main(*sys.argv[1:]) + +# ______________________________________________________________________ +# End of byte_translator.py diff --git a/llpython/bytecode_visitor.py b/llpython/bytecode_visitor.py new file mode 100644 index 0000000..3fa3f48 --- /dev/null +++ b/llpython/bytecode_visitor.py @@ -0,0 +1,360 @@ +# ______________________________________________________________________ +from __future__ import absolute_import +import itertools + +import opcode +from .opcode_util import itercode + +# ______________________________________________________________________ + +class BytecodeVisitor (object): + opnames = [name.split('+')[0] for name in opcode.opname] + + def visit_op (self, i, op, arg, *args, **kws): + if op < 0: + ret_val = self.visit_synthetic_op(i, op, arg, *args, **kws) + else: + method = getattr(self, 'op_' + self.opnames[op]) + ret_val = method(i, op, arg, *args, **kws) + return ret_val + + def visit_synthetic_op (self, i, op, arg, *args, **kws): + raise NotImplementedError( + 'BytecodeVisitor.visit_synthetic_op() must be overloaded if using ' + 'synthetic opcodes.') + + def _not_implemented (self, i, op, arg, *args, **kws): + raise NotImplementedError("BytecodeVisitor.op_%s (@ bytecode index %d)" + % (self.opnames[op], i)) + + op_BINARY_ADD = _not_implemented + op_BINARY_AND = _not_implemented + op_BINARY_DIVIDE = _not_implemented + op_BINARY_FLOOR_DIVIDE = _not_implemented + op_BINARY_LSHIFT = _not_implemented + op_BINARY_MODULO = _not_implemented + op_BINARY_MULTIPLY = _not_implemented + op_BINARY_OR = _not_implemented + op_BINARY_POWER = _not_implemented + op_BINARY_RSHIFT = _not_implemented + op_BINARY_SUBSCR = _not_implemented + op_BINARY_SUBTRACT = _not_implemented + op_BINARY_TRUE_DIVIDE = _not_implemented + op_BINARY_XOR = _not_implemented + op_BREAK_LOOP = _not_implemented + op_BUILD_CLASS = _not_implemented + op_BUILD_LIST = _not_implemented + op_BUILD_MAP = _not_implemented + op_BUILD_SET = _not_implemented + op_BUILD_SLICE = _not_implemented + op_BUILD_TUPLE = _not_implemented + op_CALL_FUNCTION = _not_implemented + op_CALL_FUNCTION_KW = _not_implemented + op_CALL_FUNCTION_VAR = _not_implemented + op_CALL_FUNCTION_VAR_KW = _not_implemented + op_COMPARE_OP = _not_implemented + op_CONTINUE_LOOP = _not_implemented + op_DELETE_ATTR = _not_implemented + op_DELETE_DEREF = _not_implemented + op_DELETE_FAST = _not_implemented + op_DELETE_GLOBAL = _not_implemented + op_DELETE_NAME = _not_implemented + op_DELETE_SLICE = _not_implemented + op_DELETE_SUBSCR = _not_implemented + op_DUP_TOP = _not_implemented + op_DUP_TOPX = _not_implemented + op_DUP_TOP_TWO = _not_implemented + op_END_FINALLY = _not_implemented + op_EXEC_STMT = _not_implemented + op_EXTENDED_ARG = _not_implemented + op_FOR_ITER = _not_implemented + op_GET_ITER = _not_implemented + op_IMPORT_FROM = _not_implemented + op_IMPORT_NAME = _not_implemented + op_IMPORT_STAR = _not_implemented + op_INPLACE_ADD = _not_implemented + op_INPLACE_AND = _not_implemented + op_INPLACE_DIVIDE = _not_implemented + op_INPLACE_FLOOR_DIVIDE = _not_implemented + op_INPLACE_LSHIFT = _not_implemented + op_INPLACE_MODULO = _not_implemented + op_INPLACE_MULTIPLY = _not_implemented + op_INPLACE_OR = _not_implemented + op_INPLACE_POWER = _not_implemented + op_INPLACE_RSHIFT = _not_implemented + op_INPLACE_SUBTRACT = _not_implemented + op_INPLACE_TRUE_DIVIDE = _not_implemented + op_INPLACE_XOR = _not_implemented + op_JUMP_ABSOLUTE = _not_implemented + op_JUMP_FORWARD = _not_implemented + op_JUMP_IF_FALSE = _not_implemented + op_JUMP_IF_FALSE_OR_POP = _not_implemented + op_JUMP_IF_TRUE = _not_implemented + op_JUMP_IF_TRUE_OR_POP = _not_implemented + op_LIST_APPEND = _not_implemented + op_LOAD_ATTR = _not_implemented + op_LOAD_BUILD_CLASS = _not_implemented + op_LOAD_CLOSURE = _not_implemented + op_LOAD_CONST = _not_implemented + op_LOAD_DEREF = _not_implemented + op_LOAD_FAST = _not_implemented + op_LOAD_GLOBAL = _not_implemented + op_LOAD_LOCALS = _not_implemented + op_LOAD_NAME = _not_implemented + op_MAKE_CLOSURE = _not_implemented + op_MAKE_FUNCTION = _not_implemented + op_MAP_ADD = _not_implemented + op_NOP = _not_implemented + op_POP_BLOCK = _not_implemented + op_POP_EXCEPT = _not_implemented + op_POP_JUMP_IF_FALSE = _not_implemented + op_POP_JUMP_IF_TRUE = _not_implemented + op_POP_TOP = _not_implemented + op_PRINT_EXPR = _not_implemented + op_PRINT_ITEM = _not_implemented + op_PRINT_ITEM_TO = _not_implemented + op_PRINT_NEWLINE = _not_implemented + op_PRINT_NEWLINE_TO = _not_implemented + op_RAISE_VARARGS = _not_implemented + op_RETURN_VALUE = _not_implemented + op_ROT_FOUR = _not_implemented + op_ROT_THREE = _not_implemented + op_ROT_TWO = _not_implemented + op_SETUP_EXCEPT = _not_implemented + op_SETUP_FINALLY = _not_implemented + op_SETUP_LOOP = _not_implemented + op_SETUP_WITH = _not_implemented + op_SET_ADD = _not_implemented + op_SLICE = _not_implemented + op_STOP_CODE = _not_implemented + op_STORE_ATTR = _not_implemented + op_STORE_DEREF = _not_implemented + op_STORE_FAST = _not_implemented + op_STORE_GLOBAL = _not_implemented + op_STORE_LOCALS = _not_implemented + op_STORE_MAP = _not_implemented + op_STORE_NAME = _not_implemented + op_STORE_SLICE = _not_implemented + op_STORE_SUBSCR = _not_implemented + op_UNARY_CONVERT = _not_implemented + op_UNARY_INVERT = _not_implemented + op_UNARY_NEGATIVE = _not_implemented + op_UNARY_NOT = _not_implemented + op_UNARY_POSITIVE = _not_implemented + op_UNPACK_EX = _not_implemented + op_UNPACK_SEQUENCE = _not_implemented + op_WITH_CLEANUP = _not_implemented + op_YIELD_VALUE = _not_implemented + +# ______________________________________________________________________ + +class BytecodeIterVisitor (BytecodeVisitor): + def visit (self, co_obj): + self.enter_code_object(co_obj) + for i, op, arg in itercode(co_obj.co_code): + self.visit_op(i, op, arg) + return self.exit_code_object(co_obj) + + def enter_code_object (self, co_obj): + pass + + def exit_code_object (self, co_obj): + pass + +# ______________________________________________________________________ + +class BasicBlockVisitor (BytecodeVisitor): + def visit (self, blocks): + self.enter_blocks(blocks) + block_indices = list(blocks.keys()) + block_indices.sort() + for block_index in block_indices: + self.enter_block(block_index) + for i, op, arg in blocks[block_index]: + self.visit_op(i, op, arg) + self.exit_block(block_index) + return self.exit_blocks(blocks) + + def enter_blocks (self, blocks): + pass + + def exit_blocks (self, blocks): + pass + + def enter_block (self, block_index): + pass + + def exit_block (self, block_index): + pass + +# ______________________________________________________________________ + +class BytecodeFlowVisitor (BytecodeVisitor): + def visit (self, flow): + self.block_list = list(flow.keys()) + self.block_list.sort() + self.enter_flow_object(flow) + for block in self.block_list: + prelude = self.enter_block(block) + prelude_isa_list = isinstance(prelude, list) + if prelude or prelude_isa_list: + if not prelude_isa_list: + prelude = [] + new_stmts = list(self.visit_op(i, op, arg, *args) + for i, op, _, arg, args in flow[block]) + self.new_flow[block] = list(itertools.chain( + prelude, *new_stmts)) + self.exit_block(block) + del self.block_list + return self.exit_flow_object(flow) + + def visit_op (self, i, op, arg, *args, **kws): + new_args = [] + for child_i, child_op, _, child_arg, child_args in args: + new_args.extend(self.visit_op(child_i, child_op, child_arg, + *child_args)) + ret_val = super(BytecodeFlowVisitor, self).visit_op(i, op, arg, + *new_args) + return ret_val + + def enter_flow_object (self, flow): + self.new_flow = {} + + def exit_flow_object (self, flow): + ret_val = self.new_flow + del self.new_flow + return ret_val + + def enter_block (self, block): + pass + + def exit_block (self, block): + pass + +# ______________________________________________________________________ + +class BenignBytecodeVisitorMixin (object): + def _do_nothing (self, i, op, arg, *args, **kws): + return [(i, op, self.opnames[op], arg, args)] + + op_BINARY_ADD = _do_nothing + op_BINARY_AND = _do_nothing + op_BINARY_DIVIDE = _do_nothing + op_BINARY_FLOOR_DIVIDE = _do_nothing + op_BINARY_LSHIFT = _do_nothing + op_BINARY_MODULO = _do_nothing + op_BINARY_MULTIPLY = _do_nothing + op_BINARY_OR = _do_nothing + op_BINARY_POWER = _do_nothing + op_BINARY_RSHIFT = _do_nothing + op_BINARY_SUBSCR = _do_nothing + op_BINARY_SUBTRACT = _do_nothing + op_BINARY_TRUE_DIVIDE = _do_nothing + op_BINARY_XOR = _do_nothing + op_BREAK_LOOP = _do_nothing + op_BUILD_CLASS = _do_nothing + op_BUILD_LIST = _do_nothing + op_BUILD_MAP = _do_nothing + op_BUILD_SET = _do_nothing + op_BUILD_SLICE = _do_nothing + op_BUILD_TUPLE = _do_nothing + op_CALL_FUNCTION = _do_nothing + op_CALL_FUNCTION_KW = _do_nothing + op_CALL_FUNCTION_VAR = _do_nothing + op_CALL_FUNCTION_VAR_KW = _do_nothing + op_COMPARE_OP = _do_nothing + op_CONTINUE_LOOP = _do_nothing + op_DELETE_ATTR = _do_nothing + op_DELETE_DEREF = _do_nothing + op_DELETE_FAST = _do_nothing + op_DELETE_GLOBAL = _do_nothing + op_DELETE_NAME = _do_nothing + op_DELETE_SLICE = _do_nothing + op_DELETE_SUBSCR = _do_nothing + op_DUP_TOP = _do_nothing + op_DUP_TOPX = _do_nothing + op_DUP_TOP_TWO = _do_nothing + op_END_FINALLY = _do_nothing + op_EXEC_STMT = _do_nothing + op_EXTENDED_ARG = _do_nothing + op_FOR_ITER = _do_nothing + op_GET_ITER = _do_nothing + op_IMPORT_FROM = _do_nothing + op_IMPORT_NAME = _do_nothing + op_IMPORT_STAR = _do_nothing + op_INPLACE_ADD = _do_nothing + op_INPLACE_AND = _do_nothing + op_INPLACE_DIVIDE = _do_nothing + op_INPLACE_FLOOR_DIVIDE = _do_nothing + op_INPLACE_LSHIFT = _do_nothing + op_INPLACE_MODULO = _do_nothing + op_INPLACE_MULTIPLY = _do_nothing + op_INPLACE_OR = _do_nothing + op_INPLACE_POWER = _do_nothing + op_INPLACE_RSHIFT = _do_nothing + op_INPLACE_SUBTRACT = _do_nothing + op_INPLACE_TRUE_DIVIDE = _do_nothing + op_INPLACE_XOR = _do_nothing + op_JUMP_ABSOLUTE = _do_nothing + op_JUMP_FORWARD = _do_nothing + op_JUMP_IF_FALSE = _do_nothing + op_JUMP_IF_FALSE_OR_POP = _do_nothing + op_JUMP_IF_TRUE = _do_nothing + op_JUMP_IF_TRUE_OR_POP = _do_nothing + op_LIST_APPEND = _do_nothing + op_LOAD_ATTR = _do_nothing + op_LOAD_BUILD_CLASS = _do_nothing + op_LOAD_CLOSURE = _do_nothing + op_LOAD_CONST = _do_nothing + op_LOAD_DEREF = _do_nothing + op_LOAD_FAST = _do_nothing + op_LOAD_GLOBAL = _do_nothing + op_LOAD_LOCALS = _do_nothing + op_LOAD_NAME = _do_nothing + op_MAKE_CLOSURE = _do_nothing + op_MAKE_FUNCTION = _do_nothing + op_MAP_ADD = _do_nothing + op_NOP = _do_nothing + op_POP_BLOCK = _do_nothing + op_POP_EXCEPT = _do_nothing + op_POP_JUMP_IF_FALSE = _do_nothing + op_POP_JUMP_IF_TRUE = _do_nothing + op_POP_TOP = _do_nothing + op_PRINT_EXPR = _do_nothing + op_PRINT_ITEM = _do_nothing + op_PRINT_ITEM_TO = _do_nothing + op_PRINT_NEWLINE = _do_nothing + op_PRINT_NEWLINE_TO = _do_nothing + op_RAISE_VARARGS = _do_nothing + op_RETURN_VALUE = _do_nothing + op_ROT_FOUR = _do_nothing + op_ROT_THREE = _do_nothing + op_ROT_TWO = _do_nothing + op_SETUP_EXCEPT = _do_nothing + op_SETUP_FINALLY = _do_nothing + op_SETUP_LOOP = _do_nothing + op_SETUP_WITH = _do_nothing + op_SET_ADD = _do_nothing + op_SLICE = _do_nothing + op_STOP_CODE = _do_nothing + op_STORE_ATTR = _do_nothing + op_STORE_DEREF = _do_nothing + op_STORE_FAST = _do_nothing + op_STORE_GLOBAL = _do_nothing + op_STORE_LOCALS = _do_nothing + op_STORE_MAP = _do_nothing + op_STORE_NAME = _do_nothing + op_STORE_SLICE = _do_nothing + op_STORE_SUBSCR = _do_nothing + op_UNARY_CONVERT = _do_nothing + op_UNARY_INVERT = _do_nothing + op_UNARY_NEGATIVE = _do_nothing + op_UNARY_NOT = _do_nothing + op_UNARY_POSITIVE = _do_nothing + op_UNPACK_EX = _do_nothing + op_UNPACK_SEQUENCE = _do_nothing + op_WITH_CLEANUP = _do_nothing + op_YIELD_VALUE = _do_nothing + +# ______________________________________________________________________ +# End of bytecode_visitor.py diff --git a/llpython/bytetype.py b/llpython/bytetype.py new file mode 100644 index 0000000..484d09e --- /dev/null +++ b/llpython/bytetype.py @@ -0,0 +1,42 @@ +# ______________________________________________________________________ + +import ctypes + +import llvm.core as lc + +# ______________________________________________________________________ + +lvoid = lc.Type.void() +li1 = lc.Type.int(1) +li8 = lc.Type.int(8) +li16 = lc.Type.int(16) +li32 = lc.Type.int(32) +li64 = lc.Type.int(64) +liptr = lc.Type.int(ctypes.sizeof(ctypes.c_void_p) * 8) +lc_size_t = lc.Type.int(ctypes.sizeof( + getattr(ctypes, 'c_ssize_t', getattr(ctypes, 'c_size_t'))) * 8) +lfloat = lc.Type.float() +ldouble = lc.Type.double() +li8_ptr = lc.Type.pointer(li8) + +lc_int = lc.Type.int(ctypes.sizeof(ctypes.c_int) * 8) +lc_long = lc.Type.int(ctypes.sizeof(ctypes.c_long) * 8) + +l_pyobject_head = [lc_size_t, lc.Type.pointer(li32)] +l_pyobject_head_struct = lc.Type.struct(l_pyobject_head) +l_pyobj_p = l_pyobject_head_struct_p = lc.Type.pointer(l_pyobject_head_struct) +l_pyfunc = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p)) + +strlen = lc.Type.function(lc_size_t, (li8_ptr,)) +strncpy = lc.Type.function(li8_ptr, (li8_ptr, li8_ptr, lc_size_t)) +strndup = lc.Type.function(li8_ptr, (li8_ptr, lc_size_t)) +malloc = lc.Type.function(li8_ptr, (lc_size_t,)) +free = lc.Type.function(lvoid, (li8_ptr,)) + +Py_BuildValue = lc.Type.function(l_pyobj_p, [li8_ptr], True) +PyArg_ParseTuple = lc.Type.function(lc_int, [l_pyobj_p, li8_ptr], True) +PyEval_SaveThread = lc.Type.function(li8_ptr, []) +PyEval_RestoreThread = lc.Type.function(lc.Type.void(), [li8_ptr]) + +# ______________________________________________________________________ +# End of bytetype.py diff --git a/llpython/control_flow.py b/llpython/control_flow.py new file mode 100644 index 0000000..8026aba --- /dev/null +++ b/llpython/control_flow.py @@ -0,0 +1,217 @@ +# ______________________________________________________________________ + +import pprint + +# ______________________________________________________________________ + +class ControlFlowGraph (object): + def __init__ (self): + self.blocks = {} + self.blocks_in = {} + self.blocks_out = {} + self.blocks_reads = {} + self.blocks_writes = {} + self.blocks_writer = {} + self.blocks_dom = {} + self.blocks_reaching = {} + + def add_block (self, key, value = None): + self.blocks[key] = value + if key not in self.blocks_in: + self.blocks_in[key] = set() + self.blocks_out[key] = set() + self.blocks_reads[key] = set() + self.blocks_writes[key] = set() + self.blocks_writer[key] = {} + + def add_edge (self, from_block, to_block): + self.blocks_out[from_block].add(to_block) + self.blocks_in[to_block].add(from_block) + + def unlink_unreachables (self): + changed = True + next_blocks = self.blocks.keys() + next_blocks.remove(0) + while changed: + changed = False + blocks = next_blocks + next_blocks = blocks[:] + for block in blocks: + if len(self.blocks_in[block]) == 0: + blocks_out = self.blocks_out[block] + for out_edge in blocks_out: + self.blocks_in[out_edge].discard(block) + blocks_out.clear() + next_blocks.remove(block) + changed = True + + def compute_dataflow (self): + '''Compute the dominator and reaching dataflow relationships + in the CFG.''' + blocks = set(self.blocks.keys()) + nonentry_blocks = blocks.copy() + for block in blocks: + self.blocks_dom[block] = blocks + self.blocks_reaching[block] = set((block,)) + if len(self.blocks_in[block]) == 0: + self.blocks_dom[block] = set((block,)) + nonentry_blocks.remove(block) + changed = True + while changed: + changed = False + for block in nonentry_blocks: + olddom = self.blocks_dom[block] + newdom = set.intersection(*[self.blocks_dom[pred] + for pred in self.blocks_in[block]]) + newdom.add(block) + if newdom != olddom: + changed = True + self.blocks_dom[block] = newdom + oldreaching = self.blocks_reaching[block] + newreaching = set.union( + *[self.blocks_reaching[pred] + for pred in self.blocks_in[block]]) + newreaching.add(block) + if newreaching != oldreaching: + changed = True + self.blocks_reaching[block] = newreaching + return self.blocks_dom, self.blocks_reaching + + def update_for_ssa (self): + '''Modify the blocks_writes map to reflect phi nodes inserted + for static single assignment representations.''' + joins = [block for block in self.blocks.keys() + if len(self.blocks_in[block]) > 1] + changed = True + while changed: + changed = False + for block in joins: + phis_needed = self.phi_needed(block) + for affected_local in phis_needed: + if affected_local not in self.blocks_writes[block]: + changed = True + # NOTE: For this to work, we assume that basic + # blocks are indexed by their instruction + # index in the VM bytecode. + self.writes_local(block, block, affected_local) + if changed: + # Any modifications have invalidated the reaching + # definitions, so delete any memoized results. + if hasattr(self, 'reaching_definitions'): + del self.reaching_definitions + + def idom (self, block): + '''Compute the immediate dominator (idom) of the given block + key. Returns None if the block has no in edges. + + Note that in the case where there are multiple immediate + dominators (a join after a non-loop branch), this returns one + of the predecessors, but is not guaranteed to reliably select + one over the others (depends on the ordering of the set type + iterator).''' + preds = self.blocks_in[block] + npreds = len(preds) + if npreds == 0: + ret_val = None + elif npreds == 1: + ret_val = tuple(preds)[0] + else: + ret_val = [pred for pred in preds + if block not in self.blocks_dom[pred]][0] + return ret_val + + def block_writes_to_writer_map (self, block): + ret_val = {} + for local in self.blocks_writes[block]: + ret_val[local] = block + return ret_val + + def get_reaching_definitions (self, block): + '''Return a nested map for the given block + s.t. ret_val[pred][local] equals the block key for the + definition of local that reaches the argument block via that + predecessor. + + Useful for actually populating phi nodes, once you know you + need them.''' + has_memoized = hasattr(self, 'reaching_definitions') + if has_memoized and block in self.reaching_definitions: + ret_val = self.reaching_definitions[block] + else: + preds = self.blocks_in[block] + ret_val = {} + for pred in preds: + ret_val[pred] = self.block_writes_to_writer_map(pred) + crnt = self.idom(pred) + while crnt != None: + crnt_writer_map = self.block_writes_to_writer_map(crnt) + # This order of update favors the first definitions + # encountered in the traversal since the traversal + # visits blocks in reverse execution order. + crnt_writer_map.update(ret_val[pred]) + ret_val[pred] = crnt_writer_map + crnt = self.idom(crnt) + if not has_memoized: + self.reaching_definitions = {} + self.reaching_definitions[block] = ret_val + return ret_val + + def nreaches (self, block): + '''For each local, find the number of unique reaching + definitions the current block has.''' + reaching_definitions = self.get_reaching_definitions(block) + definition_map = {} + for pred in self.blocks_in[block]: + reaching_from_pred = reaching_definitions[pred] + for local in reaching_from_pred.keys(): + if local not in definition_map: + definition_map[local] = set() + definition_map[local].add(reaching_from_pred[local]) + ret_val = {} + for local in definition_map.keys(): + ret_val[local] = len(definition_map[local]) + return ret_val + + def writes_local (self, block, write_instr_index, local_index): + self.blocks_writes[block].add(local_index) + block_writers = self.blocks_writer[block] + old_index = block_writers.get(local_index, -1) + # This checks for a corner case that would impact + # numba.translate.Translate.build_phi_nodes(). + assert old_index != write_instr_index, ( + "Found corner case for STORE_FAST at a CFG join!") + block_writers[local_index] = max(write_instr_index, old_index) + + def phi_needed (self, join): + '''Return the set of locals that will require a phi node to be + generated at the given join.''' + nreaches = self.nreaches(join) + return set([local for local in nreaches.keys() + if nreaches[local] > 1]) + + def pprint (self, *args, **kws): + pprint.pprint(self.__dict__, *args, **kws) + + def pformat (self, *args, **kws): + return pprint.pformat(self.__dict__, *args, **kws) + + def to_dot (self, graph_name = None): + '''Return a dot (digraph visualizer in Graphviz) graph + description as a string.''' + if graph_name is None: + graph_name = 'CFG_%d' % id(self) + lines_out = [] + for block_index in self.blocks: + lines_out.append( + 'BLOCK_%r [shape=box, label="BLOCK_%r\\nr: %r, w: %r"];' % + (block_index, block_index, + tuple(self.blocks_reads[block_index]), + tuple(self.blocks_writes[block_index]))) + for block_index in self.blocks: + for out_edge in self.blocks_out[block_index]: + lines_out.append('BLOCK_%r -> BLOCK_%r;' % + (block_index, out_edge)) + return 'digraph %s {\n%s\n}\n' % (graph_name, '\n'.join(lines_out)) + +# ______________________________________________________________________ +# End of control_flow.py diff --git a/llpython/gen_bytecode_visitor.py b/llpython/gen_bytecode_visitor.py new file mode 100644 index 0000000..a60b345 --- /dev/null +++ b/llpython/gen_bytecode_visitor.py @@ -0,0 +1,26 @@ +# ______________________________________________________________________ +from __future__ import absolute_import +from . import opcode_util + +# ______________________________________________________________________ + +def generate_bytecode_visitor (classname = 'BytecodeVisitor', + baseclass = 'object'): + opnames = list(set((opname.split('+')[0] + for opname in opcode_util.OPCODE_MAP.keys()))) + opnames.sort() + return 'class %s (%s):\n%s\n' % ( + classname, baseclass, + '\n\n'.join((' def op_%s (self, i, op, arg):\n' + ' raise NotImplementedError("%s.op_%s")' % + (opname, classname, opname) + for opname in opnames))) + +# ______________________________________________________________________ + +if __name__ == "__main__": + import sys + print(generate_bytecode_visitor(*sys.argv[1:])) + +# ______________________________________________________________________ +# End of gen_bytecode_visitor.py diff --git a/llpython/nobitey.py b/llpython/nobitey.py new file mode 100644 index 0000000..4236d29 --- /dev/null +++ b/llpython/nobitey.py @@ -0,0 +1,367 @@ +# ______________________________________________________________________ +from __future__ import absolute_import +import sys +import os.path +import imp +import io +import types + +import llvm.core as lc +import llvm.ee as le + +from . import bytetype, byte_translator +from .pyaddfunc import pyaddfunc + +LLVM_TO_INT_PARSE_STR_MAP = { + 8 : 'b', + 16 : 'h', + 32 : 'i', # Note that on 32-bit systems sizeof(int) == sizeof(long) + 64 : 'L', # Seeing sizeof(long long) == 8 on both 32 and 64-bit platforms +} + +LLVM_TO_PARSE_STR_MAP = { + lc.TYPE_FLOAT : 'f', + lc.TYPE_DOUBLE : 'd', +} + +# ______________________________________________________________________ + +# XXX Stolen from numba.translate + +def get_string_constant (module, const_str): + const_name = "__STR_%x" % (hash(const_str),) + try: + ret_val = module.get_global_variable_named(const_name) + except: + lconst_str = lc.Constant.stringz(const_str) + ret_val = module.add_global_variable(lconst_str.type, const_name) + ret_val.initializer = lconst_str + ret_val.linkage = lc.LINKAGE_INTERNAL + return ret_val + +# ______________________________________________________________________ + +class NoBitey (object): + def __init__ (self, target_module = None, type_annotations = None): + if target_module is None: + target_module = lc.Module.new('NoBitey_%d' % id(self)) + if type_annotations is None: + type_annotations = {} + self.target_module = target_module + self.type_aliases = type_annotations # Reserved for future use. + + def _build_parse_string (self, llvm_type): + kind = llvm_type.kind + if kind == lc.TYPE_INTEGER: + ret_val = LLVM_TO_INT_PARSE_STR_MAP[llvm_type.width] + elif kind in LLVM_TO_PARSE_STR_MAP: + ret_val = LLVM_TO_PARSE_STR_MAP[kind] + else: + raise TypeError('Unsupported LLVM type: %s' % str(llvm_type)) + return ret_val + + def build_parse_string (self, llvm_tys): + """Given a set of LLVM types, return a string for parsing + them via PyArg_ParseTuple.""" + return ''.join((self._build_parse_string(ty) + for ty in llvm_tys)) + + def handle_abi_casts (self, builder, result): + if result.type.kind == lc.TYPE_FLOAT: + # NOTE: The C ABI apparently casts floats to doubles when + # an argument must be pushed on the stack, as is the case + # when calling a variable argument function. + # XXX Is there documentation on this where I can find all + # coercion rules? Do we still need some libffi + # integration? + result = builder.fpext(result, bytetype.ldouble) + return result + + def build_wrapper_function (self, llvm_function, engine = None): + arg_types = llvm_function.type.pointee.args + return_type = llvm_function.type.pointee.return_type + li32_0 = lc.Constant.int(bytetype.li32, 0) + def get_llvm_function (builder): + if self.target_module != llvm_function.module: + llvm_function_ptr = self.target_module.add_global_variable( + llvm_function.type, llvm_function.name) + llvm_function_ptr.initializer = lc.Constant.inttoptr( + lc.Constant.int( + bytetype.liptr, + engine.get_pointer_to_function(llvm_function)), + llvm_function.type) + llvm_function_ptr.linkage = lc.LINKAGE_INTERNAL + ret_val = builder.load(llvm_function_ptr) + else: + ret_val = llvm_function + return ret_val + def build_parse_args (builder): + return [builder.alloca(arg_type) for arg_type in arg_types] + def build_parse_string (builder): + parse_str = get_string_constant( + self.target_module, self.build_parse_string(arg_types)) + return builder.gep(parse_str, (li32_0, li32_0)) + def load_target_args (builder, args): + return [builder.load(arg) for arg in args] + def build_build_string (builder): + build_str = get_string_constant( + self.target_module, self._build_parse_string(return_type)) + return builder.gep(build_str, (li32_0, li32_0)) + handle_abi_casts = self.handle_abi_casts + target_function_name = llvm_function.name + "_wrapper" + # __________________________________________________ + @byte_translator.llpython(bytetype.l_pyfunc, self.target_module, + **locals()) + def _wrapper (self, args): + ret_val = l_pyobj_p(0) + parse_args = build_parse_args() + parse_result = PyArg_ParseTuple(args, build_parse_string(), + *parse_args) + if parse_result != li32(0): + thread_state = PyEval_SaveThread() + target_args = load_target_args(parse_args) + llresult = handle_abi_casts(get_llvm_function()(*target_args)) + PyEval_RestoreThread(thread_state) + ret_val = Py_BuildValue(build_build_string(), llresult) + return ret_val + # __________________________________________________ + return _wrapper + + def wrap_llvm_module (self, llvm_module, engine = None, py_module = None): + ''' + Shamefully adapted from bitey.bind.wrap_llvm_module(). + ''' + functions = [func for func in llvm_module.functions + if not func.name.startswith("_") + and not func.is_declaration + and func.linkage == lc.LINKAGE_EXTERNAL] + if engine is None: + engine = le.ExecutionEngine.new(llvm_module) + wrappers = [self.build_wrapper_function(func, engine) + for func in functions] + if __debug__: print(self.target_module) + if self.target_module != llvm_module: + engine.add_module(self.target_module) + py_wrappers = [pyaddfunc(wrapper.name, + engine.get_pointer_to_function(wrapper)) + for wrapper in wrappers] + if py_module: + for py_wrapper in py_wrappers: + setattr(py_module, py_wrapper.__name__[:-8], py_wrapper) + setattr(py_module, '_llvm_module', llvm_module) + setattr(py_module, '_llvm_engine', engine) + if self.target_module != llvm_module: + setattr(py_module, '_llvm_wrappers', self.target_module) + return engine, py_wrappers + + def wrap_llvm_module_in_python (self, llvm_module, py_module = None): + ''' + Mildly reworked and abstracted bitey.bind.wrap_llvm_bitcode(). + Abstracted to accept any existing LLVM Module object, and + return a Python wrapper module (even if one wasn't originally + specified). + ''' + if py_module is None: + py_module = types.ModuleType(str(llvm_module.id)) + engine = le.ExecutionEngine.new(llvm_module) + self.wrap_llvm_module(llvm_module, engine, py_module) + return py_module + + def wrap_llvm_bitcode (self, bitcode, py_module = None): + ''' + Intended to be drop-in replacement of + bitey.bind.wrap_llvm_bitcode(). + ''' + return self.wrap_llvm_module_in_python( + lc.Module.from_bitcode(io.BytesIO(bitcode)), py_module) + + def wrap_llvm_assembly (self, llvm_asm, py_module = None): + return self.wrap_llvm_module_in_python( + lc.Module.from_assembly(io.BytesIO(llvm_asm)), py_module) + +# ______________________________________________________________________ + +class NoBiteyLoader(object): + """ + Load LLVM compiled bitcode and autogenerate a ctypes binding. + + Initially copied and adapted from bitey.loader module. + """ + def __init__(self, pkg, name, source, preload, postload): + self.package = pkg + self.name = name + self.fullname = '.'.join((pkg,name)) + self.source = source + self.preload = preload + self.postload = postload + + @classmethod + def _check_magic(cls, filename): + if os.path.exists(filename): + magic = open(filename,"rb").read(4) + if magic == b'\xde\xc0\x17\x0b': + return True + elif magic[:2] == b'\x42\x43': + return True + else: + return False + else: + return False + + @classmethod + def build_module(cls, fullname, source_path, source_data, preload=None, + postload=None): + name = fullname.split(".")[-1] + mod = imp.new_module(name) + if preload: + exec(preload, mod.__dict__, mod.__dict__) + type_annotations = getattr(mod, '_type_annotations', None) + nb = NoBitey(type_annotations = type_annotations) + if source_path.endswith(('.o', '.bc')): + nb.wrap_llvm_bitcode(source_data, mod) + elif source_path.endswith('.s'): + nb.wrap_llvm_assembly(source_data, mod) + if postload: + exec(postload, mod.__dict__, mod.__dict__) + return mod + + @classmethod + def find_module(cls, fullname, paths = None): + if paths is None: + paths = sys.path + names = fullname.split('.') + modname = names[-1] + source_paths = None + for f in paths: + path = os.path.join(os.path.realpath(f), modname) + source = path + '.o' + if cls._check_magic(source): + source_paths = path, source + break + source = path + '.bc' + if os.path.exists(source): + source_paths = path, source + break + source = path + '.s' + if os.path.exists(source): + source_paths = path, source + break + if source_paths: + path, source = source_paths + return cls('.'.join(names[:-1]), modname, source, + path + ".pre.py", path + ".post.py") + + def get_code(self, module): + pass + + def get_data(self, module): + pass + + def get_filename(self, name): + return self.source + + def get_source(self, name): + with open(self.source, 'rb') as f: + return f.read() + + def is_package(self, *args, **kw): + return False + + def load_module(self, fullname): + if fullname in sys.modules: + return sys.modules[fullname] + + preload = None + postload = None + + # Get the preload file (if any) + if os.path.exists(self.preload): + with open(self.preload) as f: + preload = f.read() + + # Get the source + with open(self.source, 'rb') as f: + source_data = f.read() + + # Get the postload file (if any) + if os.path.exists(self.postload): + with open(self.postload) as f: + postload = f.read() + + mod = self.build_module(fullname, self.get_filename(None), source_data, + preload, postload) + sys.modules[fullname] = mod + mod.__loader__ = self + mod.__file__ = self.source + return mod + + @classmethod + def install(cls): + if cls not in sys.meta_path: + sys.meta_path.append(cls) + + @classmethod + def remove(cls): + sys.meta_path.remove(cls) + +# ______________________________________________________________________ + +def _mk_add_42 (llvm_module, at_type = bytetype.lc_long): + f = llvm_module.add_function( + lc.Type.function(at_type, [at_type]), 'add_42_%s' % str(at_type)) + block = f.append_basic_block('entry') + builder = lc.Builder.new(block) + if at_type.kind == lc.TYPE_INTEGER: + const_42 = lc.Constant.int(at_type, 42) + add = builder.add + elif at_type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): + const_42 = lc.Constant.real(at_type, 42.) + add = builder.fadd + else: + raise TypeError('Unsupported type: %s' % str(at_type)) + builder.ret(add(f.args[0], const_42)) + return f + +# ______________________________________________________________________ + +def build_test_module (): + llvm_module = lc.Module.new('nobitey_test') + for ty in (bytetype.li32, bytetype.li64, bytetype.lfloat, + bytetype.ldouble): + fn = _mk_add_42(llvm_module, ty) + return llvm_module + +# ______________________________________________________________________ + +def test_wrap_module (arg = None): + # Build up a module. + m = build_test_module() + if arg and arg.lower() == 'separated': + wrap_module = NoBitey().wrap_llvm_module_in_python(m) + else: + wrap_module = NoBitey(m).wrap_llvm_module_in_python(m) + # Now try running the generated wrappers. + for py_wf_name in ('add_42_i32', 'add_42_i64', 'add_42_float', + 'add_42_double'): + py_wf = getattr(wrap_module, py_wf_name) + for i in range(42): + result = py_wf(i) + expected = i + 42 + assert result == expected, "%r != %r in %r" % ( + result, expected, py_wf) + return wrap_module + +# ______________________________________________________________________ + +def main (*args): + if args: + for arg in args: + test_wrap_module(arg) + else: + test_wrap_module() + +if __name__ == "__main__": + main(*sys.argv[1:]) + +# ______________________________________________________________________ +# End of nobitey.py diff --git a/llpython/opcode_util.py b/llpython/opcode_util.py new file mode 100644 index 0000000..7a1972b --- /dev/null +++ b/llpython/opcode_util.py @@ -0,0 +1,225 @@ +# ______________________________________________________________________ + +import dis +import opcode + +# ______________________________________________________________________ +# Module data + +hasjump = opcode.hasjrel + opcode.hasjabs +hascbranch = [op for op in hasjump + if 'IF' in opcode.opname[op] + or opcode.opname[op] in ('FOR_ITER', 'SETUP_LOOP')] + +# Since the actual opcode value may change, manage opcode abstraction +# data by opcode name. + +OPCODE_MAP = { + 'BINARY_ADD': (2, 1, None), + 'BINARY_AND': (2, 1, None), + 'BINARY_DIVIDE': (2, 1, None), + 'BINARY_FLOOR_DIVIDE': (2, 1, None), + 'BINARY_LSHIFT': (2, 1, None), + 'BINARY_MODULO': (2, 1, None), + 'BINARY_MULTIPLY': (2, 1, None), + 'BINARY_OR': (2, 1, None), + 'BINARY_POWER': (2, 1, None), + 'BINARY_RSHIFT': (2, 1, None), + 'BINARY_SUBSCR': (2, 1, None), + 'BINARY_SUBTRACT': (2, 1, None), + 'BINARY_TRUE_DIVIDE': (2, 1, None), + 'BINARY_XOR': (2, 1, None), + 'BREAK_LOOP': (0, None, 1), + 'BUILD_CLASS': (None, None, None), + 'BUILD_LIST': (-1, 1, None), + 'BUILD_MAP': (None, None, None), + 'BUILD_SET': (None, None, None), + 'BUILD_SLICE': (None, None, None), + 'BUILD_TUPLE': (-1, 1, None), + 'CALL_FUNCTION': (-2, 1, None), + 'CALL_FUNCTION_KW': (-3, 1, None), + 'CALL_FUNCTION_VAR': (-3, 1, None), + 'CALL_FUNCTION_VAR_KW': (-4, 1, None), + 'COMPARE_OP': (2, 1, None), + 'CONTINUE_LOOP': (None, None, None), + 'DELETE_ATTR': (1, None, 1), + 'DELETE_DEREF': (None, None, None), + 'DELETE_FAST': (0, None, 1), + 'DELETE_GLOBAL': (0, None, 1), + 'DELETE_NAME': (0, None, 1), + 'DELETE_SLICE+0': (1, None, 1), + 'DELETE_SLICE+1': (2, None, 1), + 'DELETE_SLICE+2': (2, None, 1), + 'DELETE_SLICE+3': (3, None, 1), + 'DELETE_SUBSCR': (2, None, 1), + 'DUP_TOP': (None, None, None), + 'DUP_TOPX': (None, None, None), + 'DUP_TOP_TWO': (None, None, None), + 'END_FINALLY': (None, None, None), + 'EXEC_STMT': (None, None, None), + 'EXTENDED_ARG': (None, None, None), + 'FOR_ITER': (1, 1, 1), + 'GET_ITER': (1, 1, None), + 'IMPORT_FROM': (None, None, None), + 'IMPORT_NAME': (None, None, None), + 'IMPORT_STAR': (1, None, 1), + 'INPLACE_ADD': (2, 1, None), + 'INPLACE_AND': (2, 1, None), + 'INPLACE_DIVIDE': (2, 1, None), + 'INPLACE_FLOOR_DIVIDE': (2, 1, None), + 'INPLACE_LSHIFT': (2, 1, None), + 'INPLACE_MODULO': (2, 1, None), + 'INPLACE_MULTIPLY': (2, 1, None), + 'INPLACE_OR': (2, 1, None), + 'INPLACE_POWER': (2, 1, None), + 'INPLACE_RSHIFT': (2, 1, None), + 'INPLACE_SUBTRACT': (2, 1, None), + 'INPLACE_TRUE_DIVIDE': (2, 1, None), + 'INPLACE_XOR': (2, 1, None), + 'JUMP_ABSOLUTE': (0, None, 1), + 'JUMP_FORWARD': (0, None, 1), + 'JUMP_IF_FALSE': (1, 1, 1), + 'JUMP_IF_FALSE_OR_POP': (None, None, None), + 'JUMP_IF_TRUE': (1, 1, 1), + 'JUMP_IF_TRUE_OR_POP': (None, None, None), + 'LIST_APPEND': (2, 0, 1), + 'LOAD_ATTR': (1, 1, None), + 'LOAD_BUILD_CLASS': (None, None, None), + 'LOAD_CLOSURE': (None, None, None), + 'LOAD_CONST': (0, 1, None), + 'LOAD_DEREF': (0, 1, None), + 'LOAD_FAST': (0, 1, None), + 'LOAD_GLOBAL': (0, 1, None), + 'LOAD_LOCALS': (None, None, None), + 'LOAD_NAME': (0, 1, None), + 'MAKE_CLOSURE': (None, None, None), + 'MAKE_FUNCTION': (-2, 1, None), + 'MAP_ADD': (None, None, None), + 'NOP': (0, None, None), + 'POP_BLOCK': (0, None, 1), + 'POP_EXCEPT': (None, None, None), + 'POP_JUMP_IF_FALSE': (1, None, 1), + 'POP_JUMP_IF_TRUE': (1, None, 1), + 'POP_TOP': (1, None, 1), + 'PRINT_EXPR': (1, None, 1), + 'PRINT_ITEM': (1, None, 1), + 'PRINT_ITEM_TO': (2, None, 1), + 'PRINT_NEWLINE': (0, None, 1), + 'PRINT_NEWLINE_TO': (1, None, 1), + 'RAISE_VARARGS': (None, None, None), + 'RETURN_VALUE': (1, None, 1), + 'ROT_FOUR': (None, None, None), + 'ROT_THREE': (None, None, None), + 'ROT_TWO': (None, None, None), + 'SETUP_EXCEPT': (None, None, None), + 'SETUP_FINALLY': (None, None, None), + 'SETUP_LOOP': (None, None, None), + 'SETUP_WITH': (None, None, None), + 'SET_ADD': (None, None, None), + 'SLICE+0': (1, 1, None), + 'SLICE+1': (2, 1, None), + 'SLICE+2': (2, 1, None), + 'SLICE+3': (3, 1, None), + 'STOP_CODE': (None, None, None), + 'STORE_ATTR': (2, None, 1), + 'STORE_DEREF': (1, 0, 1), + 'STORE_FAST': (1, None, 1), + 'STORE_GLOBAL': (1, None, 1), + 'STORE_LOCALS': (None, None, None), + 'STORE_MAP': (1, None, 1), + 'STORE_NAME': (1, None, 1), + 'STORE_SLICE+0': (1, None, 1), + 'STORE_SLICE+1': (2, None, 1), + 'STORE_SLICE+2': (2, None, 1), + 'STORE_SLICE+3': (3, None, 1), + 'STORE_SUBSCR': (3, None, 1), + 'UNARY_CONVERT': (1, 1, None), + 'UNARY_INVERT': (1, 1, None), + 'UNARY_NEGATIVE': (1, 1, None), + 'UNARY_NOT': (1, 1, None), + 'UNARY_POSITIVE': (1, 1, None), + 'UNPACK_EX': (None, None, None), + 'UNPACK_SEQUENCE': (None, None, None), + 'WITH_CLEANUP': (None, None, None), + 'YIELD_VALUE': (1, None, 1), +} + +# ______________________________________________________________________ +# Module functions + +def itercode(code, start = 0): + """Return a generator of byte-offset, opcode, and argument + from a byte-code-string + """ + i = 0 + extended_arg = 0 + if isinstance(code[0], str): + code = [ord(c) for c in code] + n = len(code) + while i < n: + op = code[i] + num = i + start + i = i + 1 + oparg = None + if op >= opcode.HAVE_ARGUMENT: + oparg = code[i] + (code[i + 1] * 256) + extended_arg + extended_arg = 0 + i = i + 2 + if op == opcode.EXTENDED_ARG: + extended_arg = oparg * 65536 + + delta = yield num, op, oparg + if delta is not None: + abs_rel, dst = delta + assert abs_rel == 'abs' or abs_rel == 'rel' + i = dst if abs_rel == 'abs' else i + dst + +# ______________________________________________________________________ + +def extendlabels(code, labels = None): + """Extend the set of jump target labels to account for the + passthrough targets of conditional branches. + + This allows us to create a control flow graph where there is at + most one branch per basic block. + """ + if labels is None: + labels = [] + if isinstance(code[0], str): + code = [ord(c) for c in code] + n = len(code) + i = 0 + while i < n: + op = code[i] + i += 1 + if op >= dis.HAVE_ARGUMENT: + i += 2 + label = -1 + if op in hasjump: + label = i + if label >= 0: + if label not in labels: + labels.append(label) + elif op == opcode.opmap['BREAK_LOOP']: + if i not in labels: + labels.append(i) + return labels + +# ______________________________________________________________________ + +def get_code_object (func): + return getattr(func, '__code__', getattr(func, 'func_code', None)) + +# ______________________________________________________________________ + +def build_basic_blocks (co_obj): + co_code = co_obj.co_code + labels = extendlabels(co_code, dis.findlabels(co_code)) + labels.sort() + blocks = dict((index, list(itercode(co_code[index:next_index], index))) + for index, next_index in zip([0] + labels, + labels + [len(co_code)])) + return blocks + +# ______________________________________________________________________ +# End of opcode_util.py diff --git a/llpython/phi_injector.py b/llpython/phi_injector.py new file mode 100644 index 0000000..dfa1061 --- /dev/null +++ b/llpython/phi_injector.py @@ -0,0 +1,153 @@ +# ______________________________________________________________________ + +from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin + +# ______________________________________________________________________ + +synthetic_opname = [] +synthetic_opmap = {} + +def def_synth_op (opname): + global synthetic_opname, synthetic_opmap + ret_val = -(len(synthetic_opname) + 1) + synthetic_opname.insert(0, opname) + synthetic_opmap[opname] = ret_val + return ret_val + +REF_ARG = def_synth_op('REF_ARG') +BUILD_PHI = def_synth_op('BUILD_PHI') +DEFINITION = def_synth_op('DEFINITION') +REF_DEF = def_synth_op('REF_DEF') + +# ______________________________________________________________________ + +class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): + '''Transformer responsible for modifying a bytecode flow, removing + LOAD_FAST and STORE_FAST opcodes, and replacing them with a static + single assignment (SSA) representation. + + In order to support SSA, PhiInjector adds the following synthetic + opcodes to transformed flows: + + * REF_ARG: Specifically reference an incomming argument value. + + * BUILD_PHI: Build a phi node to disambiguate between several + possible definitions at a control flow join. + + * DEFINITION: Unique value definition indexed by the "arg" field + in the tuple. + + * REF_DEF: Reference a specific value definition.''' + + def visit_cfg (self, cfg, nargs = 0, *args, **kws): + self.cfg = cfg + ret_val = self.visit(cfg.blocks, nargs) + del self.cfg + return ret_val + + def visit (self, flow, nargs = 0, *args, **kws): + self.nargs = nargs + self.definitions = [] + self.phis = [] + self.prev_blocks = [] + self.blocks_locals = dict((block, {}) + for block in self.cfg.blocks.keys()) + ret_val = super(PhiInjector, self).visit(flow, *args, **kws) + for block, _, _, args, _ in self.phis: + local = args.pop() + reaching_definitions = self.cfg.reaching_definitions[block] + for prev in reaching_definitions.keys(): + if 0 in self.cfg.blocks_reaching[prev]: + args.append((prev, REF_DEF, 'REF_DEF', + self.blocks_locals[prev][local], ())) + args.sort() + del self.blocks_locals + del self.prev_blocks + del self.phis + del self.definitions + del self.nargs + return ret_val + + def add_definition (self, index, local, arg): + definition_index = len(self.definitions) + definition = (index, DEFINITION, 'DEFINITION', definition_index, + (arg,)) + self.definitions.append(definition) + self.blocks_locals[self.block][local] = definition_index + return definition + + def add_phi (self, index, local): + ret_val = (index, BUILD_PHI, 'BUILD_PHI', [local], ()) + self.phis.append(ret_val) + return ret_val + + def enter_block (self, block): + ret_val = False + self.block = block + if block == 0: + if self.nargs > 0: + ret_val = [self.add_definition(-1, arg, + (-1, REF_ARG, 'REF_ARG', arg, + ())) + for arg in range(self.nargs)] + else: + ret_val = True + elif 0 in self.cfg.blocks_reaching[block]: + ret_val = True + prev_block_locals = None + for pred_block in self.cfg.blocks_in[block]: + if pred_block in self.prev_blocks: + prev_block_locals = self.blocks_locals[pred_block] + break + assert prev_block_locals is not None, "Internal translation error" + self.blocks_locals[block] = prev_block_locals.copy() + phis_needed = self.cfg.phi_needed(block) + if phis_needed: + ret_val = [self.add_definition(block, local, + self.add_phi(block, local)) + for local in phis_needed] + return ret_val + + def exit_block (self, block): + if 0 in self.cfg.blocks_reaching[block]: + self.prev_blocks.append(block) + del self.block + + def op_STORE_FAST (self, i, op, arg, *args, **kws): + assert len(args) == 1 + return [self.add_definition(i, arg, args[0])] + + def op_LOAD_FAST (self, i, op, arg, *args, **kws): + return [(i, REF_DEF, 'REF_DEF', self.blocks_locals[self.block][arg], + args)] + +# ______________________________________________________________________ + +def inject_phis (func): + '''Given a Python function, return a bytecode flow object that has + been transformed by a fresh PhiInjector instance.''' + import byte_control, byte_flow + argcount = byte_control.opcode_util.get_code_object(func).co_argcount + cfg = byte_control.build_cfg(func) + cfg.blocks = byte_flow.BytecodeFlowBuilder().visit_cfg(cfg) + return PhiInjector().visit_cfg(cfg, argcount) + +# ______________________________________________________________________ +# Main (self-test) routine + +def main (*args): + import pprint + from tests import llfuncs + if not args: + args = ('doslice',) + for arg in args: + pprint.pprint(inject_phis(getattr(llfuncs, arg))) + +# ______________________________________________________________________ + +if __name__ == "__main__": + import sys + main(*sys.argv[1:]) + +# ______________________________________________________________________ +# End of phi_injector.py diff --git a/llpython/pyaddfunc.py b/llpython/pyaddfunc.py new file mode 100644 index 0000000..d6a2945 --- /dev/null +++ b/llpython/pyaddfunc.py @@ -0,0 +1,40 @@ +# ______________________________________________________________________ + +import ctypes + +# ______________________________________________________________________ +class PyMethodDef (ctypes.Structure): + _fields_ = [ + ('ml_name', ctypes.c_char_p), + ('ml_meth', ctypes.c_void_p), + ('ml_flags', ctypes.c_int), + ('ml_doc', ctypes.c_char_p), + ] + +PyCFunction_NewEx = ctypes.pythonapi.PyCFunction_NewEx +PyCFunction_NewEx.argtypes = (ctypes.POINTER(PyMethodDef), + ctypes.c_void_p, + ctypes.c_void_p) +PyCFunction_NewEx.restype = ctypes.py_object + +cache = {} # Unsure if this is necessary to keep the PyMethodDef + # structures from being garbage collected. Assuming so... + +def pyaddfunc (func_name, func_ptr, func_doc = None): + global cache + if bytes != str: + func_name = bytes(ord(ch) for ch in func_name) + key = (func_name, func_ptr) + if key in cache: + _, ret_val = cache[key] + else: + mdef = PyMethodDef(bytes(func_name), + func_ptr, + 1, # == METH_VARARGS (hopefully remains so...) + func_doc) + ret_val = PyCFunction_NewEx(ctypes.byref(mdef), 0, 0) + cache[key] = (mdef, ret_val) + return ret_val + +# ______________________________________________________________________ +# End of pyaddfunc.py diff --git a/llpython/tests/__init__.py b/llpython/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/llpython/tests/llfuncs.py b/llpython/tests/llfuncs.py new file mode 100644 index 0000000..8b5b1f3 --- /dev/null +++ b/llpython/tests/llfuncs.py @@ -0,0 +1,41 @@ +# ______________________________________________________________________ + +def doslice (in_string, lower, upper): + l = strlen(in_string) + if lower < lc_size_t(0): + lower += l + if upper < lc_size_t(0): + upper += l + temp_len = upper - lower + if temp_len < lc_size_t(0): + temp_len = lc_size_t(0) + ret_val = alloca_array(li8, temp_len + lc_size_t(1)) + strncpy(ret_val, in_string + lower, temp_len) + ret_val[temp_len] = li8(0) + return ret_val + +def ipow (val, exp): + ret_val = 1 + temp = val + w = exp + while w > 0: + if (w & 1) != 0: + ret_val *= temp + # TODO: Overflow check on ret_val + w >>= 1 + if w == 0: break + temp *= temp + # TODO: Overflow check on temp + return ret_val + +def pymod (arg1, arg2): + ret_val = arg1 % arg2 + if ret_val < 0: + if arg2 > 0: + ret_val += arg2 + elif arg2 < 0: + ret_val += arg2 + return ret_val + +# ______________________________________________________________________ +# End of llfuncs.py diff --git a/llpython/tests/llfunctys.py b/llpython/tests/llfunctys.py new file mode 100644 index 0000000..8335044 --- /dev/null +++ b/llpython/tests/llfunctys.py @@ -0,0 +1,19 @@ +# ______________________________________________________________________ + +import llvm.core as lc + +from llpython import bytetype + +# ______________________________________________________________________ + +doslice = lc.Type.function(bytetype.li8_ptr, ( + bytetype.li8_ptr, bytetype.lc_size_t, bytetype.lc_size_t)) + +ipow = lc.Type.function(bytetype.li32, (bytetype.li32, + bytetype.li32)) + +pymod = lc.Type.function(bytetype.li32, (bytetype.li32, + bytetype.li32)) + +# ______________________________________________________________________ +# End of llfunctys.py diff --git a/llrtc/Makefile b/llrtc/Makefile new file mode 100644 index 0000000..b15eac5 --- /dev/null +++ b/llrtc/Makefile @@ -0,0 +1,22 @@ +all: + make -C lib + +ir: + make -C lib ir + +test: + make -C lib test + +clean-test: + make -C lib clean-test + +clean-temp: + make -C lib clean-temp + +clean: + make -C lib clean + +install: ir + cp llrt_*.ll ../llvm/llrt + make -C lib clean-temp + \ No newline at end of file diff --git a/llrtc/README.md b/llrtc/README.md new file mode 100644 index 0000000..539d9c3 --- /dev/null +++ b/llrtc/README.md @@ -0,0 +1,25 @@ +# LLRT: Low Level Runtime + +## Why? + +The same reason for LLVM compiler-rt. LLVM generates libgcc symbols, such as +__divdi3 for 64-bit division on 32-bit platform. They are not also available. +We need to ship compiler-rt but it is not Windows ready. +This subproject aims to provide a small portable subset of compiler-rt. +Start small and add only the things we really needed. +Performance is not crucial but should not be terrible. +Functionality and usefullness should be more important than performance. + +## Developer Instructions + +LLRT implements some functionalities in compiler-rt in ANSI C. +The C files are compiled using clang to produce LLVM IR which are shipped. +The IR files are committed in the repository. +So, remember to build the IR files commit them after modifying the C files. + +## Build Requirement + +- Make +- Clang +- Python + diff --git a/llrtc/lib/.gitignore b/llrtc/lib/.gitignore new file mode 100644 index 0000000..fbcf76a --- /dev/null +++ b/llrtc/lib/.gitignore @@ -0,0 +1,4 @@ +*.o +*.run +*.out +*.ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile new file mode 100644 index 0000000..9dbfb27 --- /dev/null +++ b/llrtc/lib/Makefile @@ -0,0 +1,66 @@ +OUTPUT = llrt +SOURCES = udivmod64.c sdivmod64.c div64.c mod64.c +TESTS = test_udivmod64.c test_sdivmod64.c + +CLANG = clang +LLVM_LINK = llvm-link +CF = -Wall -ansi +CF_TEST = $(CF) -ftrapv +CF_BUILD = $(CF) -O0 -emit-llvm +OUTDIR = .. +STRIPPER = ../tools/striptriple.py + +all: ir + +ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll + +$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ + +$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc) + $(LLVM_LINK) -S $+ -o $@ + python $(STRIPPER) $@ + +build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run) + +lib$(OUTPUT).a: $(SOURCES:.c=.o) + $(CLANG) -static $+ -o $@ + +test: $(TESTS:.c=.run) + for src in $+; do \ + echo "testing $${src}"; \ + python $${src%.*}.py > $${src%.*}.out; \ + done; + +clean-test: + rm -f *.out + rm -f *.o + rm -f *.run + +clean-dist: clean-temp + rm -f *.ll + +clean-temp: + rm -f *.bc + rm -f *.o + rm -f *.out + +clean: clean-test clean-dist + +%.c: llrt.h + +%_x86.bc: %.c + $(CLANG) -m32 $(CF_BUILD) -c $< -o $@ + +%_x86_64.bc: %.c + $(CLANG) -m64 $(CF_BUILD) -c $< -o $@ + +%.o: %.c + $(CLANG) $(CF_TEST) -c $< + +%.run: %.c + $(CLANG) $(CF_TEST) -o $@ $+ + +test_udivmod64.run: udivmod64.o +test_sdivmod64.run: udivmod64.o sdivmod64.o diff --git a/llrtc/lib/div64.c b/llrtc/lib/div64.c new file mode 100644 index 0000000..8466965 --- /dev/null +++ b/llrtc/lib/div64.c @@ -0,0 +1,11 @@ +#include "llrt.h" + +uint64_t udiv64(uint64_t dividend, uint64_t divisor) +{ + return udivmod64(dividend, divisor, NULL); +} + +int64_t sdiv64(int64_t dividend, int64_t divisor) +{ + return sdivmod64(dividend, divisor, NULL); +} diff --git a/llrtc/lib/llrt.h b/llrtc/lib/llrt.h new file mode 100644 index 0000000..4e9e348 --- /dev/null +++ b/llrtc/lib/llrt.h @@ -0,0 +1,19 @@ +#ifndef LLRT_H_ +#define LLRT_H_ + +#include + +#define NULL 0 +#define BITS_PER_BYTE 8 + +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder); +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder); + +uint64_t udiv64(uint64_t dividend, uint64_t divisor); +int64_t sdiv64(int64_t dividend, int64_t divisor); + +uint64_t umod64(uint64_t dividend, uint64_t divisor); +int64_t smod64(int64_t dividend, int64_t divisor); + +#endif /* LLRT_H_ */ + diff --git a/llrtc/lib/mod64.c b/llrtc/lib/mod64.c new file mode 100644 index 0000000..875f6b9 --- /dev/null +++ b/llrtc/lib/mod64.c @@ -0,0 +1,15 @@ +#include "llrt.h" + +uint64_t umod64(uint64_t dividend, uint64_t divisor) +{ + uint64_t rem; + udivmod64(dividend, divisor, &rem); + return rem; +} + +int64_t smod64(int64_t dividend, int64_t divisor) +{ + int64_t rem; + sdivmod64(dividend, divisor, &rem); + return rem; +} diff --git a/llrtc/lib/sdivmod64.c b/llrtc/lib/sdivmod64.c new file mode 100644 index 0000000..df294b3 --- /dev/null +++ b/llrtc/lib/sdivmod64.c @@ -0,0 +1,40 @@ +#include "llrt.h" +#include + +/* +Calls to udivmod64 internally. +Note: remainder uses sign of divisor. +*/ +int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder) +{ + int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1; + int signed_dividend = dividend < 0; + int signed_divisor = divisor < 0; + int signed_result = signed_divisor ^ signed_dividend; + + int64_t quotient; + uint64_t udvd, udvr, uquotient, uremainder; + + udvd = signed_dividend ? -dividend : dividend; + udvr = signed_divisor ? -divisor : divisor; + uquotient = udivmod64(udvd, udvr, &uremainder); + + if (signed_result){ + if (uremainder) { + quotient = -(int64_t)uquotient - 1; + } else { + quotient = -(int64_t)uquotient; + } + if (remainder) { + /* if signed, there could be unsigned overflow + causing undefined behavior */ + *remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor; + } + } else { + quotient = (int64_t)uquotient; + if (remainder) { + *remainder = signed_divisor ? -uremainder : uremainder; + } + } + return quotient; +} diff --git a/llrtc/lib/test_sdivmod64.c b/llrtc/lib/test_sdivmod64.c new file mode 100644 index 0000000..1e804d6 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.c @@ -0,0 +1,21 @@ +#include +#include +#include "llrt.h" + +int main(int argc, char * argv[]){ + int64_t n, d, q, r; + + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%lld", &n); + sscanf(argv[2], "%lld", &d); + + q = sdivmod64(n, d, &r); + + printf("%lld\n", q); + printf("%lld\n", r); + + return 0; +} diff --git a/llrtc/lib/test_sdivmod64.py b/llrtc/lib/test_sdivmod64.py new file mode 100644 index 0000000..4aa49a9 --- /dev/null +++ b/llrtc/lib/test_sdivmod64.py @@ -0,0 +1,56 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_sdivmod64.run') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0x0fffffffffffffff, 0xffff), + (0x7fffffffffffffff, 0x7fffffffffffffff), + (0x7fffffffffffffff, 0x7ffffffffffffff0), + (0x7fffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + testcase(dvd, -dvr) + testcase(-dvd, dvr) + testcase(-dvd, -dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/test_udivmod64.c b/llrtc/lib/test_udivmod64.c new file mode 100644 index 0000000..70b44aa --- /dev/null +++ b/llrtc/lib/test_udivmod64.c @@ -0,0 +1,20 @@ +#include +#include +#include "llrt.h" + +int main(int argc, char * argv[]){ + uint64_t n, d, q, r; + if (argc != 3) { + printf("invalid argument: %s dividend divisor", argv[0]); + return 1; + } + sscanf(argv[1], "%llu", &n); + sscanf(argv[2], "%llu", &d); + + q = udivmod64(n, d, &r); + + printf("%llu\n", q); + printf("%llu\n", r); + + return 0; +} diff --git a/llrtc/lib/test_udivmod64.py b/llrtc/lib/test_udivmod64.py new file mode 100644 index 0000000..da07ccb --- /dev/null +++ b/llrtc/lib/test_udivmod64.py @@ -0,0 +1,53 @@ +import math +import os +import subprocess +udt = os.path.join('.', 'test_udivmod64.run') + +def testcase(dividend, divisor): + print 'divmod64(%d, %d)' % (dividend, divisor) + + procargs = ('%s %s %s' % (udt, dividend, divisor)).split() + result = subprocess.check_output(procargs) + gotQ, gotR = map(int, result.splitlines()) + + expectQ = dividend // divisor + expectR = dividend % divisor + + print 'Q = %d, R = %d' % (gotQ, gotR) + + if expectQ != gotQ: + raise ValueError("invalid quotient: got=%d but expect=%d" % + (gotQ, expectQ)) + if expectR != gotR: + raise ValueError("invalid remainder: got=%d but expect=%d" % + (gotR, expectR)) + print 'OK' + +def testsequence(): + subjects = [ + (0, 1), + (0, 0xffffffffffffffff), + (1, 2), + (1, 983219), + (2, 2), + (3, 2), + (1024, 2), + (2048, 512), + (21321, 512), + (9329189, 1031), + (0xffffffff, 2), + (0xffffffff, 0xffff), + (0x1ffffffff, 2), + (0x1ffffffff, 0xffff), + (0xffff, 0xffffffff), + (0xffffffffffffffff, 0xffff), + (0xffffffffffffffff, 0x7fffffffffffffff), + (0xffffffffffffffff, 0xfffffffffffffff0), + (0xffffffffffffffff, 87655678587161901), + ] + + for dvd, dvr in subjects: + testcase(dvd, dvr) + +if __name__ == '__main__': + testsequence() diff --git a/llrtc/lib/udivmod64.c b/llrtc/lib/udivmod64.c new file mode 100644 index 0000000..5936f98 --- /dev/null +++ b/llrtc/lib/udivmod64.c @@ -0,0 +1,84 @@ +/* +Implements unsigned divmod using for platform missing 64-bit division and/or +modulo functions. +*/ +#include "llrt.h" + +/* +count left zero for 64-bit words + +*/ +static +int clz64(uint64_t x) +{ + const int total_bits = sizeof(x) * BITS_PER_BYTE; + int zc = 0; + + while (zc < total_bits && ((x >> (total_bits - zc - 1)) & 1) == 0) { + ++zc; + } + return zc; +} + +typedef struct div_state_ +{ + uint64_t tmp, dvd; +} div_state; + +/* +Left shift div_state by 1 bit +*/ +static +void div_state_lshift(div_state *state) +{ + state->tmp = (state->tmp << 1) | (state->dvd >> 63); + state->dvd = state->dvd << 1; +} + +/* +Division of unsigned 64-bit word using 64-bit addition and subtration following +the shift-restore division algorithm. +For those interested in 32-bit implementation, +mapping of 64-bit addition and subtraction to 32-bit should be trivial. + +Reference: + - IBM. The PowerPC Compiler Writer's Guide + - LLVM compiler-rt + +Assumptions: + - all operands and results are positive + - unsigned wrapped around +*/ +uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder) +{ + div_state state = {0, dividend}; + uint64_t quotient = 0; + int i; + int skipahead; + + if (divisor == 0) { + return 1 / 0; /* intentionally div by zero */ + } + + /* + skipahead to reduce iteration + */ + skipahead = clz64(dividend); + + for (i = 0; i < skipahead; ++i) { + div_state_lshift(&state); + } + + /* + division loop + */ + for (i = skipahead; i < 64; ++i) { + div_state_lshift(&state); + if (state.tmp >= divisor) { + state.tmp = state.tmp - divisor; + quotient |= 1ull << (63 - i); + } + } + if (remainder) *remainder = state.tmp; + return quotient; +} diff --git a/llrtc/tools/striptriple.py b/llrtc/tools/striptriple.py new file mode 100644 index 0000000..a20ba34 --- /dev/null +++ b/llrtc/tools/striptriple.py @@ -0,0 +1,15 @@ +import sys +import re + +buf = [] +with open(sys.argv[1], 'r') as fin: + tripleline = re.compile('^target\s+triple\s+=\s+') + for line in fin.readlines(): + if not tripleline.match(line): + buf.append(line) + +with open(sys.argv[1], 'w') as fout: + for line in buf: + fout.write(line) + + diff --git a/llvm-config-win32.py b/llvm-config-win32.py index 0e70231..3f756ee 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -1,76 +1,88 @@ -import sys, os +import re +import sys +from distutils.spawn import find_executable +from os.path import abspath, dirname, isfile, join +from os import listdir +from subprocess import Popen, PIPE -def find_path_of(filename, envvar='PATH'): - """Finds the path from $PATH where the file exists, returns None if not found.""" - pathlist = os.getenv(envvar).split(os.pathsep) - for path in pathlist: - if os.path.exists(os.path.join(path, filename)): - return os.path.abspath(path) - return None -if sys.argv[1] == '--version': - cmd = 'llvm-tblgen --version' - # Hardcoded extraction, only tested on llvm 3.1 - result = os.popen(cmd).read().split('\n')[1].strip().split(' ')[2] - print result -elif sys.argv[1] == '--libs': +def find_llvm_tblgen(): + path = find_executable('llvm-tblgen') + if path is None: + sys.exit('Error: could not locate llvm-tblgen') + return path + + +def find_llvm_prefix(): + return abspath(dirname(dirname(find_llvm_tblgen()))) + + +def ensure_file(path): + if not isfile(path): + sys.exit('Error: no file: %r' % path) + + +def get_llvm_version(): + args = [find_llvm_tblgen(), '--version'] + p = Popen(args, stdout=PIPE, stderr=PIPE) + stdout, stderr = p.communicate() + if stderr: + sys.exit("Error: %r stderr is:\n%s" % (args, stderr.decode())) + out = stdout.decode().strip() + pat = re.compile(r'llvm\s+version\s+(\d+\.\d+\S*)', re.I) + m = pat.search(out) + if m is None: + sys.exit('Error: could not parse version in:' + out) + return m.group(1) + + +def libs_options(): # NOTE: instead of actually looking at the components requested, - # we just spit out a bunch of libs + # we just print out a bunch of libs for lib in """ -LLVMAnalysis -LLVMAsmParser -LLVMAsmPrinter -LLVMBitReader -LLVMBitWriter -LLVMCodeGen -LLVMCore -LLVMExecutionEngine -LLVMInstCombine -LLVMInstrumentation -LLVMInterpreter -LLVMipa -LLVMipo -LLVMJIT -LLVMLinker -LLVMMC -LLVMMCParser -LLVMScalarOpts -LLVMSelectionDAG -LLVMSupport -LLVMTarget -LLVMTransformUtils -LLVMVectorize -LLVMX86AsmParser -LLVMX86AsmPrinter -LLVMX86CodeGen -LLVMX86Desc -LLVMX86Info -LLVMX86Utils Advapi32 Shell32 """.split(): print('-l%s' % lib) - # Look for the PTX .lib in %LIBPATH% - if find_path_of('LLVMPTXCodeGen.lib', 'LIBPATH') != None: - print('-lLLVMPTXAsmPrinter') - print('-lLLVMPTXCodeGen') - print('-lLLVMPTXDesc') - print('-lLLVMPTXInfo') -elif sys.argv[1] == '--includedir': - llvmbin = find_path_of('llvm-tblgen.exe') - if llvmbin is None: - raise RuntimeError('Could not find LLVM') - incdir = os.path.abspath(os.path.join(llvmbin, '../include')) - if not os.path.exists(os.path.join(incdir, 'llvm/BasicBlock.h')): - raise RuntimeError('Could not find LLVM include dir') - print incdir -elif sys.argv[1] == '--libdir': - llvmbin = find_path_of('llvm-tblgen.exe') - if llvmbin is None: - raise RuntimeError('Could not find LLVM') - libdir = os.path.abspath(os.path.join(llvmbin, '../lib')) - if not os.path.exists(os.path.join(libdir, 'LLVMCore.lib')): - raise RuntimeError('Could not find LLVM lib dir') - print libdir -else: - raise RuntimeError('Unrecognized llvm-config command %s' % sys.argv[1]) + + bpath = join(find_llvm_prefix(), 'lib') + for filename in listdir(bpath): + filepath = join(bpath, filename) + if isfile(filepath) and filename.endswith('.lib') and filename.startswith('LLVM'): + name = filename.split('.', 1)[0] + print('-l%s' % name) + +def main(): + try: + option = sys.argv[1] + except IndexError: + sys.exit('Error: option missing') + + if option == '--version': + print(get_llvm_version()) + + elif option == '--targets-built': + print('X86') # just do X86 + + elif option == '--libs': + libs_options() + + elif option == '--includedir': + incdir = join(find_llvm_prefix(), 'include') + ensure_file(join(incdir, 'llvm' , 'Linker.h')) + print(incdir) + + elif option == '--libdir': + libdir = join(find_llvm_prefix(), 'lib') + ensure_file(join(libdir, 'LLVMCore.lib')) + print(libdir) + + elif option in ('--ldflags', '--components'): + pass + + else: + sys.exit('Error: Unrecognized llvm-config option %r' % option) + + +if __name__ == '__main__': + main() diff --git a/llvm/2.9_update.diff b/llvm/2.9_update.diff deleted file mode 100644 index 5572286..0000000 --- a/llvm/2.9_update.diff +++ /dev/null @@ -1,2117 +0,0 @@ -Index: core.py -=================================================================== ---- core.py (revision 105) -+++ core.py (working copy) -@@ -51,14 +51,15 @@ - TYPE_FP128 = 4 - TYPE_PPC_FP128 = 5 - TYPE_LABEL = 6 --TYPE_INTEGER = 7 --TYPE_FUNCTION = 8 --TYPE_STRUCT = 9 --TYPE_ARRAY = 10 --TYPE_POINTER = 11 --TYPE_OPAQUE = 12 --TYPE_VECTOR = 13 --TYPE_METADATA = 14 -+TYPE_METADATA = 7 -+TYPE_X86_MMX = 8 -+TYPE_INTEGER = 9 -+TYPE_FUNCTION = 10 -+TYPE_STRUCT = 11 -+TYPE_ARRAY = 12 -+TYPE_POINTER = 13 -+TYPE_OPAQUE = 14 -+TYPE_VECTOR = 15 - - # value IDs (llvm::Value::ValueTy enum) - VALUE_ARGUMENT = 0 -@@ -140,11 +141,21 @@ - OPCODE_INSERTVALUE = 54 - - # calling conventions --CC_C = 0 --CC_FASTCALL = 8 --CC_COLDCALL = 9 --CC_X86_STDCALL = 64 --CC_X86_FASTCALL = 65 -+CC_C = 0 -+CC_FASTCALL = 8 -+CC_COLDCALL = 9 -+CC_GHC = 10 -+CC_X86_STDCALL = 64 -+CC_X86_FASTCALL = 65 -+CC_ARM_APCS = 66 -+CC_ARM_AAPCS = 67 -+CC_ARM_AAPCS_VFP = 68 -+CC_MSP430_INTR = 69 -+CC_X86_THISCALL = 70 -+CC_PTX_KERNEL = 71 -+CC_PTX_DEVICE = 72 -+CC_MBLAZE_INTR = 73 -+CC_MBLAZE_SVOL = 74 - - # int predicates - ICMP_EQ = 32 -@@ -248,11 +259,14 @@ - ATTR_OPTIMIZE_FOR_SIZE = 1<<13 - ATTR_STACK_PROTECT = 1<<14 - ATTR_STACK_PROTECT_REQ = 1<<15 -+ATTR_ALIGNMENT = 1<<16 - ATTR_NO_CAPTURE = 1<<21 - ATTR_NO_REDZONE = 1<<22 - ATTR_NO_IMPLICIT_FLOAT = 1<<23 - ATTR_NAKED = 1<<24 - ATTR_INLINE_HINT = 1<<25 -+ATTR_STACK_ALIGNMENT = 7<<26 -+ATTR_HOTPATCH = 1<<29 - - # intrinsic IDs - from llvm._intrinsic_ids import * -Index: extra.cpp -=================================================================== ---- extra.cpp (revision 105) -+++ extra.cpp (working copy) -@@ -54,7 +54,7 @@ - #include "llvm/IntrinsicInst.h" - #include "llvm/Analysis/Verifier.h" - #include "llvm/Assembly/Parser.h" --#include "llvm/System/DynamicLibrary.h" -+#include "llvm/Support/DynamicLibrary.h" - #include "llvm/PassManager.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/Analysis/LoopPass.h" -@@ -452,12 +452,19 @@ - return eep->getPointerToFunction(fnp); - } - -+ - int LLVMInlineFunction(LLVMValueRef call) - { - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - -- llvm::CallSite cs = llvm::CallSite::get(callp); -+// llvm::CallSite cs = llvm::CallSite::get(callp); -+ llvm::CallSite cs; -+ llvm::Instruction *II = llvm::dyn_cast(callp); -+ if (II->getOpcode() == llvm::Instruction::Call) -+ cs = llvm::CallSite(static_cast(II)); -+ else if (II->getOpcode() == llvm::Instruction::Invoke) -+ cs = llvm::CallSite(static_cast(II)); - - llvm::InlineFunctionInfo unused; - return llvm::InlineFunction(cs, unused); -@@ -501,13 +508,13 @@ - define_pass( DomPrinter ) - define_pass( DomViewer ) - define_pass( EdgeProfiler ) --define_pass( GEPSplitter ) -+//define_pass( GEPSplitter ) - define_pass( GlobalsModRef ) - define_pass( InstCount ) - define_pass( InstructionNamer ) - define_pass( LazyValueInfo ) - define_pass( LCSSA ) --define_pass( LiveValues ) -+//define_pass( LiveValues ) - define_pass( LoopDependenceAnalysis ) - define_pass( LoopExtractor ) - define_pass( LoopSimplify ) -@@ -519,7 +526,7 @@ - define_pass( NoProfileInfo ) - define_pass( OptimalEdgeProfiler ) - define_pass( PartialInlining ) --define_pass( PartialSpecialization ) -+//define_pass( PartialSpecialization ) - define_pass( PostDomOnlyPrinter ) - define_pass( PostDomOnlyViewer ) - define_pass( PostDomPrinter ) -@@ -528,7 +535,7 @@ - define_pass( ProfileLoader ) - define_pass( ProfileVerifier ) - define_pass( ScalarEvolutionAliasAnalysis ) --define_pass( SimplifyHalfPowrLibCalls ) -+//define_pass( SimplifyHalfPowrLibCalls ) - define_pass( SingleLoopExtractor ) - define_pass( StripNonDebugSymbols ) - define_pass( StructRetPromotion ) -Index: passes.py -=================================================================== ---- passes.py (revision 105) -+++ passes.py (working copy) -@@ -68,7 +68,7 @@ - PASS_EDGE_PROFILER = 25 - PASS_FUNCTION_ATTRS = 26 - PASS_FUNCTION_INLINING = 27 --PASS_GEP_SPLITTER = 28 -+#PASS_GEP_SPLITTER = 28 - PASS_GLOBAL_DCE = 29 - PASS_GLOBAL_OPTIMIZER = 30 - PASS_GLOBALS_MOD_REF = 31 -@@ -83,11 +83,11 @@ - PASS_LAZY_VALUE_INFO = 40 - PASS_LCSSA = 41 - PASS_LICM = 42 --PASS_LIVE_VALUES = 43 -+#PASS_LIVE_VALUES = 43 - PASS_LOOP_DELETION = 44 - PASS_LOOP_DEPENDENCE_ANALYSIS = 45 - PASS_LOOP_EXTRACTOR = 46 --PASS_LOOP_INDEX_SPLIT = 47 -+#PASS_LOOP_INDEX_SPLIT = 47 - PASS_LOOP_ROTATE = 48 - PASS_LOOP_SIMPLIFY = 49 - PASS_LOOP_STRENGTH_REDUCE = 50 -@@ -102,11 +102,11 @@ - PASS_NO_PROFILE_INFO = 59 - PASS_OPTIMAL_EDGE_PROFILER = 60 - PASS_PARTIAL_INLINING = 61 --PASS_PARTIAL_SPECIALIZATION = 62 --PASS_POST_DOM_ONLY_PRINTER = 63 --PASS_POST_DOM_ONLY_VIEWER = 64 --PASS_POST_DOM_PRINTER = 65 --PASS_POST_DOM_VIEWER = 66 -+#PASS_PARTIAL_SPECIALIZATION = 62 -+#PASS_POST_DOM_ONLY_PRINTER = 63 -+#PASS_POST_DOM_ONLY_VIEWER = 64 -+#PASS_POST_DOM_PRINTER = 65 -+#PASS_POST_DOM_VIEWER = 66 - PASS_PROFILE_ESTIMATOR = 67 - PASS_PROFILE_LOADER = 68 - PASS_PROFILE_VERIFIER = 69 -@@ -116,7 +116,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS = 73 - PASS_SCALAR_REPL_AGGREGATES = 74 - PASS_SCCP = 76 --PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 -+#PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 - PASS_SIMPLIFY_LIB_CALLS = 78 - PASS_SINGLE_LOOP_EXTRACTOR = 79 - PASS_STRIP_DEAD_PROTOTYPES = 82 -@@ -161,7 +161,7 @@ - PASS_EDGE_PROFILER : _core.LLVMAddEdgeProfilerPass, - PASS_FUNCTION_ATTRS : _core.LLVMAddFunctionAttrsPass, - PASS_FUNCTION_INLINING : _core.LLVMAddFunctionInliningPass, -- PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, -+ #PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, - PASS_GLOBAL_DCE : _core.LLVMAddGlobalDCEPass, - PASS_GLOBAL_OPTIMIZER : _core.LLVMAddGlobalOptimizerPass, - PASS_GLOBALS_MOD_REF : _core.LLVMAddGlobalsModRefPass, -@@ -176,11 +176,11 @@ - PASS_LAZY_VALUE_INFO : _core.LLVMAddLazyValueInfoPass, - PASS_LCSSA : _core.LLVMAddLCSSAPass, - PASS_LICM : _core.LLVMAddLICMPass, -- PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, -+ #PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, - PASS_LOOP_DELETION : _core.LLVMAddLoopDeletionPass, - PASS_LOOP_DEPENDENCE_ANALYSIS : _core.LLVMAddLoopDependenceAnalysisPass, - PASS_LOOP_EXTRACTOR : _core.LLVMAddLoopExtractorPass, -- PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, -+ #PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, - PASS_LOOP_ROTATE : _core.LLVMAddLoopRotatePass, - PASS_LOOP_SIMPLIFY : _core.LLVMAddLoopSimplifyPass, - PASS_LOOP_STRENGTH_REDUCE : _core.LLVMAddLoopStrengthReducePass, -@@ -195,11 +195,11 @@ - PASS_NO_PROFILE_INFO : _core.LLVMAddNoProfileInfoPass, - PASS_OPTIMAL_EDGE_PROFILER : _core.LLVMAddOptimalEdgeProfilerPass, - PASS_PARTIAL_INLINING : _core.LLVMAddPartialInliningPass, -- PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -- PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -- PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -- PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -- PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, -+ #PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -+ #PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -+ #PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -+ #PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -+ #PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, - PASS_PROFILE_ESTIMATOR : _core.LLVMAddProfileEstimatorPass, - PASS_PROFILE_LOADER : _core.LLVMAddProfileLoaderPass, - PASS_PROFILE_VERIFIER : _core.LLVMAddProfileVerifierPass, -@@ -209,7 +209,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS : _core.LLVMAddScalarEvolutionAliasAnalysisPass, - PASS_SCALAR_REPL_AGGREGATES : _core.LLVMAddScalarReplAggregatesPass, - PASS_SCCP : _core.LLVMAddSCCPPass, -- PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, -+ #PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, - PASS_SIMPLIFY_LIB_CALLS : _core.LLVMAddSimplifyLibCallsPass, - PASS_SINGLE_LOOP_EXTRACTOR : _core.LLVMAddSingleLoopExtractorPass, - PASS_STRIP_DEAD_PROTOTYPES : _core.LLVMAddStripDeadPrototypesPass, -Index: _intrinsic_ids.py -=================================================================== ---- _intrinsic_ids.py (revision 105) -+++ _intrinsic_ids.py (working copy) -@@ -49,854 +49,879 @@ - INTR_ARM_NEON_VCNT = 14 - INTR_ARM_NEON_VCVTFP2FXS = 15 - INTR_ARM_NEON_VCVTFP2FXU = 16 --INTR_ARM_NEON_VCVTFXS2FP = 17 --INTR_ARM_NEON_VCVTFXU2FP = 18 --INTR_ARM_NEON_VHADDS = 19 --INTR_ARM_NEON_VHADDU = 20 --INTR_ARM_NEON_VHSUBS = 21 --INTR_ARM_NEON_VHSUBU = 22 --INTR_ARM_NEON_VLD1 = 23 --INTR_ARM_NEON_VLD2 = 24 --INTR_ARM_NEON_VLD2LANE = 25 --INTR_ARM_NEON_VLD3 = 26 --INTR_ARM_NEON_VLD3LANE = 27 --INTR_ARM_NEON_VLD4 = 28 --INTR_ARM_NEON_VLD4LANE = 29 --INTR_ARM_NEON_VMAXS = 30 --INTR_ARM_NEON_VMAXU = 31 --INTR_ARM_NEON_VMINS = 32 --INTR_ARM_NEON_VMINU = 33 --INTR_ARM_NEON_VMULLP = 34 --INTR_ARM_NEON_VMULP = 35 --INTR_ARM_NEON_VPADALS = 36 --INTR_ARM_NEON_VPADALU = 37 --INTR_ARM_NEON_VPADD = 38 --INTR_ARM_NEON_VPADDLS = 39 --INTR_ARM_NEON_VPADDLU = 40 --INTR_ARM_NEON_VPMAXS = 41 --INTR_ARM_NEON_VPMAXU = 42 --INTR_ARM_NEON_VPMINS = 43 --INTR_ARM_NEON_VPMINU = 44 --INTR_ARM_NEON_VQABS = 45 --INTR_ARM_NEON_VQADDS = 46 --INTR_ARM_NEON_VQADDU = 47 --INTR_ARM_NEON_VQDMLAL = 48 --INTR_ARM_NEON_VQDMLSL = 49 --INTR_ARM_NEON_VQDMULH = 50 --INTR_ARM_NEON_VQDMULL = 51 --INTR_ARM_NEON_VQMOVNS = 52 --INTR_ARM_NEON_VQMOVNSU = 53 --INTR_ARM_NEON_VQMOVNU = 54 --INTR_ARM_NEON_VQNEG = 55 --INTR_ARM_NEON_VQRDMULH = 56 --INTR_ARM_NEON_VQRSHIFTNS = 57 --INTR_ARM_NEON_VQRSHIFTNSU = 58 --INTR_ARM_NEON_VQRSHIFTNU = 59 --INTR_ARM_NEON_VQRSHIFTS = 60 --INTR_ARM_NEON_VQRSHIFTU = 61 --INTR_ARM_NEON_VQSHIFTNS = 62 --INTR_ARM_NEON_VQSHIFTNSU = 63 --INTR_ARM_NEON_VQSHIFTNU = 64 --INTR_ARM_NEON_VQSHIFTS = 65 --INTR_ARM_NEON_VQSHIFTSU = 66 --INTR_ARM_NEON_VQSHIFTU = 67 --INTR_ARM_NEON_VQSUBS = 68 --INTR_ARM_NEON_VQSUBU = 69 --INTR_ARM_NEON_VRADDHN = 70 --INTR_ARM_NEON_VRECPE = 71 --INTR_ARM_NEON_VRECPS = 72 --INTR_ARM_NEON_VRHADDS = 73 --INTR_ARM_NEON_VRHADDU = 74 --INTR_ARM_NEON_VRSHIFTN = 75 --INTR_ARM_NEON_VRSHIFTS = 76 --INTR_ARM_NEON_VRSHIFTU = 77 --INTR_ARM_NEON_VRSQRTE = 78 --INTR_ARM_NEON_VRSQRTS = 79 --INTR_ARM_NEON_VRSUBHN = 80 --INTR_ARM_NEON_VSHIFTINS = 81 --INTR_ARM_NEON_VSHIFTLS = 82 --INTR_ARM_NEON_VSHIFTLU = 83 --INTR_ARM_NEON_VSHIFTN = 84 --INTR_ARM_NEON_VSHIFTS = 85 --INTR_ARM_NEON_VSHIFTU = 86 --INTR_ARM_NEON_VST1 = 87 --INTR_ARM_NEON_VST2 = 88 --INTR_ARM_NEON_VST2LANE = 89 --INTR_ARM_NEON_VST3 = 90 --INTR_ARM_NEON_VST3LANE = 91 --INTR_ARM_NEON_VST4 = 92 --INTR_ARM_NEON_VST4LANE = 93 --INTR_ARM_NEON_VSUBHN = 94 --INTR_ARM_NEON_VTBL1 = 95 --INTR_ARM_NEON_VTBL2 = 96 --INTR_ARM_NEON_VTBL3 = 97 --INTR_ARM_NEON_VTBL4 = 98 --INTR_ARM_NEON_VTBX1 = 99 --INTR_ARM_NEON_VTBX2 = 100 --INTR_ARM_NEON_VTBX3 = 101 --INTR_ARM_NEON_VTBX4 = 102 --INTR_ARM_QADD = 103 --INTR_ARM_QSUB = 104 --INTR_ARM_SET_FPSCR = 105 --INTR_ARM_SSAT = 106 --INTR_ARM_THREAD_POINTER = 107 --INTR_ARM_USAT = 108 --INTR_ARM_VCVTR = 109 --INTR_ARM_VCVTRU = 110 --INTR_ATOMIC_CMP_SWAP = 111 --INTR_ATOMIC_LOAD_ADD = 112 --INTR_ATOMIC_LOAD_AND = 113 --INTR_ATOMIC_LOAD_MAX = 114 --INTR_ATOMIC_LOAD_MIN = 115 --INTR_ATOMIC_LOAD_NAND = 116 --INTR_ATOMIC_LOAD_OR = 117 --INTR_ATOMIC_LOAD_SUB = 118 --INTR_ATOMIC_LOAD_UMAX = 119 --INTR_ATOMIC_LOAD_UMIN = 120 --INTR_ATOMIC_LOAD_XOR = 121 --INTR_ATOMIC_SWAP = 122 --INTR_BSWAP = 123 --INTR_CONVERT_FROM_FP16 = 124 --INTR_CONVERT_TO_FP16 = 125 --INTR_CONVERTFF = 126 --INTR_CONVERTFSI = 127 --INTR_CONVERTFUI = 128 --INTR_CONVERTSIF = 129 --INTR_CONVERTSS = 130 --INTR_CONVERTSU = 131 --INTR_CONVERTUIF = 132 --INTR_CONVERTUS = 133 --INTR_CONVERTUU = 134 --INTR_COS = 135 --INTR_CTLZ = 136 --INTR_CTPOP = 137 --INTR_CTTZ = 138 --INTR_DBG_DECLARE = 139 --INTR_DBG_VALUE = 140 --INTR_EH_DWARF_CFA = 141 --INTR_EH_EXCEPTION = 142 --INTR_EH_RETURN_I32 = 143 --INTR_EH_RETURN_I64 = 144 --INTR_EH_SELECTOR = 145 --INTR_EH_SJLJ_CALLSITE = 146 --INTR_EH_SJLJ_LONGJMP = 147 --INTR_EH_SJLJ_LSDA = 148 --INTR_EH_SJLJ_SETJMP = 149 --INTR_EH_TYPEID_FOR = 150 --INTR_EH_UNWIND_INIT = 151 --INTR_EXP = 152 --INTR_EXP2 = 153 --INTR_FLT_ROUNDS = 154 --INTR_FRAMEADDRESS = 155 --INTR_GCREAD = 156 --INTR_GCROOT = 157 --INTR_GCWRITE = 158 --INTR_INIT_TRAMPOLINE = 159 --INTR_INVARIANT_END = 160 --INTR_INVARIANT_START = 161 --INTR_LIFETIME_END = 162 --INTR_LIFETIME_START = 163 --INTR_LOG = 164 --INTR_LOG10 = 165 --INTR_LOG2 = 166 --INTR_LONGJMP = 167 --INTR_MEMCPY = 168 --INTR_MEMMOVE = 169 --INTR_MEMORY_BARRIER = 170 --INTR_MEMSET = 171 --INTR_OBJECTSIZE = 172 --INTR_PCMARKER = 173 --INTR_POW = 174 --INTR_POWI = 175 --INTR_PPC_ALTIVEC_DSS = 176 --INTR_PPC_ALTIVEC_DSSALL = 177 --INTR_PPC_ALTIVEC_DST = 178 --INTR_PPC_ALTIVEC_DSTST = 179 --INTR_PPC_ALTIVEC_DSTSTT = 180 --INTR_PPC_ALTIVEC_DSTT = 181 --INTR_PPC_ALTIVEC_LVEBX = 182 --INTR_PPC_ALTIVEC_LVEHX = 183 --INTR_PPC_ALTIVEC_LVEWX = 184 --INTR_PPC_ALTIVEC_LVSL = 185 --INTR_PPC_ALTIVEC_LVSR = 186 --INTR_PPC_ALTIVEC_LVX = 187 --INTR_PPC_ALTIVEC_LVXL = 188 --INTR_PPC_ALTIVEC_MFVSCR = 189 --INTR_PPC_ALTIVEC_MTVSCR = 190 --INTR_PPC_ALTIVEC_STVEBX = 191 --INTR_PPC_ALTIVEC_STVEHX = 192 --INTR_PPC_ALTIVEC_STVEWX = 193 --INTR_PPC_ALTIVEC_STVX = 194 --INTR_PPC_ALTIVEC_STVXL = 195 --INTR_PPC_ALTIVEC_VADDCUW = 196 --INTR_PPC_ALTIVEC_VADDSBS = 197 --INTR_PPC_ALTIVEC_VADDSHS = 198 --INTR_PPC_ALTIVEC_VADDSWS = 199 --INTR_PPC_ALTIVEC_VADDUBS = 200 --INTR_PPC_ALTIVEC_VADDUHS = 201 --INTR_PPC_ALTIVEC_VADDUWS = 202 --INTR_PPC_ALTIVEC_VAVGSB = 203 --INTR_PPC_ALTIVEC_VAVGSH = 204 --INTR_PPC_ALTIVEC_VAVGSW = 205 --INTR_PPC_ALTIVEC_VAVGUB = 206 --INTR_PPC_ALTIVEC_VAVGUH = 207 --INTR_PPC_ALTIVEC_VAVGUW = 208 --INTR_PPC_ALTIVEC_VCFSX = 209 --INTR_PPC_ALTIVEC_VCFUX = 210 --INTR_PPC_ALTIVEC_VCMPBFP = 211 --INTR_PPC_ALTIVEC_VCMPBFP_P = 212 --INTR_PPC_ALTIVEC_VCMPEQFP = 213 --INTR_PPC_ALTIVEC_VCMPEQFP_P = 214 --INTR_PPC_ALTIVEC_VCMPEQUB = 215 --INTR_PPC_ALTIVEC_VCMPEQUB_P = 216 --INTR_PPC_ALTIVEC_VCMPEQUH = 217 --INTR_PPC_ALTIVEC_VCMPEQUH_P = 218 --INTR_PPC_ALTIVEC_VCMPEQUW = 219 --INTR_PPC_ALTIVEC_VCMPEQUW_P = 220 --INTR_PPC_ALTIVEC_VCMPGEFP = 221 --INTR_PPC_ALTIVEC_VCMPGEFP_P = 222 --INTR_PPC_ALTIVEC_VCMPGTFP = 223 --INTR_PPC_ALTIVEC_VCMPGTFP_P = 224 --INTR_PPC_ALTIVEC_VCMPGTSB = 225 --INTR_PPC_ALTIVEC_VCMPGTSB_P = 226 --INTR_PPC_ALTIVEC_VCMPGTSH = 227 --INTR_PPC_ALTIVEC_VCMPGTSH_P = 228 --INTR_PPC_ALTIVEC_VCMPGTSW = 229 --INTR_PPC_ALTIVEC_VCMPGTSW_P = 230 --INTR_PPC_ALTIVEC_VCMPGTUB = 231 --INTR_PPC_ALTIVEC_VCMPGTUB_P = 232 --INTR_PPC_ALTIVEC_VCMPGTUH = 233 --INTR_PPC_ALTIVEC_VCMPGTUH_P = 234 --INTR_PPC_ALTIVEC_VCMPGTUW = 235 --INTR_PPC_ALTIVEC_VCMPGTUW_P = 236 --INTR_PPC_ALTIVEC_VCTSXS = 237 --INTR_PPC_ALTIVEC_VCTUXS = 238 --INTR_PPC_ALTIVEC_VEXPTEFP = 239 --INTR_PPC_ALTIVEC_VLOGEFP = 240 --INTR_PPC_ALTIVEC_VMADDFP = 241 --INTR_PPC_ALTIVEC_VMAXFP = 242 --INTR_PPC_ALTIVEC_VMAXSB = 243 --INTR_PPC_ALTIVEC_VMAXSH = 244 --INTR_PPC_ALTIVEC_VMAXSW = 245 --INTR_PPC_ALTIVEC_VMAXUB = 246 --INTR_PPC_ALTIVEC_VMAXUH = 247 --INTR_PPC_ALTIVEC_VMAXUW = 248 --INTR_PPC_ALTIVEC_VMHADDSHS = 249 --INTR_PPC_ALTIVEC_VMHRADDSHS = 250 --INTR_PPC_ALTIVEC_VMINFP = 251 --INTR_PPC_ALTIVEC_VMINSB = 252 --INTR_PPC_ALTIVEC_VMINSH = 253 --INTR_PPC_ALTIVEC_VMINSW = 254 --INTR_PPC_ALTIVEC_VMINUB = 255 --INTR_PPC_ALTIVEC_VMINUH = 256 --INTR_PPC_ALTIVEC_VMINUW = 257 --INTR_PPC_ALTIVEC_VMLADDUHM = 258 --INTR_PPC_ALTIVEC_VMSUMMBM = 259 --INTR_PPC_ALTIVEC_VMSUMSHM = 260 --INTR_PPC_ALTIVEC_VMSUMSHS = 261 --INTR_PPC_ALTIVEC_VMSUMUBM = 262 --INTR_PPC_ALTIVEC_VMSUMUHM = 263 --INTR_PPC_ALTIVEC_VMSUMUHS = 264 --INTR_PPC_ALTIVEC_VMULESB = 265 --INTR_PPC_ALTIVEC_VMULESH = 266 --INTR_PPC_ALTIVEC_VMULEUB = 267 --INTR_PPC_ALTIVEC_VMULEUH = 268 --INTR_PPC_ALTIVEC_VMULOSB = 269 --INTR_PPC_ALTIVEC_VMULOSH = 270 --INTR_PPC_ALTIVEC_VMULOUB = 271 --INTR_PPC_ALTIVEC_VMULOUH = 272 --INTR_PPC_ALTIVEC_VNMSUBFP = 273 --INTR_PPC_ALTIVEC_VPERM = 274 --INTR_PPC_ALTIVEC_VPKPX = 275 --INTR_PPC_ALTIVEC_VPKSHSS = 276 --INTR_PPC_ALTIVEC_VPKSHUS = 277 --INTR_PPC_ALTIVEC_VPKSWSS = 278 --INTR_PPC_ALTIVEC_VPKSWUS = 279 --INTR_PPC_ALTIVEC_VPKUHUS = 280 --INTR_PPC_ALTIVEC_VPKUWUS = 281 --INTR_PPC_ALTIVEC_VREFP = 282 --INTR_PPC_ALTIVEC_VRFIM = 283 --INTR_PPC_ALTIVEC_VRFIN = 284 --INTR_PPC_ALTIVEC_VRFIP = 285 --INTR_PPC_ALTIVEC_VRFIZ = 286 --INTR_PPC_ALTIVEC_VRLB = 287 --INTR_PPC_ALTIVEC_VRLH = 288 --INTR_PPC_ALTIVEC_VRLW = 289 --INTR_PPC_ALTIVEC_VRSQRTEFP = 290 --INTR_PPC_ALTIVEC_VSEL = 291 --INTR_PPC_ALTIVEC_VSL = 292 --INTR_PPC_ALTIVEC_VSLB = 293 --INTR_PPC_ALTIVEC_VSLH = 294 --INTR_PPC_ALTIVEC_VSLO = 295 --INTR_PPC_ALTIVEC_VSLW = 296 --INTR_PPC_ALTIVEC_VSR = 297 --INTR_PPC_ALTIVEC_VSRAB = 298 --INTR_PPC_ALTIVEC_VSRAH = 299 --INTR_PPC_ALTIVEC_VSRAW = 300 --INTR_PPC_ALTIVEC_VSRB = 301 --INTR_PPC_ALTIVEC_VSRH = 302 --INTR_PPC_ALTIVEC_VSRO = 303 --INTR_PPC_ALTIVEC_VSRW = 304 --INTR_PPC_ALTIVEC_VSUBCUW = 305 --INTR_PPC_ALTIVEC_VSUBSBS = 306 --INTR_PPC_ALTIVEC_VSUBSHS = 307 --INTR_PPC_ALTIVEC_VSUBSWS = 308 --INTR_PPC_ALTIVEC_VSUBUBS = 309 --INTR_PPC_ALTIVEC_VSUBUHS = 310 --INTR_PPC_ALTIVEC_VSUBUWS = 311 --INTR_PPC_ALTIVEC_VSUM2SWS = 312 --INTR_PPC_ALTIVEC_VSUM4SBS = 313 --INTR_PPC_ALTIVEC_VSUM4SHS = 314 --INTR_PPC_ALTIVEC_VSUM4UBS = 315 --INTR_PPC_ALTIVEC_VSUMSWS = 316 --INTR_PPC_ALTIVEC_VUPKHPX = 317 --INTR_PPC_ALTIVEC_VUPKHSB = 318 --INTR_PPC_ALTIVEC_VUPKHSH = 319 --INTR_PPC_ALTIVEC_VUPKLPX = 320 --INTR_PPC_ALTIVEC_VUPKLSB = 321 --INTR_PPC_ALTIVEC_VUPKLSH = 322 --INTR_PPC_DCBA = 323 --INTR_PPC_DCBF = 324 --INTR_PPC_DCBI = 325 --INTR_PPC_DCBST = 326 --INTR_PPC_DCBT = 327 --INTR_PPC_DCBTST = 328 --INTR_PPC_DCBZ = 329 --INTR_PPC_DCBZL = 330 --INTR_PPC_SYNC = 331 --INTR_PREFETCH = 332 --INTR_PTR_ANNOTATION = 333 --INTR_READCYCLECOUNTER = 334 --INTR_RETURNADDRESS = 335 --INTR_SADD_WITH_OVERFLOW = 336 --INTR_SETJMP = 337 --INTR_SIGLONGJMP = 338 --INTR_SIGSETJMP = 339 --INTR_SIN = 340 --INTR_SMUL_WITH_OVERFLOW = 341 --INTR_SPU_SI_A = 342 --INTR_SPU_SI_ADDX = 343 --INTR_SPU_SI_AH = 344 --INTR_SPU_SI_AHI = 345 --INTR_SPU_SI_AI = 346 --INTR_SPU_SI_AND = 347 --INTR_SPU_SI_ANDBI = 348 --INTR_SPU_SI_ANDC = 349 --INTR_SPU_SI_ANDHI = 350 --INTR_SPU_SI_ANDI = 351 --INTR_SPU_SI_BG = 352 --INTR_SPU_SI_BGX = 353 --INTR_SPU_SI_CEQ = 354 --INTR_SPU_SI_CEQB = 355 --INTR_SPU_SI_CEQBI = 356 --INTR_SPU_SI_CEQH = 357 --INTR_SPU_SI_CEQHI = 358 --INTR_SPU_SI_CEQI = 359 --INTR_SPU_SI_CG = 360 --INTR_SPU_SI_CGT = 361 --INTR_SPU_SI_CGTB = 362 --INTR_SPU_SI_CGTBI = 363 --INTR_SPU_SI_CGTH = 364 --INTR_SPU_SI_CGTHI = 365 --INTR_SPU_SI_CGTI = 366 --INTR_SPU_SI_CGX = 367 --INTR_SPU_SI_CLGT = 368 --INTR_SPU_SI_CLGTB = 369 --INTR_SPU_SI_CLGTBI = 370 --INTR_SPU_SI_CLGTH = 371 --INTR_SPU_SI_CLGTHI = 372 --INTR_SPU_SI_CLGTI = 373 --INTR_SPU_SI_DFA = 374 --INTR_SPU_SI_DFM = 375 --INTR_SPU_SI_DFMA = 376 --INTR_SPU_SI_DFMS = 377 --INTR_SPU_SI_DFNMA = 378 --INTR_SPU_SI_DFNMS = 379 --INTR_SPU_SI_DFS = 380 --INTR_SPU_SI_FA = 381 --INTR_SPU_SI_FCEQ = 382 --INTR_SPU_SI_FCGT = 383 --INTR_SPU_SI_FCMEQ = 384 --INTR_SPU_SI_FCMGT = 385 --INTR_SPU_SI_FM = 386 --INTR_SPU_SI_FMA = 387 --INTR_SPU_SI_FMS = 388 --INTR_SPU_SI_FNMS = 389 --INTR_SPU_SI_FS = 390 --INTR_SPU_SI_FSMBI = 391 --INTR_SPU_SI_MPY = 392 --INTR_SPU_SI_MPYA = 393 --INTR_SPU_SI_MPYH = 394 --INTR_SPU_SI_MPYHH = 395 --INTR_SPU_SI_MPYHHA = 396 --INTR_SPU_SI_MPYHHAU = 397 --INTR_SPU_SI_MPYHHU = 398 --INTR_SPU_SI_MPYI = 399 --INTR_SPU_SI_MPYS = 400 --INTR_SPU_SI_MPYU = 401 --INTR_SPU_SI_MPYUI = 402 --INTR_SPU_SI_NAND = 403 --INTR_SPU_SI_NOR = 404 --INTR_SPU_SI_OR = 405 --INTR_SPU_SI_ORBI = 406 --INTR_SPU_SI_ORC = 407 --INTR_SPU_SI_ORHI = 408 --INTR_SPU_SI_ORI = 409 --INTR_SPU_SI_SF = 410 --INTR_SPU_SI_SFH = 411 --INTR_SPU_SI_SFHI = 412 --INTR_SPU_SI_SFI = 413 --INTR_SPU_SI_SFX = 414 --INTR_SPU_SI_SHLI = 415 --INTR_SPU_SI_SHLQBI = 416 --INTR_SPU_SI_SHLQBII = 417 --INTR_SPU_SI_SHLQBY = 418 --INTR_SPU_SI_SHLQBYI = 419 --INTR_SPU_SI_XOR = 420 --INTR_SPU_SI_XORBI = 421 --INTR_SPU_SI_XORHI = 422 --INTR_SPU_SI_XORI = 423 --INTR_SQRT = 424 --INTR_SSUB_WITH_OVERFLOW = 425 --INTR_STACKPROTECTOR = 426 --INTR_STACKRESTORE = 427 --INTR_STACKSAVE = 428 --INTR_TRAP = 429 --INTR_UADD_WITH_OVERFLOW = 430 --INTR_UMUL_WITH_OVERFLOW = 431 --INTR_USUB_WITH_OVERFLOW = 432 --INTR_VACOPY = 433 --INTR_VAEND = 434 --INTR_VAR_ANNOTATION = 435 --INTR_VASTART = 436 --INTR_X86_AESNI_AESDEC = 437 --INTR_X86_AESNI_AESDECLAST = 438 --INTR_X86_AESNI_AESENC = 439 --INTR_X86_AESNI_AESENCLAST = 440 --INTR_X86_AESNI_AESIMC = 441 --INTR_X86_AESNI_AESKEYGENASSIST = 442 --INTR_X86_AVX_ADDSUB_PD_256 = 443 --INTR_X86_AVX_ADDSUB_PS_256 = 444 --INTR_X86_AVX_BLEND_PD_256 = 445 --INTR_X86_AVX_BLEND_PS_256 = 446 --INTR_X86_AVX_BLENDV_PD_256 = 447 --INTR_X86_AVX_BLENDV_PS_256 = 448 --INTR_X86_AVX_CMP_PD_256 = 449 --INTR_X86_AVX_CMP_PS_256 = 450 --INTR_X86_AVX_CVT_PD2_PS_256 = 451 --INTR_X86_AVX_CVT_PD2DQ_256 = 452 --INTR_X86_AVX_CVT_PS2_PD_256 = 453 --INTR_X86_AVX_CVT_PS2DQ_256 = 454 --INTR_X86_AVX_CVTDQ2_PD_256 = 455 --INTR_X86_AVX_CVTDQ2_PS_256 = 456 --INTR_X86_AVX_CVTT_PD2DQ_256 = 457 --INTR_X86_AVX_CVTT_PS2DQ_256 = 458 --INTR_X86_AVX_DP_PS_256 = 459 --INTR_X86_AVX_HADD_PD_256 = 460 --INTR_X86_AVX_HADD_PS_256 = 461 --INTR_X86_AVX_HSUB_PD_256 = 462 --INTR_X86_AVX_HSUB_PS_256 = 463 --INTR_X86_AVX_LDU_DQ_256 = 464 --INTR_X86_AVX_LOADU_DQ_256 = 465 --INTR_X86_AVX_LOADU_PD_256 = 466 --INTR_X86_AVX_LOADU_PS_256 = 467 --INTR_X86_AVX_MASKLOAD_PD = 468 --INTR_X86_AVX_MASKLOAD_PD_256 = 469 --INTR_X86_AVX_MASKLOAD_PS = 470 --INTR_X86_AVX_MASKLOAD_PS_256 = 471 --INTR_X86_AVX_MASKSTORE_PD = 472 --INTR_X86_AVX_MASKSTORE_PD_256 = 473 --INTR_X86_AVX_MASKSTORE_PS = 474 --INTR_X86_AVX_MASKSTORE_PS_256 = 475 --INTR_X86_AVX_MAX_PD_256 = 476 --INTR_X86_AVX_MAX_PS_256 = 477 --INTR_X86_AVX_MIN_PD_256 = 478 --INTR_X86_AVX_MIN_PS_256 = 479 --INTR_X86_AVX_MOVMSK_PD_256 = 480 --INTR_X86_AVX_MOVMSK_PS_256 = 481 --INTR_X86_AVX_MOVNT_DQ_256 = 482 --INTR_X86_AVX_MOVNT_PD_256 = 483 --INTR_X86_AVX_MOVNT_PS_256 = 484 --INTR_X86_AVX_PTESTC_256 = 485 --INTR_X86_AVX_PTESTNZC_256 = 486 --INTR_X86_AVX_PTESTZ_256 = 487 --INTR_X86_AVX_RCP_PS_256 = 488 --INTR_X86_AVX_ROUND_PD_256 = 489 --INTR_X86_AVX_ROUND_PS_256 = 490 --INTR_X86_AVX_RSQRT_PS_256 = 491 --INTR_X86_AVX_SQRT_PD_256 = 492 --INTR_X86_AVX_SQRT_PS_256 = 493 --INTR_X86_AVX_STOREU_DQ_256 = 494 --INTR_X86_AVX_STOREU_PD_256 = 495 --INTR_X86_AVX_STOREU_PS_256 = 496 --INTR_X86_AVX_VBROADCAST_SD_256 = 497 --INTR_X86_AVX_VBROADCASTF128_PD_256 = 498 --INTR_X86_AVX_VBROADCASTF128_PS_256 = 499 --INTR_X86_AVX_VBROADCASTSS = 500 --INTR_X86_AVX_VBROADCASTSS_256 = 501 --INTR_X86_AVX_VEXTRACTF128_PD_256 = 502 --INTR_X86_AVX_VEXTRACTF128_PS_256 = 503 --INTR_X86_AVX_VEXTRACTF128_SI_256 = 504 --INTR_X86_AVX_VINSERTF128_PD_256 = 505 --INTR_X86_AVX_VINSERTF128_PS_256 = 506 --INTR_X86_AVX_VINSERTF128_SI_256 = 507 --INTR_X86_AVX_VPERM2F128_PD_256 = 508 --INTR_X86_AVX_VPERM2F128_PS_256 = 509 --INTR_X86_AVX_VPERM2F128_SI_256 = 510 --INTR_X86_AVX_VPERMIL_PD = 511 --INTR_X86_AVX_VPERMIL_PD_256 = 512 --INTR_X86_AVX_VPERMIL_PS = 513 --INTR_X86_AVX_VPERMIL_PS_256 = 514 --INTR_X86_AVX_VPERMILVAR_PD = 515 --INTR_X86_AVX_VPERMILVAR_PD_256 = 516 --INTR_X86_AVX_VPERMILVAR_PS = 517 --INTR_X86_AVX_VPERMILVAR_PS_256 = 518 --INTR_X86_AVX_VTESTC_PD = 519 --INTR_X86_AVX_VTESTC_PD_256 = 520 --INTR_X86_AVX_VTESTC_PS = 521 --INTR_X86_AVX_VTESTC_PS_256 = 522 --INTR_X86_AVX_VTESTNZC_PD = 523 --INTR_X86_AVX_VTESTNZC_PD_256 = 524 --INTR_X86_AVX_VTESTNZC_PS = 525 --INTR_X86_AVX_VTESTNZC_PS_256 = 526 --INTR_X86_AVX_VTESTZ_PD = 527 --INTR_X86_AVX_VTESTZ_PD_256 = 528 --INTR_X86_AVX_VTESTZ_PS = 529 --INTR_X86_AVX_VTESTZ_PS_256 = 530 --INTR_X86_AVX_VZEROALL = 531 --INTR_X86_AVX_VZEROUPPER = 532 --INTR_X86_INT = 533 --INTR_X86_MMX_CVTSI32_SI64 = 534 --INTR_X86_MMX_CVTSI64_SI32 = 535 --INTR_X86_MMX_EMMS = 536 --INTR_X86_MMX_FEMMS = 537 --INTR_X86_MMX_MASKMOVQ = 538 --INTR_X86_MMX_MOVNT_DQ = 539 --INTR_X86_MMX_PACKSSDW = 540 --INTR_X86_MMX_PACKSSWB = 541 --INTR_X86_MMX_PACKUSWB = 542 --INTR_X86_MMX_PADD_B = 543 --INTR_X86_MMX_PADD_D = 544 --INTR_X86_MMX_PADD_Q = 545 --INTR_X86_MMX_PADD_W = 546 --INTR_X86_MMX_PADDS_B = 547 --INTR_X86_MMX_PADDS_W = 548 --INTR_X86_MMX_PADDUS_B = 549 --INTR_X86_MMX_PADDUS_W = 550 --INTR_X86_MMX_PAND = 551 --INTR_X86_MMX_PANDN = 552 --INTR_X86_MMX_PAVG_B = 553 --INTR_X86_MMX_PAVG_W = 554 --INTR_X86_MMX_PCMPEQ_B = 555 --INTR_X86_MMX_PCMPEQ_D = 556 --INTR_X86_MMX_PCMPEQ_W = 557 --INTR_X86_MMX_PCMPGT_B = 558 --INTR_X86_MMX_PCMPGT_D = 559 --INTR_X86_MMX_PCMPGT_W = 560 --INTR_X86_MMX_PEXTR_W = 561 --INTR_X86_MMX_PINSR_W = 562 --INTR_X86_MMX_PMADD_WD = 563 --INTR_X86_MMX_PMAXS_W = 564 --INTR_X86_MMX_PMAXU_B = 565 --INTR_X86_MMX_PMINS_W = 566 --INTR_X86_MMX_PMINU_B = 567 --INTR_X86_MMX_PMOVMSKB = 568 --INTR_X86_MMX_PMULH_W = 569 --INTR_X86_MMX_PMULHU_W = 570 --INTR_X86_MMX_PMULL_W = 571 --INTR_X86_MMX_PMULU_DQ = 572 --INTR_X86_MMX_POR = 573 --INTR_X86_MMX_PSAD_BW = 574 --INTR_X86_MMX_PSLL_D = 575 --INTR_X86_MMX_PSLL_Q = 576 --INTR_X86_MMX_PSLL_W = 577 --INTR_X86_MMX_PSLLI_D = 578 --INTR_X86_MMX_PSLLI_Q = 579 --INTR_X86_MMX_PSLLI_W = 580 --INTR_X86_MMX_PSRA_D = 581 --INTR_X86_MMX_PSRA_W = 582 --INTR_X86_MMX_PSRAI_D = 583 --INTR_X86_MMX_PSRAI_W = 584 --INTR_X86_MMX_PSRL_D = 585 --INTR_X86_MMX_PSRL_Q = 586 --INTR_X86_MMX_PSRL_W = 587 --INTR_X86_MMX_PSRLI_D = 588 --INTR_X86_MMX_PSRLI_Q = 589 --INTR_X86_MMX_PSRLI_W = 590 --INTR_X86_MMX_PSUB_B = 591 --INTR_X86_MMX_PSUB_D = 592 --INTR_X86_MMX_PSUB_Q = 593 --INTR_X86_MMX_PSUB_W = 594 --INTR_X86_MMX_PSUBS_B = 595 --INTR_X86_MMX_PSUBS_W = 596 --INTR_X86_MMX_PSUBUS_B = 597 --INTR_X86_MMX_PSUBUS_W = 598 --INTR_X86_MMX_PUNPCKHBW = 599 --INTR_X86_MMX_PUNPCKHDQ = 600 --INTR_X86_MMX_PUNPCKHWD = 601 --INTR_X86_MMX_PUNPCKLBW = 602 --INTR_X86_MMX_PUNPCKLDQ = 603 --INTR_X86_MMX_PUNPCKLWD = 604 --INTR_X86_MMX_PXOR = 605 --INTR_X86_MMX_VEC_EXT_D = 606 --INTR_X86_MMX_VEC_INIT_B = 607 --INTR_X86_MMX_VEC_INIT_D = 608 --INTR_X86_MMX_VEC_INIT_W = 609 --INTR_X86_SSE2_ADD_SD = 610 --INTR_X86_SSE2_CLFLUSH = 611 --INTR_X86_SSE2_CMP_PD = 612 --INTR_X86_SSE2_CMP_SD = 613 --INTR_X86_SSE2_COMIEQ_SD = 614 --INTR_X86_SSE2_COMIGE_SD = 615 --INTR_X86_SSE2_COMIGT_SD = 616 --INTR_X86_SSE2_COMILE_SD = 617 --INTR_X86_SSE2_COMILT_SD = 618 --INTR_X86_SSE2_COMINEQ_SD = 619 --INTR_X86_SSE2_CVTDQ2PD = 620 --INTR_X86_SSE2_CVTDQ2PS = 621 --INTR_X86_SSE2_CVTPD2DQ = 622 --INTR_X86_SSE2_CVTPD2PS = 623 --INTR_X86_SSE2_CVTPS2DQ = 624 --INTR_X86_SSE2_CVTPS2PD = 625 --INTR_X86_SSE2_CVTSD2SI = 626 --INTR_X86_SSE2_CVTSD2SI64 = 627 --INTR_X86_SSE2_CVTSD2SS = 628 --INTR_X86_SSE2_CVTSI2SD = 629 --INTR_X86_SSE2_CVTSI642SD = 630 --INTR_X86_SSE2_CVTSS2SD = 631 --INTR_X86_SSE2_CVTTPD2DQ = 632 --INTR_X86_SSE2_CVTTPS2DQ = 633 --INTR_X86_SSE2_CVTTSD2SI = 634 --INTR_X86_SSE2_CVTTSD2SI64 = 635 --INTR_X86_SSE2_DIV_SD = 636 --INTR_X86_SSE2_LFENCE = 637 --INTR_X86_SSE2_LOADU_DQ = 638 --INTR_X86_SSE2_LOADU_PD = 639 --INTR_X86_SSE2_MASKMOV_DQU = 640 --INTR_X86_SSE2_MAX_PD = 641 --INTR_X86_SSE2_MAX_SD = 642 --INTR_X86_SSE2_MFENCE = 643 --INTR_X86_SSE2_MIN_PD = 644 --INTR_X86_SSE2_MIN_SD = 645 --INTR_X86_SSE2_MOVMSK_PD = 646 --INTR_X86_SSE2_MOVNT_DQ = 647 --INTR_X86_SSE2_MOVNT_I = 648 --INTR_X86_SSE2_MOVNT_PD = 649 --INTR_X86_SSE2_MUL_SD = 650 --INTR_X86_SSE2_PACKSSDW_128 = 651 --INTR_X86_SSE2_PACKSSWB_128 = 652 --INTR_X86_SSE2_PACKUSWB_128 = 653 --INTR_X86_SSE2_PADDS_B = 654 --INTR_X86_SSE2_PADDS_W = 655 --INTR_X86_SSE2_PADDUS_B = 656 --INTR_X86_SSE2_PADDUS_W = 657 --INTR_X86_SSE2_PAVG_B = 658 --INTR_X86_SSE2_PAVG_W = 659 --INTR_X86_SSE2_PCMPEQ_B = 660 --INTR_X86_SSE2_PCMPEQ_D = 661 --INTR_X86_SSE2_PCMPEQ_W = 662 --INTR_X86_SSE2_PCMPGT_B = 663 --INTR_X86_SSE2_PCMPGT_D = 664 --INTR_X86_SSE2_PCMPGT_W = 665 --INTR_X86_SSE2_PMADD_WD = 666 --INTR_X86_SSE2_PMAXS_W = 667 --INTR_X86_SSE2_PMAXU_B = 668 --INTR_X86_SSE2_PMINS_W = 669 --INTR_X86_SSE2_PMINU_B = 670 --INTR_X86_SSE2_PMOVMSKB_128 = 671 --INTR_X86_SSE2_PMULH_W = 672 --INTR_X86_SSE2_PMULHU_W = 673 --INTR_X86_SSE2_PMULU_DQ = 674 --INTR_X86_SSE2_PSAD_BW = 675 --INTR_X86_SSE2_PSLL_D = 676 --INTR_X86_SSE2_PSLL_DQ = 677 --INTR_X86_SSE2_PSLL_DQ_BS = 678 --INTR_X86_SSE2_PSLL_Q = 679 --INTR_X86_SSE2_PSLL_W = 680 --INTR_X86_SSE2_PSLLI_D = 681 --INTR_X86_SSE2_PSLLI_Q = 682 --INTR_X86_SSE2_PSLLI_W = 683 --INTR_X86_SSE2_PSRA_D = 684 --INTR_X86_SSE2_PSRA_W = 685 --INTR_X86_SSE2_PSRAI_D = 686 --INTR_X86_SSE2_PSRAI_W = 687 --INTR_X86_SSE2_PSRL_D = 688 --INTR_X86_SSE2_PSRL_DQ = 689 --INTR_X86_SSE2_PSRL_DQ_BS = 690 --INTR_X86_SSE2_PSRL_Q = 691 --INTR_X86_SSE2_PSRL_W = 692 --INTR_X86_SSE2_PSRLI_D = 693 --INTR_X86_SSE2_PSRLI_Q = 694 --INTR_X86_SSE2_PSRLI_W = 695 --INTR_X86_SSE2_PSUBS_B = 696 --INTR_X86_SSE2_PSUBS_W = 697 --INTR_X86_SSE2_PSUBUS_B = 698 --INTR_X86_SSE2_PSUBUS_W = 699 --INTR_X86_SSE2_SQRT_PD = 700 --INTR_X86_SSE2_SQRT_SD = 701 --INTR_X86_SSE2_STOREL_DQ = 702 --INTR_X86_SSE2_STOREU_DQ = 703 --INTR_X86_SSE2_STOREU_PD = 704 --INTR_X86_SSE2_SUB_SD = 705 --INTR_X86_SSE2_UCOMIEQ_SD = 706 --INTR_X86_SSE2_UCOMIGE_SD = 707 --INTR_X86_SSE2_UCOMIGT_SD = 708 --INTR_X86_SSE2_UCOMILE_SD = 709 --INTR_X86_SSE2_UCOMILT_SD = 710 --INTR_X86_SSE2_UCOMINEQ_SD = 711 --INTR_X86_SSE3_ADDSUB_PD = 712 --INTR_X86_SSE3_ADDSUB_PS = 713 --INTR_X86_SSE3_HADD_PD = 714 --INTR_X86_SSE3_HADD_PS = 715 --INTR_X86_SSE3_HSUB_PD = 716 --INTR_X86_SSE3_HSUB_PS = 717 --INTR_X86_SSE3_LDU_DQ = 718 --INTR_X86_SSE3_MONITOR = 719 --INTR_X86_SSE3_MWAIT = 720 --INTR_X86_SSE41_BLENDPD = 721 --INTR_X86_SSE41_BLENDPS = 722 --INTR_X86_SSE41_BLENDVPD = 723 --INTR_X86_SSE41_BLENDVPS = 724 --INTR_X86_SSE41_DPPD = 725 --INTR_X86_SSE41_DPPS = 726 --INTR_X86_SSE41_EXTRACTPS = 727 --INTR_X86_SSE41_INSERTPS = 728 --INTR_X86_SSE41_MOVNTDQA = 729 --INTR_X86_SSE41_MPSADBW = 730 --INTR_X86_SSE41_PACKUSDW = 731 --INTR_X86_SSE41_PBLENDVB = 732 --INTR_X86_SSE41_PBLENDW = 733 --INTR_X86_SSE41_PCMPEQQ = 734 --INTR_X86_SSE41_PEXTRB = 735 --INTR_X86_SSE41_PEXTRD = 736 --INTR_X86_SSE41_PEXTRQ = 737 --INTR_X86_SSE41_PHMINPOSUW = 738 --INTR_X86_SSE41_PMAXSB = 739 --INTR_X86_SSE41_PMAXSD = 740 --INTR_X86_SSE41_PMAXUD = 741 --INTR_X86_SSE41_PMAXUW = 742 --INTR_X86_SSE41_PMINSB = 743 --INTR_X86_SSE41_PMINSD = 744 --INTR_X86_SSE41_PMINUD = 745 --INTR_X86_SSE41_PMINUW = 746 --INTR_X86_SSE41_PMOVSXBD = 747 --INTR_X86_SSE41_PMOVSXBQ = 748 --INTR_X86_SSE41_PMOVSXBW = 749 --INTR_X86_SSE41_PMOVSXDQ = 750 --INTR_X86_SSE41_PMOVSXWD = 751 --INTR_X86_SSE41_PMOVSXWQ = 752 --INTR_X86_SSE41_PMOVZXBD = 753 --INTR_X86_SSE41_PMOVZXBQ = 754 --INTR_X86_SSE41_PMOVZXBW = 755 --INTR_X86_SSE41_PMOVZXDQ = 756 --INTR_X86_SSE41_PMOVZXWD = 757 --INTR_X86_SSE41_PMOVZXWQ = 758 --INTR_X86_SSE41_PMULDQ = 759 --INTR_X86_SSE41_PTESTC = 760 --INTR_X86_SSE41_PTESTNZC = 761 --INTR_X86_SSE41_PTESTZ = 762 --INTR_X86_SSE41_ROUND_PD = 763 --INTR_X86_SSE41_ROUND_PS = 764 --INTR_X86_SSE41_ROUND_SD = 765 --INTR_X86_SSE41_ROUND_SS = 766 --INTR_X86_SSE42_CRC32_16 = 767 --INTR_X86_SSE42_CRC32_32 = 768 --INTR_X86_SSE42_CRC32_8 = 769 --INTR_X86_SSE42_CRC64_64 = 770 --INTR_X86_SSE42_CRC64_8 = 771 --INTR_X86_SSE42_PCMPESTRI128 = 772 --INTR_X86_SSE42_PCMPESTRIA128 = 773 --INTR_X86_SSE42_PCMPESTRIC128 = 774 --INTR_X86_SSE42_PCMPESTRIO128 = 775 --INTR_X86_SSE42_PCMPESTRIS128 = 776 --INTR_X86_SSE42_PCMPESTRIZ128 = 777 --INTR_X86_SSE42_PCMPESTRM128 = 778 --INTR_X86_SSE42_PCMPGTQ = 779 --INTR_X86_SSE42_PCMPISTRI128 = 780 --INTR_X86_SSE42_PCMPISTRIA128 = 781 --INTR_X86_SSE42_PCMPISTRIC128 = 782 --INTR_X86_SSE42_PCMPISTRIO128 = 783 --INTR_X86_SSE42_PCMPISTRIS128 = 784 --INTR_X86_SSE42_PCMPISTRIZ128 = 785 --INTR_X86_SSE42_PCMPISTRM128 = 786 --INTR_X86_SSE_ADD_SS = 787 --INTR_X86_SSE_CMP_PS = 788 --INTR_X86_SSE_CMP_SS = 789 --INTR_X86_SSE_COMIEQ_SS = 790 --INTR_X86_SSE_COMIGE_SS = 791 --INTR_X86_SSE_COMIGT_SS = 792 --INTR_X86_SSE_COMILE_SS = 793 --INTR_X86_SSE_COMILT_SS = 794 --INTR_X86_SSE_COMINEQ_SS = 795 --INTR_X86_SSE_CVTPD2PI = 796 --INTR_X86_SSE_CVTPI2PD = 797 --INTR_X86_SSE_CVTPI2PS = 798 --INTR_X86_SSE_CVTPS2PI = 799 --INTR_X86_SSE_CVTSI2SS = 800 --INTR_X86_SSE_CVTSI642SS = 801 --INTR_X86_SSE_CVTSS2SI = 802 --INTR_X86_SSE_CVTSS2SI64 = 803 --INTR_X86_SSE_CVTTPD2PI = 804 --INTR_X86_SSE_CVTTPS2PI = 805 --INTR_X86_SSE_CVTTSS2SI = 806 --INTR_X86_SSE_CVTTSS2SI64 = 807 --INTR_X86_SSE_DIV_SS = 808 --INTR_X86_SSE_LDMXCSR = 809 --INTR_X86_SSE_LOADU_PS = 810 --INTR_X86_SSE_MAX_PS = 811 --INTR_X86_SSE_MAX_SS = 812 --INTR_X86_SSE_MIN_PS = 813 --INTR_X86_SSE_MIN_SS = 814 --INTR_X86_SSE_MOVMSK_PS = 815 --INTR_X86_SSE_MOVNT_PS = 816 --INTR_X86_SSE_MUL_SS = 817 --INTR_X86_SSE_RCP_PS = 818 --INTR_X86_SSE_RCP_SS = 819 --INTR_X86_SSE_RSQRT_PS = 820 --INTR_X86_SSE_RSQRT_SS = 821 --INTR_X86_SSE_SFENCE = 822 --INTR_X86_SSE_SQRT_PS = 823 --INTR_X86_SSE_SQRT_SS = 824 --INTR_X86_SSE_STMXCSR = 825 --INTR_X86_SSE_STOREU_PS = 826 --INTR_X86_SSE_SUB_SS = 827 --INTR_X86_SSE_UCOMIEQ_SS = 828 --INTR_X86_SSE_UCOMIGE_SS = 829 --INTR_X86_SSE_UCOMIGT_SS = 830 --INTR_X86_SSE_UCOMILE_SS = 831 --INTR_X86_SSE_UCOMILT_SS = 832 --INTR_X86_SSE_UCOMINEQ_SS = 833 --INTR_X86_SSSE3_PABS_B = 834 --INTR_X86_SSSE3_PABS_B_128 = 835 --INTR_X86_SSSE3_PABS_D = 836 --INTR_X86_SSSE3_PABS_D_128 = 837 --INTR_X86_SSSE3_PABS_W = 838 --INTR_X86_SSSE3_PABS_W_128 = 839 --INTR_X86_SSSE3_PHADD_D = 840 --INTR_X86_SSSE3_PHADD_D_128 = 841 --INTR_X86_SSSE3_PHADD_SW = 842 --INTR_X86_SSSE3_PHADD_SW_128 = 843 --INTR_X86_SSSE3_PHADD_W = 844 --INTR_X86_SSSE3_PHADD_W_128 = 845 --INTR_X86_SSSE3_PHSUB_D = 846 --INTR_X86_SSSE3_PHSUB_D_128 = 847 --INTR_X86_SSSE3_PHSUB_SW = 848 --INTR_X86_SSSE3_PHSUB_SW_128 = 849 --INTR_X86_SSSE3_PHSUB_W = 850 --INTR_X86_SSSE3_PHSUB_W_128 = 851 --INTR_X86_SSSE3_PMADD_UB_SW = 852 --INTR_X86_SSSE3_PMADD_UB_SW_128 = 853 --INTR_X86_SSSE3_PMUL_HR_SW = 854 --INTR_X86_SSSE3_PMUL_HR_SW_128 = 855 --INTR_X86_SSSE3_PSHUF_B = 856 --INTR_X86_SSSE3_PSHUF_B_128 = 857 --INTR_X86_SSSE3_PSHUF_W = 858 --INTR_X86_SSSE3_PSIGN_B = 859 --INTR_X86_SSSE3_PSIGN_B_128 = 860 --INTR_X86_SSSE3_PSIGN_D = 861 --INTR_X86_SSSE3_PSIGN_D_128 = 862 --INTR_X86_SSSE3_PSIGN_W = 863 --INTR_X86_SSSE3_PSIGN_W_128 = 864 --INTR_XCORE_BITREV = 865 --INTR_XCORE_GETID = 866 -- -+INTR_ARM_NEON_VCVTFP2HF = 17 -+INTR_ARM_NEON_VCVTFXS2FP = 18 -+INTR_ARM_NEON_VCVTFXU2FP = 19 -+INTR_ARM_NEON_VCVTHF2FP = 20 -+INTR_ARM_NEON_VHADDS = 21 -+INTR_ARM_NEON_VHADDU = 22 -+INTR_ARM_NEON_VHSUBS = 23 -+INTR_ARM_NEON_VHSUBU = 24 -+INTR_ARM_NEON_VLD1 = 25 -+INTR_ARM_NEON_VLD2 = 26 -+INTR_ARM_NEON_VLD2LANE = 27 -+INTR_ARM_NEON_VLD3 = 28 -+INTR_ARM_NEON_VLD3LANE = 29 -+INTR_ARM_NEON_VLD4 = 30 -+INTR_ARM_NEON_VLD4LANE = 31 -+INTR_ARM_NEON_VMAXS = 32 -+INTR_ARM_NEON_VMAXU = 33 -+INTR_ARM_NEON_VMINS = 34 -+INTR_ARM_NEON_VMINU = 35 -+INTR_ARM_NEON_VMULLP = 36 -+INTR_ARM_NEON_VMULP = 37 -+INTR_ARM_NEON_VPADALS = 38 -+INTR_ARM_NEON_VPADALU = 39 -+INTR_ARM_NEON_VPADD = 40 -+INTR_ARM_NEON_VPADDLS = 41 -+INTR_ARM_NEON_VPADDLU = 42 -+INTR_ARM_NEON_VPMAXS = 43 -+INTR_ARM_NEON_VPMAXU = 44 -+INTR_ARM_NEON_VPMINS = 45 -+INTR_ARM_NEON_VPMINU = 46 -+INTR_ARM_NEON_VQABS = 47 -+INTR_ARM_NEON_VQADDS = 48 -+INTR_ARM_NEON_VQADDU = 49 -+INTR_ARM_NEON_VQDMLAL = 50 -+INTR_ARM_NEON_VQDMLSL = 51 -+INTR_ARM_NEON_VQDMULH = 52 -+INTR_ARM_NEON_VQDMULL = 53 -+INTR_ARM_NEON_VQMOVNS = 54 -+INTR_ARM_NEON_VQMOVNSU = 55 -+INTR_ARM_NEON_VQMOVNU = 56 -+INTR_ARM_NEON_VQNEG = 57 -+INTR_ARM_NEON_VQRDMULH = 58 -+INTR_ARM_NEON_VQRSHIFTNS = 59 -+INTR_ARM_NEON_VQRSHIFTNSU = 60 -+INTR_ARM_NEON_VQRSHIFTNU = 61 -+INTR_ARM_NEON_VQRSHIFTS = 62 -+INTR_ARM_NEON_VQRSHIFTU = 63 -+INTR_ARM_NEON_VQSHIFTNS = 64 -+INTR_ARM_NEON_VQSHIFTNSU = 65 -+INTR_ARM_NEON_VQSHIFTNU = 66 -+INTR_ARM_NEON_VQSHIFTS = 67 -+INTR_ARM_NEON_VQSHIFTSU = 68 -+INTR_ARM_NEON_VQSHIFTU = 69 -+INTR_ARM_NEON_VQSUBS = 70 -+INTR_ARM_NEON_VQSUBU = 71 -+INTR_ARM_NEON_VRADDHN = 72 -+INTR_ARM_NEON_VRECPE = 73 -+INTR_ARM_NEON_VRECPS = 74 -+INTR_ARM_NEON_VRHADDS = 75 -+INTR_ARM_NEON_VRHADDU = 76 -+INTR_ARM_NEON_VRSHIFTN = 77 -+INTR_ARM_NEON_VRSHIFTS = 78 -+INTR_ARM_NEON_VRSHIFTU = 79 -+INTR_ARM_NEON_VRSQRTE = 80 -+INTR_ARM_NEON_VRSQRTS = 81 -+INTR_ARM_NEON_VRSUBHN = 82 -+INTR_ARM_NEON_VSHIFTINS = 83 -+INTR_ARM_NEON_VSHIFTLS = 84 -+INTR_ARM_NEON_VSHIFTLU = 85 -+INTR_ARM_NEON_VSHIFTN = 86 -+INTR_ARM_NEON_VSHIFTS = 87 -+INTR_ARM_NEON_VSHIFTU = 88 -+INTR_ARM_NEON_VST1 = 89 -+INTR_ARM_NEON_VST2 = 90 -+INTR_ARM_NEON_VST2LANE = 91 -+INTR_ARM_NEON_VST3 = 92 -+INTR_ARM_NEON_VST3LANE = 93 -+INTR_ARM_NEON_VST4 = 94 -+INTR_ARM_NEON_VST4LANE = 95 -+INTR_ARM_NEON_VSUBHN = 96 -+INTR_ARM_NEON_VTBL1 = 97 -+INTR_ARM_NEON_VTBL2 = 98 -+INTR_ARM_NEON_VTBL3 = 99 -+INTR_ARM_NEON_VTBL4 = 100 -+INTR_ARM_NEON_VTBX1 = 101 -+INTR_ARM_NEON_VTBX2 = 102 -+INTR_ARM_NEON_VTBX3 = 103 -+INTR_ARM_NEON_VTBX4 = 104 -+INTR_ARM_QADD = 105 -+INTR_ARM_QSUB = 106 -+INTR_ARM_SET_FPSCR = 107 -+INTR_ARM_SSAT = 108 -+INTR_ARM_THREAD_POINTER = 109 -+INTR_ARM_USAT = 110 -+INTR_ARM_VCVTR = 111 -+INTR_ARM_VCVTRU = 112 -+INTR_ATOMIC_CMP_SWAP = 113 -+INTR_ATOMIC_LOAD_ADD = 114 -+INTR_ATOMIC_LOAD_AND = 115 -+INTR_ATOMIC_LOAD_MAX = 116 -+INTR_ATOMIC_LOAD_MIN = 117 -+INTR_ATOMIC_LOAD_NAND = 118 -+INTR_ATOMIC_LOAD_OR = 119 -+INTR_ATOMIC_LOAD_SUB = 120 -+INTR_ATOMIC_LOAD_UMAX = 121 -+INTR_ATOMIC_LOAD_UMIN = 122 -+INTR_ATOMIC_LOAD_XOR = 123 -+INTR_ATOMIC_SWAP = 124 -+INTR_BSWAP = 125 -+INTR_CONVERT_FROM_FP16 = 126 -+INTR_CONVERT_TO_FP16 = 127 -+INTR_CONVERTFF = 128 -+INTR_CONVERTFSI = 129 -+INTR_CONVERTFUI = 130 -+INTR_CONVERTSIF = 131 -+INTR_CONVERTSS = 132 -+INTR_CONVERTSU = 133 -+INTR_CONVERTUIF = 134 -+INTR_CONVERTUS = 135 -+INTR_CONVERTUU = 136 -+INTR_COS = 137 -+INTR_CTLZ = 138 -+INTR_CTPOP = 139 -+INTR_CTTZ = 140 -+INTR_DBG_DECLARE = 141 -+INTR_DBG_VALUE = 142 -+INTR_EH_DWARF_CFA = 143 -+INTR_EH_EXCEPTION = 144 -+INTR_EH_RETURN_I32 = 145 -+INTR_EH_RETURN_I64 = 146 -+INTR_EH_SELECTOR = 147 -+INTR_EH_SJLJ_CALLSITE = 148 -+INTR_EH_SJLJ_DISPATCH_SETUP = 149 -+INTR_EH_SJLJ_LONGJMP = 150 -+INTR_EH_SJLJ_LSDA = 151 -+INTR_EH_SJLJ_SETJMP = 152 -+INTR_EH_TYPEID_FOR = 153 -+INTR_EH_UNWIND_INIT = 154 -+INTR_EXP = 155 -+INTR_EXP2 = 156 -+INTR_FLT_ROUNDS = 157 -+INTR_FRAMEADDRESS = 158 -+INTR_GCREAD = 159 -+INTR_GCROOT = 160 -+INTR_GCWRITE = 161 -+INTR_INIT_TRAMPOLINE = 162 -+INTR_INVARIANT_END = 163 -+INTR_INVARIANT_START = 164 -+INTR_LIFETIME_END = 165 -+INTR_LIFETIME_START = 166 -+INTR_LOG = 167 -+INTR_LOG10 = 168 -+INTR_LOG2 = 169 -+INTR_LONGJMP = 170 -+INTR_MEMCPY = 171 -+INTR_MEMMOVE = 172 -+INTR_MEMORY_BARRIER = 173 -+INTR_MEMSET = 174 -+INTR_OBJECTSIZE = 175 -+INTR_PCMARKER = 176 -+INTR_POW = 177 -+INTR_POWI = 178 -+INTR_PPC_ALTIVEC_DSS = 179 -+INTR_PPC_ALTIVEC_DSSALL = 180 -+INTR_PPC_ALTIVEC_DST = 181 -+INTR_PPC_ALTIVEC_DSTST = 182 -+INTR_PPC_ALTIVEC_DSTSTT = 183 -+INTR_PPC_ALTIVEC_DSTT = 184 -+INTR_PPC_ALTIVEC_LVEBX = 185 -+INTR_PPC_ALTIVEC_LVEHX = 186 -+INTR_PPC_ALTIVEC_LVEWX = 187 -+INTR_PPC_ALTIVEC_LVSL = 188 -+INTR_PPC_ALTIVEC_LVSR = 189 -+INTR_PPC_ALTIVEC_LVX = 190 -+INTR_PPC_ALTIVEC_LVXL = 191 -+INTR_PPC_ALTIVEC_MFVSCR = 192 -+INTR_PPC_ALTIVEC_MTVSCR = 193 -+INTR_PPC_ALTIVEC_STVEBX = 194 -+INTR_PPC_ALTIVEC_STVEHX = 195 -+INTR_PPC_ALTIVEC_STVEWX = 196 -+INTR_PPC_ALTIVEC_STVX = 197 -+INTR_PPC_ALTIVEC_STVXL = 198 -+INTR_PPC_ALTIVEC_VADDCUW = 199 -+INTR_PPC_ALTIVEC_VADDSBS = 200 -+INTR_PPC_ALTIVEC_VADDSHS = 201 -+INTR_PPC_ALTIVEC_VADDSWS = 202 -+INTR_PPC_ALTIVEC_VADDUBS = 203 -+INTR_PPC_ALTIVEC_VADDUHS = 204 -+INTR_PPC_ALTIVEC_VADDUWS = 205 -+INTR_PPC_ALTIVEC_VAVGSB = 206 -+INTR_PPC_ALTIVEC_VAVGSH = 207 -+INTR_PPC_ALTIVEC_VAVGSW = 208 -+INTR_PPC_ALTIVEC_VAVGUB = 209 -+INTR_PPC_ALTIVEC_VAVGUH = 210 -+INTR_PPC_ALTIVEC_VAVGUW = 211 -+INTR_PPC_ALTIVEC_VCFSX = 212 -+INTR_PPC_ALTIVEC_VCFUX = 213 -+INTR_PPC_ALTIVEC_VCMPBFP = 214 -+INTR_PPC_ALTIVEC_VCMPBFP_P = 215 -+INTR_PPC_ALTIVEC_VCMPEQFP = 216 -+INTR_PPC_ALTIVEC_VCMPEQFP_P = 217 -+INTR_PPC_ALTIVEC_VCMPEQUB = 218 -+INTR_PPC_ALTIVEC_VCMPEQUB_P = 219 -+INTR_PPC_ALTIVEC_VCMPEQUH = 220 -+INTR_PPC_ALTIVEC_VCMPEQUH_P = 221 -+INTR_PPC_ALTIVEC_VCMPEQUW = 222 -+INTR_PPC_ALTIVEC_VCMPEQUW_P = 223 -+INTR_PPC_ALTIVEC_VCMPGEFP = 224 -+INTR_PPC_ALTIVEC_VCMPGEFP_P = 225 -+INTR_PPC_ALTIVEC_VCMPGTFP = 226 -+INTR_PPC_ALTIVEC_VCMPGTFP_P = 227 -+INTR_PPC_ALTIVEC_VCMPGTSB = 228 -+INTR_PPC_ALTIVEC_VCMPGTSB_P = 229 -+INTR_PPC_ALTIVEC_VCMPGTSH = 230 -+INTR_PPC_ALTIVEC_VCMPGTSH_P = 231 -+INTR_PPC_ALTIVEC_VCMPGTSW = 232 -+INTR_PPC_ALTIVEC_VCMPGTSW_P = 233 -+INTR_PPC_ALTIVEC_VCMPGTUB = 234 -+INTR_PPC_ALTIVEC_VCMPGTUB_P = 235 -+INTR_PPC_ALTIVEC_VCMPGTUH = 236 -+INTR_PPC_ALTIVEC_VCMPGTUH_P = 237 -+INTR_PPC_ALTIVEC_VCMPGTUW = 238 -+INTR_PPC_ALTIVEC_VCMPGTUW_P = 239 -+INTR_PPC_ALTIVEC_VCTSXS = 240 -+INTR_PPC_ALTIVEC_VCTUXS = 241 -+INTR_PPC_ALTIVEC_VEXPTEFP = 242 -+INTR_PPC_ALTIVEC_VLOGEFP = 243 -+INTR_PPC_ALTIVEC_VMADDFP = 244 -+INTR_PPC_ALTIVEC_VMAXFP = 245 -+INTR_PPC_ALTIVEC_VMAXSB = 246 -+INTR_PPC_ALTIVEC_VMAXSH = 247 -+INTR_PPC_ALTIVEC_VMAXSW = 248 -+INTR_PPC_ALTIVEC_VMAXUB = 249 -+INTR_PPC_ALTIVEC_VMAXUH = 250 -+INTR_PPC_ALTIVEC_VMAXUW = 251 -+INTR_PPC_ALTIVEC_VMHADDSHS = 252 -+INTR_PPC_ALTIVEC_VMHRADDSHS = 253 -+INTR_PPC_ALTIVEC_VMINFP = 254 -+INTR_PPC_ALTIVEC_VMINSB = 255 -+INTR_PPC_ALTIVEC_VMINSH = 256 -+INTR_PPC_ALTIVEC_VMINSW = 257 -+INTR_PPC_ALTIVEC_VMINUB = 258 -+INTR_PPC_ALTIVEC_VMINUH = 259 -+INTR_PPC_ALTIVEC_VMINUW = 260 -+INTR_PPC_ALTIVEC_VMLADDUHM = 261 -+INTR_PPC_ALTIVEC_VMSUMMBM = 262 -+INTR_PPC_ALTIVEC_VMSUMSHM = 263 -+INTR_PPC_ALTIVEC_VMSUMSHS = 264 -+INTR_PPC_ALTIVEC_VMSUMUBM = 265 -+INTR_PPC_ALTIVEC_VMSUMUHM = 266 -+INTR_PPC_ALTIVEC_VMSUMUHS = 267 -+INTR_PPC_ALTIVEC_VMULESB = 268 -+INTR_PPC_ALTIVEC_VMULESH = 269 -+INTR_PPC_ALTIVEC_VMULEUB = 270 -+INTR_PPC_ALTIVEC_VMULEUH = 271 -+INTR_PPC_ALTIVEC_VMULOSB = 272 -+INTR_PPC_ALTIVEC_VMULOSH = 273 -+INTR_PPC_ALTIVEC_VMULOUB = 274 -+INTR_PPC_ALTIVEC_VMULOUH = 275 -+INTR_PPC_ALTIVEC_VNMSUBFP = 276 -+INTR_PPC_ALTIVEC_VPERM = 277 -+INTR_PPC_ALTIVEC_VPKPX = 278 -+INTR_PPC_ALTIVEC_VPKSHSS = 279 -+INTR_PPC_ALTIVEC_VPKSHUS = 280 -+INTR_PPC_ALTIVEC_VPKSWSS = 281 -+INTR_PPC_ALTIVEC_VPKSWUS = 282 -+INTR_PPC_ALTIVEC_VPKUHUS = 283 -+INTR_PPC_ALTIVEC_VPKUWUS = 284 -+INTR_PPC_ALTIVEC_VREFP = 285 -+INTR_PPC_ALTIVEC_VRFIM = 286 -+INTR_PPC_ALTIVEC_VRFIN = 287 -+INTR_PPC_ALTIVEC_VRFIP = 288 -+INTR_PPC_ALTIVEC_VRFIZ = 289 -+INTR_PPC_ALTIVEC_VRLB = 290 -+INTR_PPC_ALTIVEC_VRLH = 291 -+INTR_PPC_ALTIVEC_VRLW = 292 -+INTR_PPC_ALTIVEC_VRSQRTEFP = 293 -+INTR_PPC_ALTIVEC_VSEL = 294 -+INTR_PPC_ALTIVEC_VSL = 295 -+INTR_PPC_ALTIVEC_VSLB = 296 -+INTR_PPC_ALTIVEC_VSLH = 297 -+INTR_PPC_ALTIVEC_VSLO = 298 -+INTR_PPC_ALTIVEC_VSLW = 299 -+INTR_PPC_ALTIVEC_VSR = 300 -+INTR_PPC_ALTIVEC_VSRAB = 301 -+INTR_PPC_ALTIVEC_VSRAH = 302 -+INTR_PPC_ALTIVEC_VSRAW = 303 -+INTR_PPC_ALTIVEC_VSRB = 304 -+INTR_PPC_ALTIVEC_VSRH = 305 -+INTR_PPC_ALTIVEC_VSRO = 306 -+INTR_PPC_ALTIVEC_VSRW = 307 -+INTR_PPC_ALTIVEC_VSUBCUW = 308 -+INTR_PPC_ALTIVEC_VSUBSBS = 309 -+INTR_PPC_ALTIVEC_VSUBSHS = 310 -+INTR_PPC_ALTIVEC_VSUBSWS = 311 -+INTR_PPC_ALTIVEC_VSUBUBS = 312 -+INTR_PPC_ALTIVEC_VSUBUHS = 313 -+INTR_PPC_ALTIVEC_VSUBUWS = 314 -+INTR_PPC_ALTIVEC_VSUM2SWS = 315 -+INTR_PPC_ALTIVEC_VSUM4SBS = 316 -+INTR_PPC_ALTIVEC_VSUM4SHS = 317 -+INTR_PPC_ALTIVEC_VSUM4UBS = 318 -+INTR_PPC_ALTIVEC_VSUMSWS = 319 -+INTR_PPC_ALTIVEC_VUPKHPX = 320 -+INTR_PPC_ALTIVEC_VUPKHSB = 321 -+INTR_PPC_ALTIVEC_VUPKHSH = 322 -+INTR_PPC_ALTIVEC_VUPKLPX = 323 -+INTR_PPC_ALTIVEC_VUPKLSB = 324 -+INTR_PPC_ALTIVEC_VUPKLSH = 325 -+INTR_PPC_DCBA = 326 -+INTR_PPC_DCBF = 327 -+INTR_PPC_DCBI = 328 -+INTR_PPC_DCBST = 329 -+INTR_PPC_DCBT = 330 -+INTR_PPC_DCBTST = 331 -+INTR_PPC_DCBZ = 332 -+INTR_PPC_DCBZL = 333 -+INTR_PPC_SYNC = 334 -+INTR_PREFETCH = 335 -+INTR_PTR_ANNOTATION = 336 -+INTR_PTX_BAR_SYNC = 337 -+INTR_PTX_READ_TID_R64 = 338 -+INTR_PTX_READ_TID_V4I16 = 339 -+INTR_PTX_READ_TID_W = 340 -+INTR_PTX_READ_TID_X = 341 -+INTR_PTX_READ_TID_Y = 342 -+INTR_PTX_READ_TID_Z = 343 -+INTR_READCYCLECOUNTER = 344 -+INTR_RETURNADDRESS = 345 -+INTR_SADD_WITH_OVERFLOW = 346 -+INTR_SETJMP = 347 -+INTR_SIGLONGJMP = 348 -+INTR_SIGSETJMP = 349 -+INTR_SIN = 350 -+INTR_SMUL_WITH_OVERFLOW = 351 -+INTR_SPU_SI_A = 352 -+INTR_SPU_SI_ADDX = 353 -+INTR_SPU_SI_AH = 354 -+INTR_SPU_SI_AHI = 355 -+INTR_SPU_SI_AI = 356 -+INTR_SPU_SI_AND = 357 -+INTR_SPU_SI_ANDBI = 358 -+INTR_SPU_SI_ANDC = 359 -+INTR_SPU_SI_ANDHI = 360 -+INTR_SPU_SI_ANDI = 361 -+INTR_SPU_SI_BG = 362 -+INTR_SPU_SI_BGX = 363 -+INTR_SPU_SI_CEQ = 364 -+INTR_SPU_SI_CEQB = 365 -+INTR_SPU_SI_CEQBI = 366 -+INTR_SPU_SI_CEQH = 367 -+INTR_SPU_SI_CEQHI = 368 -+INTR_SPU_SI_CEQI = 369 -+INTR_SPU_SI_CG = 370 -+INTR_SPU_SI_CGT = 371 -+INTR_SPU_SI_CGTB = 372 -+INTR_SPU_SI_CGTBI = 373 -+INTR_SPU_SI_CGTH = 374 -+INTR_SPU_SI_CGTHI = 375 -+INTR_SPU_SI_CGTI = 376 -+INTR_SPU_SI_CGX = 377 -+INTR_SPU_SI_CLGT = 378 -+INTR_SPU_SI_CLGTB = 379 -+INTR_SPU_SI_CLGTBI = 380 -+INTR_SPU_SI_CLGTH = 381 -+INTR_SPU_SI_CLGTHI = 382 -+INTR_SPU_SI_CLGTI = 383 -+INTR_SPU_SI_DFA = 384 -+INTR_SPU_SI_DFM = 385 -+INTR_SPU_SI_DFMA = 386 -+INTR_SPU_SI_DFMS = 387 -+INTR_SPU_SI_DFNMA = 388 -+INTR_SPU_SI_DFNMS = 389 -+INTR_SPU_SI_DFS = 390 -+INTR_SPU_SI_FA = 391 -+INTR_SPU_SI_FCEQ = 392 -+INTR_SPU_SI_FCGT = 393 -+INTR_SPU_SI_FCMEQ = 394 -+INTR_SPU_SI_FCMGT = 395 -+INTR_SPU_SI_FM = 396 -+INTR_SPU_SI_FMA = 397 -+INTR_SPU_SI_FMS = 398 -+INTR_SPU_SI_FNMS = 399 -+INTR_SPU_SI_FS = 400 -+INTR_SPU_SI_FSMBI = 401 -+INTR_SPU_SI_MPY = 402 -+INTR_SPU_SI_MPYA = 403 -+INTR_SPU_SI_MPYH = 404 -+INTR_SPU_SI_MPYHH = 405 -+INTR_SPU_SI_MPYHHA = 406 -+INTR_SPU_SI_MPYHHAU = 407 -+INTR_SPU_SI_MPYHHU = 408 -+INTR_SPU_SI_MPYI = 409 -+INTR_SPU_SI_MPYS = 410 -+INTR_SPU_SI_MPYU = 411 -+INTR_SPU_SI_MPYUI = 412 -+INTR_SPU_SI_NAND = 413 -+INTR_SPU_SI_NOR = 414 -+INTR_SPU_SI_OR = 415 -+INTR_SPU_SI_ORBI = 416 -+INTR_SPU_SI_ORC = 417 -+INTR_SPU_SI_ORHI = 418 -+INTR_SPU_SI_ORI = 419 -+INTR_SPU_SI_SF = 420 -+INTR_SPU_SI_SFH = 421 -+INTR_SPU_SI_SFHI = 422 -+INTR_SPU_SI_SFI = 423 -+INTR_SPU_SI_SFX = 424 -+INTR_SPU_SI_SHLI = 425 -+INTR_SPU_SI_SHLQBI = 426 -+INTR_SPU_SI_SHLQBII = 427 -+INTR_SPU_SI_SHLQBY = 428 -+INTR_SPU_SI_SHLQBYI = 429 -+INTR_SPU_SI_XOR = 430 -+INTR_SPU_SI_XORBI = 431 -+INTR_SPU_SI_XORHI = 432 -+INTR_SPU_SI_XORI = 433 -+INTR_SQRT = 434 -+INTR_SSUB_WITH_OVERFLOW = 435 -+INTR_STACKPROTECTOR = 436 -+INTR_STACKRESTORE = 437 -+INTR_STACKSAVE = 438 -+INTR_TRAP = 439 -+INTR_UADD_WITH_OVERFLOW = 440 -+INTR_UMUL_WITH_OVERFLOW = 441 -+INTR_USUB_WITH_OVERFLOW = 442 -+INTR_VACOPY = 443 -+INTR_VAEND = 444 -+INTR_VAR_ANNOTATION = 445 -+INTR_VASTART = 446 -+INTR_X86_AESNI_AESDEC = 447 -+INTR_X86_AESNI_AESDECLAST = 448 -+INTR_X86_AESNI_AESENC = 449 -+INTR_X86_AESNI_AESENCLAST = 450 -+INTR_X86_AESNI_AESIMC = 451 -+INTR_X86_AESNI_AESKEYGENASSIST = 452 -+INTR_X86_AVX_ADDSUB_PD_256 = 453 -+INTR_X86_AVX_ADDSUB_PS_256 = 454 -+INTR_X86_AVX_BLEND_PD_256 = 455 -+INTR_X86_AVX_BLEND_PS_256 = 456 -+INTR_X86_AVX_BLENDV_PD_256 = 457 -+INTR_X86_AVX_BLENDV_PS_256 = 458 -+INTR_X86_AVX_CMP_PD_256 = 459 -+INTR_X86_AVX_CMP_PS_256 = 460 -+INTR_X86_AVX_CVT_PD2_PS_256 = 461 -+INTR_X86_AVX_CVT_PD2DQ_256 = 462 -+INTR_X86_AVX_CVT_PS2_PD_256 = 463 -+INTR_X86_AVX_CVT_PS2DQ_256 = 464 -+INTR_X86_AVX_CVTDQ2_PD_256 = 465 -+INTR_X86_AVX_CVTDQ2_PS_256 = 466 -+INTR_X86_AVX_CVTT_PD2DQ_256 = 467 -+INTR_X86_AVX_CVTT_PS2DQ_256 = 468 -+INTR_X86_AVX_DP_PS_256 = 469 -+INTR_X86_AVX_HADD_PD_256 = 470 -+INTR_X86_AVX_HADD_PS_256 = 471 -+INTR_X86_AVX_HSUB_PD_256 = 472 -+INTR_X86_AVX_HSUB_PS_256 = 473 -+INTR_X86_AVX_LDU_DQ_256 = 474 -+INTR_X86_AVX_LOADU_DQ_256 = 475 -+INTR_X86_AVX_LOADU_PD_256 = 476 -+INTR_X86_AVX_LOADU_PS_256 = 477 -+INTR_X86_AVX_MASKLOAD_PD = 478 -+INTR_X86_AVX_MASKLOAD_PD_256 = 479 -+INTR_X86_AVX_MASKLOAD_PS = 480 -+INTR_X86_AVX_MASKLOAD_PS_256 = 481 -+INTR_X86_AVX_MASKSTORE_PD = 482 -+INTR_X86_AVX_MASKSTORE_PD_256 = 483 -+INTR_X86_AVX_MASKSTORE_PS = 484 -+INTR_X86_AVX_MASKSTORE_PS_256 = 485 -+INTR_X86_AVX_MAX_PD_256 = 486 -+INTR_X86_AVX_MAX_PS_256 = 487 -+INTR_X86_AVX_MIN_PD_256 = 488 -+INTR_X86_AVX_MIN_PS_256 = 489 -+INTR_X86_AVX_MOVMSK_PD_256 = 490 -+INTR_X86_AVX_MOVMSK_PS_256 = 491 -+INTR_X86_AVX_MOVNT_DQ_256 = 492 -+INTR_X86_AVX_MOVNT_PD_256 = 493 -+INTR_X86_AVX_MOVNT_PS_256 = 494 -+INTR_X86_AVX_PTESTC_256 = 495 -+INTR_X86_AVX_PTESTNZC_256 = 496 -+INTR_X86_AVX_PTESTZ_256 = 497 -+INTR_X86_AVX_RCP_PS_256 = 498 -+INTR_X86_AVX_ROUND_PD_256 = 499 -+INTR_X86_AVX_ROUND_PS_256 = 500 -+INTR_X86_AVX_RSQRT_PS_256 = 501 -+INTR_X86_AVX_SQRT_PD_256 = 502 -+INTR_X86_AVX_SQRT_PS_256 = 503 -+INTR_X86_AVX_STOREU_DQ_256 = 504 -+INTR_X86_AVX_STOREU_PD_256 = 505 -+INTR_X86_AVX_STOREU_PS_256 = 506 -+INTR_X86_AVX_VBROADCAST_SD_256 = 507 -+INTR_X86_AVX_VBROADCASTF128_PD_256 = 508 -+INTR_X86_AVX_VBROADCASTF128_PS_256 = 509 -+INTR_X86_AVX_VBROADCASTSS = 510 -+INTR_X86_AVX_VBROADCASTSS_256 = 511 -+INTR_X86_AVX_VEXTRACTF128_PD_256 = 512 -+INTR_X86_AVX_VEXTRACTF128_PS_256 = 513 -+INTR_X86_AVX_VEXTRACTF128_SI_256 = 514 -+INTR_X86_AVX_VINSERTF128_PD_256 = 515 -+INTR_X86_AVX_VINSERTF128_PS_256 = 516 -+INTR_X86_AVX_VINSERTF128_SI_256 = 517 -+INTR_X86_AVX_VPERM2F128_PD_256 = 518 -+INTR_X86_AVX_VPERM2F128_PS_256 = 519 -+INTR_X86_AVX_VPERM2F128_SI_256 = 520 -+INTR_X86_AVX_VPERMIL_PD = 521 -+INTR_X86_AVX_VPERMIL_PD_256 = 522 -+INTR_X86_AVX_VPERMIL_PS = 523 -+INTR_X86_AVX_VPERMIL_PS_256 = 524 -+INTR_X86_AVX_VPERMILVAR_PD = 525 -+INTR_X86_AVX_VPERMILVAR_PD_256 = 526 -+INTR_X86_AVX_VPERMILVAR_PS = 527 -+INTR_X86_AVX_VPERMILVAR_PS_256 = 528 -+INTR_X86_AVX_VTESTC_PD = 529 -+INTR_X86_AVX_VTESTC_PD_256 = 530 -+INTR_X86_AVX_VTESTC_PS = 531 -+INTR_X86_AVX_VTESTC_PS_256 = 532 -+INTR_X86_AVX_VTESTNZC_PD = 533 -+INTR_X86_AVX_VTESTNZC_PD_256 = 534 -+INTR_X86_AVX_VTESTNZC_PS = 535 -+INTR_X86_AVX_VTESTNZC_PS_256 = 536 -+INTR_X86_AVX_VTESTZ_PD = 537 -+INTR_X86_AVX_VTESTZ_PD_256 = 538 -+INTR_X86_AVX_VTESTZ_PS = 539 -+INTR_X86_AVX_VTESTZ_PS_256 = 540 -+INTR_X86_AVX_VZEROALL = 541 -+INTR_X86_AVX_VZEROUPPER = 542 -+INTR_X86_INT = 543 -+INTR_X86_MMX_EMMS = 544 -+INTR_X86_MMX_FEMMS = 545 -+INTR_X86_MMX_MASKMOVQ = 546 -+INTR_X86_MMX_MOVNT_DQ = 547 -+INTR_X86_MMX_PACKSSDW = 548 -+INTR_X86_MMX_PACKSSWB = 549 -+INTR_X86_MMX_PACKUSWB = 550 -+INTR_X86_MMX_PADD_B = 551 -+INTR_X86_MMX_PADD_D = 552 -+INTR_X86_MMX_PADD_Q = 553 -+INTR_X86_MMX_PADD_W = 554 -+INTR_X86_MMX_PADDS_B = 555 -+INTR_X86_MMX_PADDS_W = 556 -+INTR_X86_MMX_PADDUS_B = 557 -+INTR_X86_MMX_PADDUS_W = 558 -+INTR_X86_MMX_PALIGNR_B = 559 -+INTR_X86_MMX_PAND = 560 -+INTR_X86_MMX_PANDN = 561 -+INTR_X86_MMX_PAVG_B = 562 -+INTR_X86_MMX_PAVG_W = 563 -+INTR_X86_MMX_PCMPEQ_B = 564 -+INTR_X86_MMX_PCMPEQ_D = 565 -+INTR_X86_MMX_PCMPEQ_W = 566 -+INTR_X86_MMX_PCMPGT_B = 567 -+INTR_X86_MMX_PCMPGT_D = 568 -+INTR_X86_MMX_PCMPGT_W = 569 -+INTR_X86_MMX_PEXTR_W = 570 -+INTR_X86_MMX_PINSR_W = 571 -+INTR_X86_MMX_PMADD_WD = 572 -+INTR_X86_MMX_PMAXS_W = 573 -+INTR_X86_MMX_PMAXU_B = 574 -+INTR_X86_MMX_PMINS_W = 575 -+INTR_X86_MMX_PMINU_B = 576 -+INTR_X86_MMX_PMOVMSKB = 577 -+INTR_X86_MMX_PMULH_W = 578 -+INTR_X86_MMX_PMULHU_W = 579 -+INTR_X86_MMX_PMULL_W = 580 -+INTR_X86_MMX_PMULU_DQ = 581 -+INTR_X86_MMX_POR = 582 -+INTR_X86_MMX_PSAD_BW = 583 -+INTR_X86_MMX_PSLL_D = 584 -+INTR_X86_MMX_PSLL_Q = 585 -+INTR_X86_MMX_PSLL_W = 586 -+INTR_X86_MMX_PSLLI_D = 587 -+INTR_X86_MMX_PSLLI_Q = 588 -+INTR_X86_MMX_PSLLI_W = 589 -+INTR_X86_MMX_PSRA_D = 590 -+INTR_X86_MMX_PSRA_W = 591 -+INTR_X86_MMX_PSRAI_D = 592 -+INTR_X86_MMX_PSRAI_W = 593 -+INTR_X86_MMX_PSRL_D = 594 -+INTR_X86_MMX_PSRL_Q = 595 -+INTR_X86_MMX_PSRL_W = 596 -+INTR_X86_MMX_PSRLI_D = 597 -+INTR_X86_MMX_PSRLI_Q = 598 -+INTR_X86_MMX_PSRLI_W = 599 -+INTR_X86_MMX_PSUB_B = 600 -+INTR_X86_MMX_PSUB_D = 601 -+INTR_X86_MMX_PSUB_Q = 602 -+INTR_X86_MMX_PSUB_W = 603 -+INTR_X86_MMX_PSUBS_B = 604 -+INTR_X86_MMX_PSUBS_W = 605 -+INTR_X86_MMX_PSUBUS_B = 606 -+INTR_X86_MMX_PSUBUS_W = 607 -+INTR_X86_MMX_PUNPCKHBW = 608 -+INTR_X86_MMX_PUNPCKHDQ = 609 -+INTR_X86_MMX_PUNPCKHWD = 610 -+INTR_X86_MMX_PUNPCKLBW = 611 -+INTR_X86_MMX_PUNPCKLDQ = 612 -+INTR_X86_MMX_PUNPCKLWD = 613 -+INTR_X86_MMX_PXOR = 614 -+INTR_X86_SSE2_ADD_SD = 615 -+INTR_X86_SSE2_CLFLUSH = 616 -+INTR_X86_SSE2_CMP_PD = 617 -+INTR_X86_SSE2_CMP_SD = 618 -+INTR_X86_SSE2_COMIEQ_SD = 619 -+INTR_X86_SSE2_COMIGE_SD = 620 -+INTR_X86_SSE2_COMIGT_SD = 621 -+INTR_X86_SSE2_COMILE_SD = 622 -+INTR_X86_SSE2_COMILT_SD = 623 -+INTR_X86_SSE2_COMINEQ_SD = 624 -+INTR_X86_SSE2_CVTDQ2PD = 625 -+INTR_X86_SSE2_CVTDQ2PS = 626 -+INTR_X86_SSE2_CVTPD2DQ = 627 -+INTR_X86_SSE2_CVTPD2PS = 628 -+INTR_X86_SSE2_CVTPS2DQ = 629 -+INTR_X86_SSE2_CVTPS2PD = 630 -+INTR_X86_SSE2_CVTSD2SI = 631 -+INTR_X86_SSE2_CVTSD2SI64 = 632 -+INTR_X86_SSE2_CVTSD2SS = 633 -+INTR_X86_SSE2_CVTSI2SD = 634 -+INTR_X86_SSE2_CVTSI642SD = 635 -+INTR_X86_SSE2_CVTSS2SD = 636 -+INTR_X86_SSE2_CVTTPD2DQ = 637 -+INTR_X86_SSE2_CVTTPS2DQ = 638 -+INTR_X86_SSE2_CVTTSD2SI = 639 -+INTR_X86_SSE2_CVTTSD2SI64 = 640 -+INTR_X86_SSE2_DIV_SD = 641 -+INTR_X86_SSE2_LFENCE = 642 -+INTR_X86_SSE2_LOADU_DQ = 643 -+INTR_X86_SSE2_LOADU_PD = 644 -+INTR_X86_SSE2_MASKMOV_DQU = 645 -+INTR_X86_SSE2_MAX_PD = 646 -+INTR_X86_SSE2_MAX_SD = 647 -+INTR_X86_SSE2_MFENCE = 648 -+INTR_X86_SSE2_MIN_PD = 649 -+INTR_X86_SSE2_MIN_SD = 650 -+INTR_X86_SSE2_MOVMSK_PD = 651 -+INTR_X86_SSE2_MOVNT_DQ = 652 -+INTR_X86_SSE2_MOVNT_I = 653 -+INTR_X86_SSE2_MOVNT_PD = 654 -+INTR_X86_SSE2_MUL_SD = 655 -+INTR_X86_SSE2_PACKSSDW_128 = 656 -+INTR_X86_SSE2_PACKSSWB_128 = 657 -+INTR_X86_SSE2_PACKUSWB_128 = 658 -+INTR_X86_SSE2_PADDS_B = 659 -+INTR_X86_SSE2_PADDS_W = 660 -+INTR_X86_SSE2_PADDUS_B = 661 -+INTR_X86_SSE2_PADDUS_W = 662 -+INTR_X86_SSE2_PAVG_B = 663 -+INTR_X86_SSE2_PAVG_W = 664 -+INTR_X86_SSE2_PCMPEQ_B = 665 -+INTR_X86_SSE2_PCMPEQ_D = 666 -+INTR_X86_SSE2_PCMPEQ_W = 667 -+INTR_X86_SSE2_PCMPGT_B = 668 -+INTR_X86_SSE2_PCMPGT_D = 669 -+INTR_X86_SSE2_PCMPGT_W = 670 -+INTR_X86_SSE2_PMADD_WD = 671 -+INTR_X86_SSE2_PMAXS_W = 672 -+INTR_X86_SSE2_PMAXU_B = 673 -+INTR_X86_SSE2_PMINS_W = 674 -+INTR_X86_SSE2_PMINU_B = 675 -+INTR_X86_SSE2_PMOVMSKB_128 = 676 -+INTR_X86_SSE2_PMULH_W = 677 -+INTR_X86_SSE2_PMULHU_W = 678 -+INTR_X86_SSE2_PMULU_DQ = 679 -+INTR_X86_SSE2_PSAD_BW = 680 -+INTR_X86_SSE2_PSLL_D = 681 -+INTR_X86_SSE2_PSLL_DQ = 682 -+INTR_X86_SSE2_PSLL_DQ_BS = 683 -+INTR_X86_SSE2_PSLL_Q = 684 -+INTR_X86_SSE2_PSLL_W = 685 -+INTR_X86_SSE2_PSLLI_D = 686 -+INTR_X86_SSE2_PSLLI_Q = 687 -+INTR_X86_SSE2_PSLLI_W = 688 -+INTR_X86_SSE2_PSRA_D = 689 -+INTR_X86_SSE2_PSRA_W = 690 -+INTR_X86_SSE2_PSRAI_D = 691 -+INTR_X86_SSE2_PSRAI_W = 692 -+INTR_X86_SSE2_PSRL_D = 693 -+INTR_X86_SSE2_PSRL_DQ = 694 -+INTR_X86_SSE2_PSRL_DQ_BS = 695 -+INTR_X86_SSE2_PSRL_Q = 696 -+INTR_X86_SSE2_PSRL_W = 697 -+INTR_X86_SSE2_PSRLI_D = 698 -+INTR_X86_SSE2_PSRLI_Q = 699 -+INTR_X86_SSE2_PSRLI_W = 700 -+INTR_X86_SSE2_PSUBS_B = 701 -+INTR_X86_SSE2_PSUBS_W = 702 -+INTR_X86_SSE2_PSUBUS_B = 703 -+INTR_X86_SSE2_PSUBUS_W = 704 -+INTR_X86_SSE2_SQRT_PD = 705 -+INTR_X86_SSE2_SQRT_SD = 706 -+INTR_X86_SSE2_STOREL_DQ = 707 -+INTR_X86_SSE2_STOREU_DQ = 708 -+INTR_X86_SSE2_STOREU_PD = 709 -+INTR_X86_SSE2_SUB_SD = 710 -+INTR_X86_SSE2_UCOMIEQ_SD = 711 -+INTR_X86_SSE2_UCOMIGE_SD = 712 -+INTR_X86_SSE2_UCOMIGT_SD = 713 -+INTR_X86_SSE2_UCOMILE_SD = 714 -+INTR_X86_SSE2_UCOMILT_SD = 715 -+INTR_X86_SSE2_UCOMINEQ_SD = 716 -+INTR_X86_SSE3_ADDSUB_PD = 717 -+INTR_X86_SSE3_ADDSUB_PS = 718 -+INTR_X86_SSE3_HADD_PD = 719 -+INTR_X86_SSE3_HADD_PS = 720 -+INTR_X86_SSE3_HSUB_PD = 721 -+INTR_X86_SSE3_HSUB_PS = 722 -+INTR_X86_SSE3_LDU_DQ = 723 -+INTR_X86_SSE3_MONITOR = 724 -+INTR_X86_SSE3_MWAIT = 725 -+INTR_X86_SSE41_BLENDPD = 726 -+INTR_X86_SSE41_BLENDPS = 727 -+INTR_X86_SSE41_BLENDVPD = 728 -+INTR_X86_SSE41_BLENDVPS = 729 -+INTR_X86_SSE41_DPPD = 730 -+INTR_X86_SSE41_DPPS = 731 -+INTR_X86_SSE41_EXTRACTPS = 732 -+INTR_X86_SSE41_INSERTPS = 733 -+INTR_X86_SSE41_MOVNTDQA = 734 -+INTR_X86_SSE41_MPSADBW = 735 -+INTR_X86_SSE41_PACKUSDW = 736 -+INTR_X86_SSE41_PBLENDVB = 737 -+INTR_X86_SSE41_PBLENDW = 738 -+INTR_X86_SSE41_PCMPEQQ = 739 -+INTR_X86_SSE41_PEXTRB = 740 -+INTR_X86_SSE41_PEXTRD = 741 -+INTR_X86_SSE41_PEXTRQ = 742 -+INTR_X86_SSE41_PHMINPOSUW = 743 -+INTR_X86_SSE41_PMAXSB = 744 -+INTR_X86_SSE41_PMAXSD = 745 -+INTR_X86_SSE41_PMAXUD = 746 -+INTR_X86_SSE41_PMAXUW = 747 -+INTR_X86_SSE41_PMINSB = 748 -+INTR_X86_SSE41_PMINSD = 749 -+INTR_X86_SSE41_PMINUD = 750 -+INTR_X86_SSE41_PMINUW = 751 -+INTR_X86_SSE41_PMOVSXBD = 752 -+INTR_X86_SSE41_PMOVSXBQ = 753 -+INTR_X86_SSE41_PMOVSXBW = 754 -+INTR_X86_SSE41_PMOVSXDQ = 755 -+INTR_X86_SSE41_PMOVSXWD = 756 -+INTR_X86_SSE41_PMOVSXWQ = 757 -+INTR_X86_SSE41_PMOVZXBD = 758 -+INTR_X86_SSE41_PMOVZXBQ = 759 -+INTR_X86_SSE41_PMOVZXBW = 760 -+INTR_X86_SSE41_PMOVZXDQ = 761 -+INTR_X86_SSE41_PMOVZXWD = 762 -+INTR_X86_SSE41_PMOVZXWQ = 763 -+INTR_X86_SSE41_PMULDQ = 764 -+INTR_X86_SSE41_PTESTC = 765 -+INTR_X86_SSE41_PTESTNZC = 766 -+INTR_X86_SSE41_PTESTZ = 767 -+INTR_X86_SSE41_ROUND_PD = 768 -+INTR_X86_SSE41_ROUND_PS = 769 -+INTR_X86_SSE41_ROUND_SD = 770 -+INTR_X86_SSE41_ROUND_SS = 771 -+INTR_X86_SSE42_CRC32_16 = 772 -+INTR_X86_SSE42_CRC32_32 = 773 -+INTR_X86_SSE42_CRC32_8 = 774 -+INTR_X86_SSE42_CRC64_64 = 775 -+INTR_X86_SSE42_CRC64_8 = 776 -+INTR_X86_SSE42_PCMPESTRI128 = 777 -+INTR_X86_SSE42_PCMPESTRIA128 = 778 -+INTR_X86_SSE42_PCMPESTRIC128 = 779 -+INTR_X86_SSE42_PCMPESTRIO128 = 780 -+INTR_X86_SSE42_PCMPESTRIS128 = 781 -+INTR_X86_SSE42_PCMPESTRIZ128 = 782 -+INTR_X86_SSE42_PCMPESTRM128 = 783 -+INTR_X86_SSE42_PCMPGTQ = 784 -+INTR_X86_SSE42_PCMPISTRI128 = 785 -+INTR_X86_SSE42_PCMPISTRIA128 = 786 -+INTR_X86_SSE42_PCMPISTRIC128 = 787 -+INTR_X86_SSE42_PCMPISTRIO128 = 788 -+INTR_X86_SSE42_PCMPISTRIS128 = 789 -+INTR_X86_SSE42_PCMPISTRIZ128 = 790 -+INTR_X86_SSE42_PCMPISTRM128 = 791 -+INTR_X86_SSE_ADD_SS = 792 -+INTR_X86_SSE_CMP_PS = 793 -+INTR_X86_SSE_CMP_SS = 794 -+INTR_X86_SSE_COMIEQ_SS = 795 -+INTR_X86_SSE_COMIGE_SS = 796 -+INTR_X86_SSE_COMIGT_SS = 797 -+INTR_X86_SSE_COMILE_SS = 798 -+INTR_X86_SSE_COMILT_SS = 799 -+INTR_X86_SSE_COMINEQ_SS = 800 -+INTR_X86_SSE_CVTPD2PI = 801 -+INTR_X86_SSE_CVTPI2PD = 802 -+INTR_X86_SSE_CVTPI2PS = 803 -+INTR_X86_SSE_CVTPS2PI = 804 -+INTR_X86_SSE_CVTSI2SS = 805 -+INTR_X86_SSE_CVTSI642SS = 806 -+INTR_X86_SSE_CVTSS2SI = 807 -+INTR_X86_SSE_CVTSS2SI64 = 808 -+INTR_X86_SSE_CVTTPD2PI = 809 -+INTR_X86_SSE_CVTTPS2PI = 810 -+INTR_X86_SSE_CVTTSS2SI = 811 -+INTR_X86_SSE_CVTTSS2SI64 = 812 -+INTR_X86_SSE_DIV_SS = 813 -+INTR_X86_SSE_LDMXCSR = 814 -+INTR_X86_SSE_LOADU_PS = 815 -+INTR_X86_SSE_MAX_PS = 816 -+INTR_X86_SSE_MAX_SS = 817 -+INTR_X86_SSE_MIN_PS = 818 -+INTR_X86_SSE_MIN_SS = 819 -+INTR_X86_SSE_MOVMSK_PS = 820 -+INTR_X86_SSE_MOVNT_PS = 821 -+INTR_X86_SSE_MUL_SS = 822 -+INTR_X86_SSE_PSHUF_W = 823 -+INTR_X86_SSE_RCP_PS = 824 -+INTR_X86_SSE_RCP_SS = 825 -+INTR_X86_SSE_RSQRT_PS = 826 -+INTR_X86_SSE_RSQRT_SS = 827 -+INTR_X86_SSE_SFENCE = 828 -+INTR_X86_SSE_SQRT_PS = 829 -+INTR_X86_SSE_SQRT_SS = 830 -+INTR_X86_SSE_STMXCSR = 831 -+INTR_X86_SSE_STOREU_PS = 832 -+INTR_X86_SSE_SUB_SS = 833 -+INTR_X86_SSE_UCOMIEQ_SS = 834 -+INTR_X86_SSE_UCOMIGE_SS = 835 -+INTR_X86_SSE_UCOMIGT_SS = 836 -+INTR_X86_SSE_UCOMILE_SS = 837 -+INTR_X86_SSE_UCOMILT_SS = 838 -+INTR_X86_SSE_UCOMINEQ_SS = 839 -+INTR_X86_SSSE3_PABS_B = 840 -+INTR_X86_SSSE3_PABS_B_128 = 841 -+INTR_X86_SSSE3_PABS_D = 842 -+INTR_X86_SSSE3_PABS_D_128 = 843 -+INTR_X86_SSSE3_PABS_W = 844 -+INTR_X86_SSSE3_PABS_W_128 = 845 -+INTR_X86_SSSE3_PHADD_D = 846 -+INTR_X86_SSSE3_PHADD_D_128 = 847 -+INTR_X86_SSSE3_PHADD_SW = 848 -+INTR_X86_SSSE3_PHADD_SW_128 = 849 -+INTR_X86_SSSE3_PHADD_W = 850 -+INTR_X86_SSSE3_PHADD_W_128 = 851 -+INTR_X86_SSSE3_PHSUB_D = 852 -+INTR_X86_SSSE3_PHSUB_D_128 = 853 -+INTR_X86_SSSE3_PHSUB_SW = 854 -+INTR_X86_SSSE3_PHSUB_SW_128 = 855 -+INTR_X86_SSSE3_PHSUB_W = 856 -+INTR_X86_SSSE3_PHSUB_W_128 = 857 -+INTR_X86_SSSE3_PMADD_UB_SW = 858 -+INTR_X86_SSSE3_PMADD_UB_SW_128 = 859 -+INTR_X86_SSSE3_PMUL_HR_SW = 860 -+INTR_X86_SSSE3_PMUL_HR_SW_128 = 861 -+INTR_X86_SSSE3_PSHUF_B = 862 -+INTR_X86_SSSE3_PSHUF_B_128 = 863 -+INTR_X86_SSSE3_PSIGN_B = 864 -+INTR_X86_SSSE3_PSIGN_B_128 = 865 -+INTR_X86_SSSE3_PSIGN_D = 866 -+INTR_X86_SSSE3_PSIGN_D_128 = 867 -+INTR_X86_SSSE3_PSIGN_W = 868 -+INTR_X86_SSSE3_PSIGN_W_128 = 869 -+INTR_XCORE_BITREV = 870 -+INTR_XCORE_CHKCT = 871 -+INTR_XCORE_CLRE = 872 -+INTR_XCORE_EEU = 873 -+INTR_XCORE_FREER = 874 -+INTR_XCORE_GETID = 875 -+INTR_XCORE_GETR = 876 -+INTR_XCORE_GETTS = 877 -+INTR_XCORE_IN = 878 -+INTR_XCORE_INCT = 879 -+INTR_XCORE_INSHR = 880 -+INTR_XCORE_INT = 881 -+INTR_XCORE_OUT = 882 -+INTR_XCORE_OUTCT = 883 -+INTR_XCORE_OUTSHR = 884 -+INTR_XCORE_OUTT = 885 -+INTR_XCORE_SETC = 886 -+INTR_XCORE_SETD = 887 -+INTR_XCORE_SETPT = 888 -+INTR_XCORE_SETTW = 889 -+INTR_XCORE_SETV = 890 -+INTR_XCORE_SYNCR = 891 -+INTR_XCORE_WAITEVENT = 892 -Index: _core.c -=================================================================== ---- _core.c (revision 105) -+++ _core.c (working copy) -@@ -807,7 +807,7 @@ - _wrap_pass( EdgeProfiler ) - _wrap_pass( FunctionAttrs ) - _wrap_pass( FunctionInlining ) --_wrap_pass( GEPSplitter ) -+//_wrap_pass( GEPSplitter ) - _wrap_pass( GlobalDCE ) - _wrap_pass( GlobalOptimizer ) - _wrap_pass( GlobalsModRef ) -@@ -822,11 +822,11 @@ - _wrap_pass( LazyValueInfo ) - _wrap_pass( LCSSA ) - _wrap_pass( LICM ) --_wrap_pass( LiveValues ) -+//_wrap_pass( LiveValues ) - _wrap_pass( LoopDeletion ) - _wrap_pass( LoopDependenceAnalysis ) - _wrap_pass( LoopExtractor ) --_wrap_pass( LoopIndexSplit ) -+//_wrap_pass( LoopIndexSplit ) - _wrap_pass( LoopRotate ) - _wrap_pass( LoopSimplify ) - _wrap_pass( LoopStrengthReduce ) -@@ -841,7 +841,7 @@ - _wrap_pass( NoProfileInfo ) - _wrap_pass( OptimalEdgeProfiler ) - _wrap_pass( PartialInlining ) --_wrap_pass( PartialSpecialization ) -+//_wrap_pass( PartialSpecialization ) - _wrap_pass( PostDomOnlyPrinter ) - _wrap_pass( PostDomOnlyViewer ) - _wrap_pass( PostDomPrinter ) -@@ -855,7 +855,7 @@ - _wrap_pass( ScalarEvolutionAliasAnalysis ) - _wrap_pass( ScalarReplAggregates ) - _wrap_pass( SCCP ) --_wrap_pass( SimplifyHalfPowrLibCalls ) -+//_wrap_pass( SimplifyHalfPowrLibCalls ) - _wrap_pass( SimplifyLibCalls ) - _wrap_pass( SingleLoopExtractor ) - _wrap_pass( StripDeadPrototypes ) -@@ -1162,7 +1162,7 @@ - Py_RETURN_NONE; - } - --_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) -+//_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - - /* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -@@ -1569,7 +1569,7 @@ - _pass( EdgeProfiler ) - _pass( FunctionAttrs ) - _pass( FunctionInlining ) -- _pass( GEPSplitter ) -+ //_pass( GEPSplitter ) - _pass( GlobalDCE ) - _pass( GlobalOptimizer ) - _pass( GlobalsModRef ) -@@ -1584,11 +1584,11 @@ - _pass( LazyValueInfo ) - _pass( LCSSA ) - _pass( LICM ) -- _pass( LiveValues ) -+ //_pass( LiveValues ) - _pass( LoopDeletion ) - _pass( LoopDependenceAnalysis ) - _pass( LoopExtractor ) -- _pass( LoopIndexSplit ) -+ //_pass( LoopIndexSplit ) - _pass( LoopRotate ) - _pass( LoopSimplify ) - _pass( LoopStrengthReduce ) -@@ -1603,7 +1603,7 @@ - _pass( NoProfileInfo ) - _pass( OptimalEdgeProfiler ) - _pass( PartialInlining ) -- _pass( PartialSpecialization ) -+ //_pass( PartialSpecialization ) - _pass( PostDomOnlyPrinter ) - _pass( PostDomOnlyViewer ) - _pass( PostDomPrinter ) -@@ -1617,7 +1617,7 @@ - _pass( ScalarEvolutionAliasAnalysis ) - _pass( ScalarReplAggregates ) - _pass( SCCP ) -- _pass( SimplifyHalfPowrLibCalls ) -+ //_pass( SimplifyHalfPowrLibCalls ) - _pass( SimplifyLibCalls ) - _pass( SingleLoopExtractor ) - _pass( StripDeadPrototypes ) -@@ -1672,7 +1672,7 @@ - /* Misc */ - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) -- _method( LLVMInlineFunction ) -+ //_method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - - { NULL } -Index: extra.h -=================================================================== ---- extra.h (revision 105) -+++ extra.h (working copy) -@@ -181,7 +181,7 @@ - /* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). */ --int LLVMInlineFunction(LLVMValueRef call); -+//int LLVMInlineFunction(LLVMValueRef call); - - /* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -@@ -209,13 +209,13 @@ - declare_pass( DomPrinter ) - declare_pass( DomViewer ) - declare_pass( EdgeProfiler ) --declare_pass( GEPSplitter ) -+//declare_pass( GEPSplitter ) - declare_pass( GlobalsModRef ) - declare_pass( InstCount ) - declare_pass( InstructionNamer ) - declare_pass( LazyValueInfo ) - declare_pass( LCSSA ) --declare_pass( LiveValues ) -+//declare_pass( LiveValues ) - declare_pass( LoopDependenceAnalysis ) - declare_pass( LoopExtractor ) - declare_pass( LoopSimplify ) -@@ -227,7 +227,7 @@ - declare_pass( NoProfileInfo ) - declare_pass( OptimalEdgeProfiler ) - declare_pass( PartialInlining ) --declare_pass( PartialSpecialization ) -+//declare_pass( PartialSpecialization ) - declare_pass( PostDomOnlyPrinter ) - declare_pass( PostDomOnlyViewer ) - declare_pass( PostDomPrinter ) diff --git a/llvm/__init__.py b/llvm/__init__.py index d7461ce..9b24112 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,140 +1,47 @@ -""" -Common classes related to LLVM. -""" - -__version__ = '0.8.3' +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions -from weakref import WeakValueDictionary +from llvmpy import extra + +version = extra.get_llvm_version() +del extra + +class Wrapper(object): + __slots__ = '__ptr' + + def __init__(self, ptr): + assert ptr + self.__ptr = ptr + + @property + def _ptr(self): + try: + return self.__ptr + except AttributeError: + raise AttributeError("_ptr resource has been removed") + + @_ptr.deleter + def _ptr(self): + del self.__ptr -#===----------------------------------------------------------------------=== -# Exceptions -#===----------------------------------------------------------------------=== +def _extract_ptrs(objs): + return [(x._ptr if x is not None else None) + for x in objs] class LLVMException(Exception): - """Generic LLVM exception.""" - - def __init__(self, msg=""): - Exception.__init__(self, msg) - - -#===----------------------------------------------------------------------=== -# Ownables -#===----------------------------------------------------------------------=== - -class Ownable(object): - """Objects that can be owned. - - Modules and Module Providers can be owned, i.e., the responsibility of - destruction of ownable objects can be handed over to other objects. The - llvm.Ownable class represents objects that can be so owned. This class - is NOT intended for public use. - """ - - def __init__(self, ptr, del_fn): - self.ptr = ptr - self.owner = None - self.del_fn = del_fn - - def _own(self, owner): - if self.owner: - raise LLVMException("object already owned") - self.owner = owner - - def _disown(self): - if not self.owner: - raise LLVMException("not owned") - self.owner = None - - def __del__(self): - if not self.owner: - self.del_fn(self.ptr) - - -#===----------------------------------------------------------------------=== -# Dummy owner, will not delete ownee. Be careful. -#===----------------------------------------------------------------------=== - -class DummyOwner(object): pass - -#===----------------------------------------------------------------------=== -# A metaclass to prevent aliasing. It stores a (weak) reference to objects -# constructed based on a PyCObject. If an object is constructed based on a -# PyCObject with the same underlying pointer as a previous object, a reference -# to the previous object is returned rather than a new one. -#===----------------------------------------------------------------------=== - -class _ObjectCache(type): - """A metaclass to prevent aliasing. - - Classes using 'ObjectCache' as a metaclass must have constructors - that take a PyCObject as their first argument. When the class is - called (to create a new instance of the class), the value of the - pointer wrapped by the PyCObj is checked: - - If no previous object has been created based on the same - underlying pointer (note that different PyCObject objects can - wrap the same pointer), the object will be initialized as - usual and returned. - - If a previous has been created based on the same pointer, - then a reference to that object will be returned, and no - object initialization is performed. - """ - - __instances = WeakValueDictionary() - - def __call__(cls, ptr, *args, **kwargs): - objid = _core.PyCObjectVoidPtrToPyLong(ptr) - key = "%s:%d" % (cls.__name__, objid) - obj = _ObjectCache.__instances.get(key) - if obj is None: - obj = super(_ObjectCache, cls).__call__(ptr, *args, **kwargs) - _ObjectCache.__instances[key] = obj - return obj - - @staticmethod - def forget(obj): - objid = _core.PyCObjectVoidPtrToPyLong(obj.ptr) - key = "%s:%d" % (type(obj).__name__, objid) - if key in _ObjectCache.__instances: - del _ObjectCache.__instances[key] - - -#===----------------------------------------------------------------------=== -# Cacheables -#===----------------------------------------------------------------------=== - -# version 2/3 compatibility help -# version 2 metaclass -# class Cacheable(object): -# __metaclass__ = _ObjectCache # Doing nothing for version 3 -# -# version 3 metaclass -# class Cacheable(metaclass=_ObjectCache): -# -# Reference: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/#using-the-metaclass-in-python-3-x -ObjectCache = _ObjectCache('ObjectCache', (object, ), {}) - -class Cacheable(ObjectCache): - """Objects that can be cached. - - Objects that wrap a PyCObject are cached to avoid "aliasing", i.e., - two Python objects each containing a PyCObject which internally points - to the same C pointer.""" - - def forget(self): - ObjectCache.forget(self) - - -def test(verbosity=1): +def test(verbosity=3, run_isolated=True): """test(verbosity=1) -> TextTestResult - Run self-test, and return unittest.runner.TextTestResult object. - """ - from llvm.test_llvmpy import run + Run self-test, and return the number of failures + errors + """ + from llvm.tests import run - return run(verbosity=verbosity) + result = run(verbosity=verbosity, run_isolated=run_isolated) + errct = len(result.failures) + len(result.errors) + + return errct diff --git a/llvm/_core.cpp b/llvm/_core.cpp deleted file mode 100644 index b8899ef..0000000 --- a/llvm/_core.cpp +++ /dev/null @@ -1,2180 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* our includes */ -#include "wrap.h" -#include "extra.h" - - - -// Python include -#include "Python.h" - -/* LLVM includes */ -#include "llvm-c/Analysis.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/IPO.h" - -#include "llvm/Support/CommandLine.h" -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #include "llvm-c/Linker.h" -#else - typedef unsigned int LLVMLinkerMode; -#endif - -/* Compatibility with Python 2.4: Py_ssize_t is not available. */ -#ifndef PY_SSIZE_T_MAX -typedef int Py_ssize_t; -#endif - - -// explicit specializations -template <> PyObject* pycap_new(int i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned long i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMTypeKind i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMLinkage i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMVisibility i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMByteOrdering i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned long long ull) -{ - return PyLong_FromUnsignedLongLong(ull); -} - -template <> PyObject* pycap_new(long long ll) -{ - return PyLong_FromLongLong(ll); -} - -/*===----------------------------------------------------------------------===*/ -/* Modules */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMModuleCreateWithName(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - - if (!PyArg_ParseTuple(args, "s:LLVMModuleCreateWithName", &s)) { - return NULL; - } - - const LLVMModuleRef module = LLVMModuleCreateWithName(s); - return pycap_new(module); - LLVMPY_CATCH_ALL -} - -_wrap_obj2str(LLVMGetDataLayout, LLVMModuleRef) -_wrap_objstr2none(LLVMSetDataLayout, LLVMModuleRef) -_wrap_obj2str(LLVMGetModuleIdentifier, LLVMModuleRef) -_wrap_objstr2none(LLVMSetModuleIdentifier, LLVMModuleRef) -_wrap_obj2str(LLVMGetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMSetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMModuleAddLibrary, LLVMModuleRef) -_wrap_objstr2obj(LLVMGetTypeByName, LLVMModuleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDumpModule, LLVMModuleRef) -_wrap_obj2none(LLVMDisposeModule, LLVMModuleRef) -_wrap_dumper(LLVMDumpModuleToString, LLVMModuleRef) - _wrap_obj2obj( LLVMModuleGetPointerSize, LLVMModuleRef, int) -_wrap_objstrobj2obj(LLVMModuleGetOrInsertFunction, LLVMModuleRef, - LLVMTypeRef, LLVMValueRef) - -static PyObject * -_wLLVMVerifyModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m) return NULL; - - char *outmsg = 0; - (void) LLVMVerifyModule(m, LLVMReturnStatusAction, &outmsg); - - PyObject *ret; - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString(""); - } - - return ret; - LLVMPY_CATCH_ALL -} - -///// unused -// typedef LLVMModuleRef (*asm_or_bc_fn_t)(const char *A, unsigned Len, char **OutMessage); - - -static PyObject* -_wLLVMGetModuleFromAssembly(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * str; - if ( !PyArg_ParseTuple(args, "s", &str) ){ - return NULL; - } - - char * outmsg = 0; - const LLVMModuleRef mod = LLVMGetModuleFromAssembly(str, &outmsg); - - if ( !mod ){ - if ( outmsg ){ - PyObject * ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(mod); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj ; - - if (!PyArg_ParseTuple(args, "S", &obj)) - return NULL; - - const char *start = PyBytes_AsString(obj); - const Py_ssize_t len = PyBytes_Size(obj); - - char *outmsg = 0; - LLVMModuleRef m = LLVMGetModuleFromBitcode(start, len, &outmsg); - - PyObject *ret; - if (!m) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(m); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m ) return NULL; - - size_t len; - unsigned const char *ubytes = LLVMGetBitcodeFromModule(m, &len) ; - if ( !ubytes ) Py_RETURN_NONE; - - const char *chars = reinterpret_cast(ubytes) ; - PyObject *ret = PyBytes_FromStringAndSize(chars, len); - LLVMDisposeMessage(const_cast(chars)); - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetNativeCodeFromModule(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject * arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "Oi", &arg_m, &arg_use_asm)) - return NULL; - - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - - LLVMDisposeMessage(const_cast(chars)); - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMLinkModules(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - size_t mode = 0; - - PyObject *dest_obj, *src_obj ; - if (!PyArg_ParseTuple(args, "OO|I", &dest_obj, &src_obj, &mode)) - return NULL; - - const LLVMModuleRef dest = pycap_get(dest_obj ) ; - const LLVMModuleRef src = pycap_get(src_obj) ; - - PyObject *ret; - char *errmsg; - if (!LLVMLinkModules(dest, src, (LLVMLinkerMode)mode, &errmsg)) { - if (errmsg) { - ret = PyUnicode_FromString(errmsg); - LLVMDisposeMessage(errmsg); - } else { - ret = PyUnicode_FromString("Link error"); - } - return ret; - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -/*===----------------------------------------------------------------------===*/ -/* Types */ -/*===----------------------------------------------------------------------===*/ - -/*===-- General ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetTypeKind, LLVMTypeRef, int) -_wrap_dumper(LLVMDumpTypeToString, LLVMTypeRef) - -/*===-- Integer types ----------------------------------------------------===*/ - -_wrap_none2obj(LLVMInt1Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt8Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt16Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt32Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt64Type, LLVMTypeRef) -_wrap_int2obj(LLVMIntType, LLVMTypeRef) -_wrap_obj2obj(LLVMGetIntTypeWidth, LLVMTypeRef, int) - -/*===-- Floating-point types ---------------------------------------------===*/ - -_wrap_none2obj(LLVMFloatType, LLVMTypeRef) -_wrap_none2obj(LLVMDoubleType, LLVMTypeRef) -_wrap_none2obj(LLVMX86FP80Type, LLVMTypeRef) -_wrap_none2obj(LLVMFP128Type, LLVMTypeRef) -_wrap_none2obj(LLVMPPCFP128Type, LLVMTypeRef) - -/*===-- Function types ---------------------------------------------------===*/ - -_wrap_objlistint2obj(LLVMFunctionType, LLVMTypeRef, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMIsFunctionVarArg, LLVMTypeRef, int) -_wrap_obj2obj(LLVMGetReturnType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountParamTypes, LLVMTypeRef, int) - -/* The LLVMGetParamTypes and LLVMGetStructElementTypes functions both - * have the same signatures. The following implementation takes advantage - * of this. - */ - -typedef void (*obj2arr_fn_t)(LLVMTypeRef ty, LLVMTypeRef *outv); -typedef unsigned (*arrcnt_fn_t)(LLVMTypeRef ty); - -static PyObject * -obj2arr(PyObject *self, PyObject *args, arrcnt_fn_t cntfunc, obj2arr_fn_t arrfunc) -{ - size_t param_count; - - /* get the function object ptr */ - const LLVMTypeRef type = get_object_arg(args) ; - - /* get param count */ - param_count = cntfunc(type); - - /* alloc enough space for all of them */ - LLVMTypeRef* param_types = new LLVMTypeRef[param_count] ; - - /* call LLVM func */ - arrfunc(type, param_types); - - /* create a list from the array */ - PyObject *list = make_list(param_types, param_count); - - /* free temp storage */ - delete [] param_types ; - - return list; -} - -static PyObject * -_wLLVMGetFunctionTypeParams(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountParamTypes, LLVMGetParamTypes); - LLVMPY_CATCH_ALL -} - -/*===-- Struct types -----------------------------------------------------===*/ - -_wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef) -_wrap_str2obj(LLVMStructTypeIdentified, LLVMTypeRef) -_wrap_objlistint2none(LLVMSetStructBody, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int) -_wrap_obj2str(LLVMGetStructName, LLVMTypeRef) -_wrap_objstr2none(LLVMSetStructName, LLVMTypeRef) - - -static PyObject * -_wLLVMGetStructElementTypes(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountStructElementTypes, - LLVMGetStructElementTypes); - LLVMPY_CATCH_ALL -} - - -_wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsOpaqueStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsLiteralStruct, LLVMTypeRef, int) - -/*===-- Array types ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMArrayType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetElementType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetArrayLength, LLVMTypeRef, int) - -/*===-- Pointer types ----------------------------------------------------===*/ - -_wrap_objint2obj(LLVMPointerType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetPointerAddressSpace, LLVMTypeRef, int) - -/*===-- Vector type ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMVectorType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetVectorSize, LLVMTypeRef, int) - -/*===-- Other types ------------------------------------------------------===*/ - -_wrap_none2obj(LLVMVoidType, LLVMTypeRef) -_wrap_none2obj(LLVMLabelType, LLVMTypeRef) - -/*===-- Type handles -----------------------------------------------------===*/ - -/* -_wrap_obj2obj(LLVMCreateTypeHandle, LLVMTypeRef, LLVMTypeHandleRef) -_wrap_obj2obj(LLVMResolveTypeHandle, LLVMTypeHandleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDisposeTypeHandle, LLVMTypeHandleRef) -*/ - - -/*===----------------------------------------------------------------------===*/ -/* Values */ -/*===----------------------------------------------------------------------===*/ - -/* Operations on all values */ - -_wrap_obj2obj(LLVMTypeOf, LLVMValueRef, LLVMTypeRef) -_wrap_obj2str(LLVMGetValueName, LLVMValueRef) -_wrap_objstr2none(LLVMSetValueName, LLVMValueRef) -_wrap_obj2none(LLVMDumpValue, LLVMValueRef) -_wrap_dumper(LLVMDumpValueToString, LLVMValueRef) -_wrap_obj2obj(LLVMValueGetID, LLVMValueRef, int) -_wrap_obj2obj(LLVMValueGetNumUses, LLVMValueRef, int) - -static PyObject * -_wLLVMValueGetUses(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef value = get_object_arg(args) ; - - LLVMValueRef *uses = 0; - size_t n = LLVMValueGetUses(value, &uses); - - PyObject *list = make_list(uses, n); - if (n > 0) - LLVMDisposeValueRefArray(uses); - - return list; - LLVMPY_CATCH_ALL -} - -/*===-- Users ------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMUserGetNumOperands, LLVMValueRef, int) -_wrap_objint2obj(LLVMUserGetOperand, LLVMValueRef, LLVMValueRef) - -/*===-- Constant Values --------------------------------------------------===*/ - -/* Operations on constants of any type */ - -_wrap_obj2obj(LLVMConstNull, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstAllOnes, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetUndef, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMIsConstant, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsNull, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsUndef, LLVMValueRef, int) - -/* Operations on scalar constants */ - -static PyObject * -_wLLVMConstInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - unsigned long long n; - int sign_extend; - - if (!PyArg_ParseTuple(args, "OKi", &obj, &n, &sign_extend)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstInt(ty, n, sign_extend); - - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMConstReal(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - double d; - - if (!PyArg_ParseTuple(args, "Od", &obj, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstReal(ty, d); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objstr2obj(LLVMConstRealOfString, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstIntGetZExtValue, LLVMValueRef, llvmwrap_ull) -_wrap_obj2obj(LLVMConstIntGetSExtValue, LLVMValueRef, llvmwrap_ll) - -/* Operations on composite constants */ - -static PyObject * -_wLLVMConstString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - int dont_null_terminate; - - if (!PyArg_ParseTuple(args, "si:LLVMConstString", &s, &dont_null_terminate)) { - return NULL; - } - - LLVMValueRef val = LLVMConstString(s, strlen(s), dont_null_terminate); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objlist2obj(LLVMConstArray, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_listint2obj(LLVMConstStruct, LLVMValueRef, LLVMValueRef) -_wrap_list2obj(LLVMConstVector, LLVMValueRef, LLVMValueRef) - -/* Constant expressions */ - -_wrap_obj2obj(LLVMGetConstExprOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMGetConstExprOpcodeName, LLVMValueRef) -_wrap_obj2obj(LLVMSizeOf, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNeg, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNot, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstURem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAnd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstOr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstXor, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_enumobjobj2obj(LLVMConstICmp, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_enumobjobj2obj(LLVMConstFCmp, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstShl, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstLShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMConstGEP, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstZExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToUI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToSI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstPtrToInt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstIntToPtr, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstBitCast, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstSelect, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstExtractElement, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstInsertElement, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstShuffleVector, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Globals */ -/*===----------------------------------------------------------------------===*/ - -/*===-- Globals ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetGlobalParent, LLVMValueRef, LLVMModuleRef) -_wrap_obj2obj(LLVMIsDeclaration, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetLinkage, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetLinkage, LLVMValueRef, LLVMLinkage) -_wrap_obj2str(LLVMGetSection, LLVMValueRef) -_wrap_objstr2none(LLVMSetSection, LLVMValueRef) -_wrap_obj2obj(LLVMGetVisibility, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetVisibility, LLVMValueRef, LLVMVisibility) -_wrap_obj2obj(LLVMGetAlignment, LLVMValueRef, int) -_wrap_objint2none(LLVMSetAlignment, LLVMValueRef) - -/*===-- Global Variables -------------------------------------------------===*/ - -_wrap_objobjstr2obj(LLVMAddGlobal, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextGlobal, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteGlobal, LLVMValueRef) -_wrap_obj2obj(LLVMHasInitializer, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objobj2none(LLVMSetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objint2none(LLVMSetGlobalConstant, LLVMValueRef) -_wrap_obj2obj(LLVMIsGlobalConstant, LLVMValueRef, int) -_wrap_objint2none(LLVMSetThreadLocal, LLVMValueRef) -_wrap_obj2obj(LLVMIsThreadLocal, LLVMValueRef, int) - - -/*===-- Functions --------------------------------------------------------===*/ - -_wrap_objstrobj2obj(LLVMAddFunction, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextFunction, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteFunction, LLVMValueRef) -_wrap_obj2obj(LLVMGetIntrinsicID, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFunctionCallConv, LLVMValueRef, int) -_wrap_objint2none(LLVMSetFunctionCallConv, LLVMValueRef) -_wrap_obj2str(LLVMGetGC, LLVMValueRef) -_wrap_objstr2none(LLVMSetGC, LLVMValueRef) -_wrap_obj2obj(LLVMGetDoesNotThrow, LLVMValueRef, int) -_wrap_objint2none(LLVMSetDoesNotThrow, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFG, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFGOnly, LLVMValueRef) -_wrap_objenum2none(LLVMAddFunctionAttr, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveFunctionAttr, LLVMValueRef, LLVMAttribute) - - -static PyObject * -_wLLVMVerifyFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef fn = get_object_arg(args); - if (!fn) return NULL; - - return pycap_new(LLVMVerifyFunction(fn, LLVMReturnStatusAction)); - LLVMPY_CATCH_ALL -} - - -/*===-- Arguments --------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCountParams, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetParamParent, LLVMValueRef, LLVMValueRef) -_wrap_objenum2none(LLVMAddAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMSetParamAlignment, LLVMValueRef, LLVMAttribute) -_wrap_obj2obj(LLVMGetParamAlignment, LLVMValueRef, int) - -/*===-- Basic Blocks -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetBasicBlockParent, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMCountBasicBlocks, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetNextBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetEntryBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMAppendBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMInsertBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDeleteBasicBlock, LLVMBasicBlockRef) - - -/*===-- MetaData -----------------------------------------------------===*/ - -_wrap_objlist2obj(LLVMMetaDataGet, LLVMModuleRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobj2none(LLVMAddNamedMetadataOperand, LLVMModuleRef, LLVMValueRef) -_wrap_objint2obj(LLVMMetaDataGetOperand, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMMetaDataGetNumOperands, LLVMValueRef, int) -_wrap_objstr2obj(LLVMMetaDataStringGet, LLVMModuleRef, LLVMValueRef) - -static PyObject * -_wLLVMGetNamedMetadataOperands(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_module; - const char *name; - - if (!PyArg_ParseTuple(args, "Os", &obj_module, &name)) - return NULL; - - LLVMModuleRef module = pycap_get(obj_module); - unsigned num_operands = LLVMGetNamedMetadataNumOperands(module, name); - LLVMValueRef *operands = new LLVMValueRef[num_operands]; - LLVMGetNamedMetadataOperands(module, name, operands); - - PyObject *list = make_list(operands, num_operands); - delete [] operands; - - return list; - LLVMPY_CATCH_ALL -} - -/*===-- Instructions -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetInstructionParent, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetFirstInstruction, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextInstruction, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMInstIsTerminator, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsBinaryOp, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCast, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsLogicalShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsArithmeticShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsAssociative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCommutative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int) -_wrap_objint2none(LLVMSetVolatile, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef) - -_wrap_objstrobj2none(LLVMInstSetMetaData, LLVMValueRef, LLVMValueRef) - -/*===-- Call Sites (Call or Invoke) --------------------------------------===*/ - -_wrap_objint2none(LLVMSetInstructionCallConv, LLVMValueRef) -_wrap_obj2obj(LLVMGetInstructionCallConv, LLVMValueRef, int) -_wrap_objintenum2none(LLVMAddInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintenum2none(LLVMRemoveInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintint2none(LLVMSetInstrParamAlignment, LLVMValueRef) -_wrap_obj2obj(LLVMIsTailCall, LLVMValueRef, int) -_wrap_objint2none(LLVMSetTailCall, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetCalledFunction, LLVMValueRef, LLVMValueRef) - -/*===-- PHI Nodes --------------------------------------------------------===*/ - -static void LLVMAddIncoming1(LLVMValueRef PhiNode, LLVMValueRef IncomingValue, LLVMBasicBlockRef IncomingBlock) -{ - LLVMAddIncoming(PhiNode, &IncomingValue, &IncomingBlock, 1); -} - -_wrap_objobjobj2none(LLVMAddIncoming1, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMCountIncoming, LLVMValueRef, int) -_wrap_objint2obj(LLVMGetIncomingValue, LLVMValueRef, LLVMValueRef) -_wrap_objint2obj(LLVMGetIncomingBlock, LLVMValueRef, LLVMBasicBlockRef) - -/*===-- Compare Instructions ---------------------------------------------===*/ - -_wrap_obj2obj(LLVMCmpInstGetPredicate, LLVMValueRef, int) - -/*===-- Instruction builders ----------------------------------------------===*/ - -_wrap_none2obj(LLVMCreateBuilder, LLVMBuilderRef) -_wrap_objobj2none(LLVMPositionBuilderBefore, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2none(LLVMPositionBuilderAtEnd, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetInsertBlock, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDisposeBuilder, LLVMBuilderRef) - -/* Terminators */ - -_wrap_obj2obj(LLVMBuildRetVoid, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildRet, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMBuildRetMultiple, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildBr, LLVMBuilderRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjobj2obj(LLVMBuildCondBr, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjint2obj(LLVMBuildSwitch, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMValueRef) - -static PyObject * -_wLLVMBuildInvoke(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2, *obj3, *obj4, *obj5; - const char *name; - - if (!PyArg_ParseTuple(args, "OOOOOs:LLVMBuildInvoke", &obj1, &obj2, &obj3, &obj4, &obj5, &name)) { - return NULL; - } - - const LLVMBuilderRef builder = pycap_get( obj1); - const LLVMValueRef func = pycap_get( obj2 ) ; - - size_t fnarg_count = PyList_Size(obj3); - LLVMValueRef *fnargs - = make_array_from_list(obj3, fnarg_count); - - const LLVMBasicBlockRef then_blk = pycap_get ( obj4 ) ; - const LLVMBasicBlockRef catch_blk = pycap_get ( obj5 ) ; - - const LLVMValueRef inst - = LLVMBuildInvoke(builder, func, fnargs, fnarg_count, then_blk, - catch_blk, name); - - delete [] fnargs; - - return pycap_new(inst); - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMBuildUnreachable, LLVMBuilderRef, LLVMValueRef) - -/* Add a case to the switch instruction */ - -_wrap_objobjobj2none(LLVMAddCase, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) - -/* Arithmetic */ - -_wrap_objobjobjstr2obj(LLVMBuildAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildURem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildShl, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildLShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAnd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildOr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildXor, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNeg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNot, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) - -/* Memory */ - -_wrap_objobjstr2obj(LLVMBuildMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildFree, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMBuildStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildGEP, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_objint2none(LLVMLdSetAlignment, LLVMValueRef) -_wrap_objint2none(LLVMStSetAlignment, LLVMValueRef) - -/* Casts */ - -_wrap_objobjobjstr2obj(LLVMBuildTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildZExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToUI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToSI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildPtrToInt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildIntToPtr, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildBitCast, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) - -/* Comparisons */ - -_wrap_objenumobjobjstr2obj(LLVMBuildICmp, LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/* Atomics */ -_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef) - -/* Miscellaneous instructions */ - -_wrap_objobjintstr2obj(LLVMBuildGetResult, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstr2obj(LLVMBuildInsertValue, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildPhi, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildCall, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildSelect, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildVAArg, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildExtractElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildInsertElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildShuffleVector, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Memory Buffer */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateMemoryBufferWithContentsOfFile(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *path; - LLVMMemoryBufferRef ref; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMCreateMemoryBufferWithContentsOfFile", &path)) { - return NULL; - } - - char *outmsg; - if (!LLVMCreateMemoryBufferWithContentsOfFile(path, &ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateMemoryBufferWithSTDIN(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *ret; - LLVMMemoryBufferRef ref; - char *outmsg; - if (!LLVMCreateMemoryBufferWithSTDIN(&ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeMemoryBuffer, LLVMMemoryBufferRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderRef) -_wrap_obj2none(LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderRef) - -_wrap_objint2none(LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetOptLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetSizeLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetSizeLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetVectorize, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetVectorize, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnitAtATime, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnitAtATime, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnrollLoops, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnrollLoops, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderUseInlinerWithThreshold, - LLVMPassManagerBuilderRef) - - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateFunctionPassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateModulePassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMCreatePassManager, LLVMPassManagerRef) -_wrap_obj2obj(LLVMCreateFunctionPassManagerForModule, LLVMModuleRef, LLVMPassManagerRef) -_wrap_objobj2obj(LLVMRunPassManager, LLVMPassManagerRef, LLVMModuleRef, int) -_wrap_obj2obj(LLVMInitializeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_objobj2obj(LLVMRunFunctionPassManager, LLVMPassManagerRef, LLVMValueRef, int) -_wrap_obj2obj(LLVMFinalizeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_obj2none(LLVMDisposePassManager, LLVMPassManagerRef) -_wrap_none2str(LLVMDumpPasses) -_wrap_objstr2obj(LLVMAddPassByName, LLVMPassManagerRef, int) - - -_wrap_none2none(LLVMInitializePasses) - -_wrap_none2obj(LLVMInitializeNativeTarget, int) -_wrap_none2obj(LLVMInitializeNativeTargetAsmPrinter, int) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX -_wrap_none2none(LLVMInitializeNVPTXTarget) -_wrap_none2none(LLVMInitializeNVPTXTargetInfo) -_wrap_none2none( LLVMInitializeNVPTXTargetMC ) -_wrap_none2none(LLVMInitializeNVPTXAsmPrinter) -# else -_wrap_none2none(LLVMInitializePTXTarget) -_wrap_none2none(LLVMInitializePTXTargetInfo) -_wrap_none2none( LLVMInitializePTXTargetMC ) -_wrap_none2none(LLVMInitializePTXAsmPrinter) -# endif -#endif - -/*===----------------------------------------------------------------------===*/ -/* Passes */ -/*===----------------------------------------------------------------------===*/ -/* - -#define _wrap_pass(P) \ -_wrap_obj2none( LLVMAdd ## P ## Pass, LLVMPassManagerRef) - -_wrap_pass( AAEval ) -_wrap_pass( AggressiveDCE ) -_wrap_pass( AliasAnalysisCounter ) -_wrap_pass( AlwaysInliner ) -_wrap_pass( ArgumentPromotion ) -_wrap_pass( BasicAliasAnalysis ) -_wrap_pass( BlockPlacement ) -_wrap_pass( BreakCriticalEdges ) -_wrap_pass( CFGSimplification ) -_wrap_pass( CodeGenPrepare ) -_wrap_pass( ConstantMerge ) -_wrap_pass( ConstantPropagation ) -_wrap_pass( DbgInfoPrinter ) -_wrap_pass( DeadArgElimination ) -_wrap_pass( DeadCodeElimination ) -_wrap_pass( DeadInstElimination ) -_wrap_pass( DeadStoreElimination ) -_wrap_pass( DemoteRegisterToMemory ) -_wrap_pass( DomOnlyPrinter ) -_wrap_pass( DomOnlyViewer ) -_wrap_pass( DomPrinter ) -_wrap_pass( DomViewer ) -_wrap_pass( EdgeProfiler ) -_wrap_pass( FunctionAttrs ) -_wrap_pass( FunctionInlining ) -//_wrap_pass( GEPSplitter ) -_wrap_pass( GlobalDCE ) -_wrap_pass( GlobalOptimizer ) -_wrap_pass( GlobalsModRef ) -_wrap_pass( GVN ) -_wrap_pass( IndVarSimplify ) -_wrap_pass( InstCount ) -_wrap_pass( InstructionCombining ) -_wrap_pass( InstructionNamer ) -_wrap_pass( IPConstantPropagation ) -_wrap_pass( IPSCCP ) -_wrap_pass( JumpThreading ) -_wrap_pass( LazyValueInfo ) -_wrap_pass( LCSSA ) -_wrap_pass( LICM ) -//_wrap_pass( LiveValues ) -_wrap_pass( LoopDeletion ) -_wrap_pass( LoopDependenceAnalysis ) -_wrap_pass( LoopExtractor ) -//_wrap_pass( LoopIndexSplit ) -_wrap_pass( LoopRotate ) -_wrap_pass( LoopSimplify ) -_wrap_pass( LoopStrengthReduce ) -_wrap_pass( LoopUnroll ) -_wrap_pass( LoopUnswitch ) -_wrap_pass( LowerInvoke ) -_wrap_pass( LowerSwitch ) -_wrap_pass( MemCpyOpt ) -_wrap_pass( MergeFunctions ) -_wrap_pass( NoAA ) -_wrap_pass( NoProfileInfo ) -_wrap_pass( OptimalEdgeProfiler ) -_wrap_pass( PartialInlining ) -//_wrap_pass( PartialSpecialization ) -_wrap_pass( PostDomOnlyPrinter ) -_wrap_pass( PostDomOnlyViewer ) -_wrap_pass( PostDomPrinter ) -_wrap_pass( PostDomViewer ) -_wrap_pass( ProfileEstimator ) -_wrap_pass( ProfileLoader ) -_wrap_pass( ProfileVerifier ) -_wrap_pass( PromoteMemoryToRegister ) -_wrap_pass( PruneEH ) -_wrap_pass( Reassociate ) -_wrap_pass( ScalarEvolutionAliasAnalysis ) -_wrap_pass( ScalarReplAggregates ) -_wrap_pass( SCCP ) -//_wrap_pass( SimplifyHalfPowrLibCalls ) -_wrap_pass( SimplifyLibCalls ) -_wrap_pass( SingleLoopExtractor ) -_wrap_pass( StripDeadPrototypes ) -_wrap_pass( StripNonDebugSymbols ) -_wrap_pass( StripSymbols ) -//_wrap_pass( StructRetPromotion ) -_wrap_pass( TailCallElimination ) -//_wrap_pass( TailDuplication ) -_wrap_pass( UnifyFunctionExitNodes ) - -_wrap_pass( Internalize2 ) -*/ - - -/*===----------------------------------------------------------------------===*/ -/* Target Machine */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2str(LLVMGetHostCPUName); - -_wrap_obj2obj(LLVMTargetMachineFromEngineBuilder, LLVMEngineBuilderRef, - LLVMTargetMachineRef) -_wrap_obj2none(LLVMDisposeTargetMachine, LLVMTargetMachineRef) - -static PyObject * -_wLLVMTargetMachineLookup(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - const char *arch; - const char *cpu; - const char *features; - int opt; - - if (!PyArg_ParseTuple(args, "sssi", &arch, &cpu, &features, &opt)) - return NULL; - - std::string error; - LLVMTargetMachineRef tm = LLVMTargetMachineLookup(arch, cpu, features, opt, - error); - if(!error.empty()){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - return pycap_new(tm); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject *arg_tm, *arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "OOi", &arg_tm, &arg_m, &arg_use_asm)) - return NULL; - - const LLVMTargetMachineRef tm - = pycap_get( arg_tm ) ; - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - delete [] ubytes; - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMTargetMachineGetTargetData, LLVMTargetMachineRef, - LLVMTargetDataRef) -_wrap_obj2str(LLVMTargetMachineGetTargetName, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTargetShortDescription, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTriple, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetCPU, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetFS, LLVMTargetMachineRef) -_wrap_none2none(LLVMPrintRegisteredTargetsForVersion) - - -/*===----------------------------------------------------------------------===*/ -/* Target Data */ -/*===----------------------------------------------------------------------===*/ - -_wrap_str2obj(LLVMCreateTargetData, LLVMTargetDataRef) -_wrap_obj2none(LLVMDisposeTargetData, LLVMTargetDataRef) - -static PyObject * -_wLLVMTargetDataAsString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMTargetDataRef td = get_object_arg(args); - - char *tdrep = LLVMCopyStringRepOfTargetData(td); - PyObject *ret = PyUnicode_FromString(tdrep); - LLVMDisposeMessage(tdrep); - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_objobj2none(LLVMAddTargetData, LLVMTargetDataRef, LLVMPassManagerRef) -_wrap_obj2obj(LLVMByteOrder, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMPointerSize, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMIntPtrType, LLVMTargetDataRef, LLVMTypeRef) -_wrap_objobj2obj(LLVMSizeOfTypeInBits, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMStoreSizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABISizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABIAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMCallFrameAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfGlobal, LLVMTargetDataRef, - LLVMValueRef, int) -_wrap_objobjull2obj(LLVMElementAtOffset, LLVMTargetDataRef, LLVMTypeRef, int) -_wrap_objobjint2obj(LLVMOffsetOfElement, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) - - -/*===----------------------------------------------------------------------===*/ -/* Engine Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCreateEngineBuilder, LLVMModuleRef, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMDisposeEngineBuilder, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceJIT, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceInterpreter, LLVMEngineBuilderRef) -_wrap_objint2none(LLVMEngineBuilderSetOptLevel, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMCPU, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMAttrs, LLVMEngineBuilderRef) - -static PyObject * -_wLLVMEngineBuilderCreate(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMEngineBuilderRef obj - = get_object_arg(args) ; - - std::string outmsg; - const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreate(obj, outmsg); - - PyObject * ret; - if( !ee ){ // check if error message is set. - ret = PyUnicode_FromString(outmsg.c_str()); - }else{ - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -/*===----------------------------------------------------------------------===*/ -/* Execution Engine */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateExecutionEngine(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - int force_interpreter; - char *outmsg = 0; - int error; - - if (!PyArg_ParseTuple(args, "Oi", &obj, &force_interpreter)) - return NULL; - - const LLVMModuleRef mod = pycap_get( obj ) ; - - LLVMExecutionEngineRef ee; - if (force_interpreter) - error = LLVMCreateInterpreterForModule(&ee, mod, &outmsg); - else - error = LLVMCreateJITCompilerForModule(&ee, mod, 1 /*fast*/, &outmsg); - - PyObject *ret; - if (error) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetPointerToFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_fn; - - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_fn)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get(obj_ee ) ; - const LLVMValueRef fn = pycap_get( obj_fn ) ; - - return PyLong_FromVoidPtr(LLVMGetPointerToFunction(ee,fn)); - LLVMPY_CATCH_ALL -} - -/* the args should have been ptr, num */ -LLVMGenericValueRef LLVMRunFunction2(LLVMExecutionEngineRef EE, - LLVMValueRef F, LLVMGenericValueRef *Args, unsigned NumArgs) -{ - return LLVMRunFunction(EE, F, NumArgs, Args); -} - -static PyObject * -_wLLVMRemoveModule2(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_mod; - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_mod)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ) ; - const LLVMModuleRef mod = pycap_get(obj_mod) ; - - char *outmsg = 0; - LLVMModuleRef mod_new = 0; - LLVMRemoveModule(ee, mod, &mod_new, &outmsg); - PyObject *ret; - if (mod_new) { - ret = pycap_new(mod_new); - } else { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString("error"); - } - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeExecutionEngine, LLVMExecutionEngineRef) -_wrap_objobjlist2obj(LLVMRunFunction2, LLVMExecutionEngineRef, - LLVMValueRef, LLVMGenericValueRef, LLVMGenericValueRef) -_wrap_obj2obj(LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef, - LLVMTargetDataRef) -_wrap_obj2none(LLVMRunStaticConstructors, LLVMExecutionEngineRef) -_wrap_obj2none(LLVMRunStaticDestructors, LLVMExecutionEngineRef) -_wrap_objobj2none(LLVMFreeMachineCodeForFunction, LLVMExecutionEngineRef, - LLVMValueRef) -_wrap_objobj2none(LLVMAddModule, LLVMExecutionEngineRef, - LLVMModuleRef) - - -/*===----------------------------------------------------------------------===*/ -/* Generic Value */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateGenericValueOfInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - unsigned long long n; - int is_signed; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "OLi", &obj1, &n, &is_signed)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfInt(ty, n, is_signed); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - double d; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "Od", &obj1, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfFloat(ty, d); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY -// PyObject *obj1; -// LLVMTypeRef ty; //unused? - unsigned long long n_; - size_t n; - - if (!PyArg_ParseTuple(args, "L", &n_)) - return NULL; - - n=n_; - - const LLVMGenericValueRef gv = LLVMCreateGenericValueOfPointer((void*)n); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - int is_signed; - unsigned long long val; - - if (!PyArg_ParseTuple(args, "Oi", &obj1, &is_signed)) - return NULL; - - LLVMGenericValueRef gv = pycap_get(obj1); - - val = LLVMGenericValueToInt(gv, is_signed); - return is_signed ? - PyLong_FromLongLong((long long)val) : - PyLong_FromUnsignedLongLong(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2; - - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - const LLVMGenericValueRef gv = pycap_get( obj2 ) ; - - double val = LLVMGenericValueToFloat(ty, gv); - return PyFloat_FromDouble(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - - if (!PyArg_ParseTuple(args, "O", &obj1)) - return NULL; - - const LLVMGenericValueRef gv = pycap_get( obj1 ) ; - - void * val = LLVMGenericValueToPointer(gv); - return PyLong_FromVoidPtr(val); - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeGenericValue, LLVMGenericValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Misc */ -/*===----------------------------------------------------------------------===*/ - -_wrap_objintlist2obj(LLVMGetIntrinsic, LLVMModuleRef, LLVMTypeRef, - LLVMValueRef) - -static PyObject * -_wLLVMLoadLibraryPermanently(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *filename; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMLoadLibraryPermanently", &filename)) { - return NULL; - } - - char *outmsg = 0; - if (!LLVMLoadLibraryPermanently(filename, &outmsg)) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMParseEnvOpts(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * progname; - const char * envname; - if(!PyArg_ParseTuple(args, "ss", &progname, &envname)) { - return NULL; - } - - llvm::cl::ParseEnvironmentOptions(progname, envname); - - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - -/* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -static PyObject * -_wPyCObjectVoidPtrToPyLong(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - void *p = get_object_arg(args); - return PyLong_FromVoidPtr(p); - LLVMPY_CATCH_ALL -} - - -/*===----------------------------------------------------------------------===*/ -/* Python member method table */ -/*===----------------------------------------------------------------------===*/ - -#define _method( func ) { # func , ( PyCFunction )_w ## func , METH_VARARGS , NULL }, -#define _pass( P ) _method( LLVMAdd ## P ## Pass ) - -static PyMethodDef core_methods[] = { - - /* Modules */ - _method( LLVMModuleCreateWithName ) - _method( LLVMGetDataLayout ) - _method( LLVMSetDataLayout ) - _method( LLVMGetModuleIdentifier ) - _method( LLVMSetModuleIdentifier ) - _method( LLVMGetTarget ) - _method( LLVMSetTarget ) - _method( LLVMModuleAddLibrary ) - _method( LLVMGetTypeByName ) - _method( LLVMDumpModule ) - _method( LLVMDisposeModule ) - _method( LLVMDumpModuleToString ) - _method( LLVMVerifyModule ) - _method( LLVMGetModuleFromAssembly ) - _method( LLVMGetModuleFromBitcode ) - _method( LLVMGetBitcodeFromModule ) - _method( LLVMGetNativeCodeFromModule ) - _method( LLVMModuleGetPointerSize ) - _method( LLVMModuleGetOrInsertFunction ) - _method( LLVMLinkModules ) - - /* Types */ - - /* General */ - _method( LLVMGetTypeKind ) - _method( LLVMDumpTypeToString ) - - /* Integer types */ - _method( LLVMInt1Type ) - _method( LLVMInt8Type ) - _method( LLVMInt16Type ) - _method( LLVMInt32Type ) - _method( LLVMInt64Type ) - _method( LLVMIntType ) - _method( LLVMGetIntTypeWidth ) - - /* Floating-point types */ - _method( LLVMFloatType ) - _method( LLVMDoubleType ) - _method( LLVMX86FP80Type ) - _method( LLVMFP128Type ) - _method( LLVMPPCFP128Type ) - - /* Function types */ - _method( LLVMFunctionType ) - _method( LLVMIsFunctionVarArg ) - _method( LLVMGetReturnType ) - _method( LLVMCountParamTypes ) - _method( LLVMGetFunctionTypeParams ) - - /* Struct types */ - _method( LLVMStructType ) - _method( LLVMStructTypeIdentified ) - _method( LLVMSetStructBody ) - _method( LLVMCountStructElementTypes ) - _method( LLVMGetStructElementTypes ) - _method( LLVMIsPackedStruct ) - _method( LLVMIsOpaqueStruct ) - _method( LLVMIsLiteralStruct ) - _method( LLVMGetStructName ) - _method( LLVMSetStructName ) - - /* Array types */ - _method( LLVMArrayType ) - _method( LLVMGetElementType ) - _method( LLVMGetArrayLength ) - - /* Pointer types */ - _method( LLVMPointerType ) - _method( LLVMGetPointerAddressSpace ) - - /* Vector type */ - _method( LLVMVectorType ) - _method( LLVMGetVectorSize ) - - /* Other types */ - _method( LLVMVoidType ) - _method( LLVMLabelType ) - - /* Type handles */ - /* - _method( LLVMResolveTypeHandle ) - _method( LLVMDisposeTypeHandle ) - */ - - /* Values */ - - /* Operations on all values */ - _method( LLVMTypeOf ) - _method( LLVMGetValueName ) - _method( LLVMSetValueName ) - _method( LLVMDumpValue ) - _method( LLVMDumpValueToString ) - _method( LLVMValueGetID ) - _method( LLVMValueGetNumUses ) - _method( LLVMValueGetUses ) - - /* Users */ - - _method( LLVMUserGetNumOperands ) - _method( LLVMUserGetOperand ) - - /* Constant Values */ - - /* Operations on constants of any type */ - _method( LLVMConstNull ) - _method( LLVMConstAllOnes ) - _method( LLVMGetUndef ) - _method( LLVMIsConstant ) - _method( LLVMIsNull ) - _method( LLVMIsUndef ) - - /* Operations on scalar constants */ - _method( LLVMConstInt ) - _method( LLVMConstReal ) - _method( LLVMConstRealOfString ) - _method( LLVMConstIntGetZExtValue ) - _method( LLVMConstIntGetSExtValue ) - - /* Operations on composite constants */ - _method( LLVMConstString ) - _method( LLVMConstArray ) - _method( LLVMConstStruct ) - _method( LLVMConstVector ) - - /* Constant expressions */ - _method( LLVMGetConstExprOpcode ) - _method( LLVMGetConstExprOpcodeName ) - _method( LLVMSizeOf ) - _method( LLVMConstNeg ) - _method( LLVMConstNot ) - _method( LLVMConstAdd ) - _method( LLVMConstFAdd ) - _method( LLVMConstSub ) - _method( LLVMConstFSub ) - _method( LLVMConstMul ) - _method( LLVMConstFMul ) - _method( LLVMConstUDiv ) - _method( LLVMConstSDiv ) - _method( LLVMConstFDiv ) - _method( LLVMConstURem ) - _method( LLVMConstSRem ) - _method( LLVMConstFRem ) - _method( LLVMConstAnd ) - _method( LLVMConstOr ) - _method( LLVMConstXor ) - _method( LLVMConstICmp ) - _method( LLVMConstFCmp ) - _method( LLVMConstShl ) - _method( LLVMConstLShr ) - _method( LLVMConstAShr ) - _method( LLVMConstGEP ) - _method( LLVMConstTrunc ) - _method( LLVMConstSExt ) - _method( LLVMConstZExt ) - _method( LLVMConstFPTrunc ) - _method( LLVMConstFPExt ) - _method( LLVMConstUIToFP ) - _method( LLVMConstSIToFP ) - _method( LLVMConstFPToUI ) - _method( LLVMConstFPToSI ) - _method( LLVMConstPtrToInt ) - _method( LLVMConstIntToPtr ) - _method( LLVMConstBitCast ) - _method( LLVMConstSelect ) - _method( LLVMConstExtractElement ) - _method( LLVMConstInsertElement ) - _method( LLVMConstShuffleVector ) - - /* Globals */ - - /* Globals (general) */ - _method( LLVMGetGlobalParent ) - _method( LLVMIsDeclaration ) - _method( LLVMGetLinkage ) - _method( LLVMSetLinkage ) - _method( LLVMGetSection ) - _method( LLVMSetSection ) - _method( LLVMGetVisibility ) - _method( LLVMSetVisibility ) - _method( LLVMGetAlignment ) - _method( LLVMSetAlignment ) - - /* Global Variables */ - _method( LLVMAddGlobal ) - _method( LLVMGetNamedGlobal ) - _method( LLVMGetFirstGlobal ) - _method( LLVMGetNextGlobal ) - _method( LLVMDeleteGlobal ) - _method( LLVMHasInitializer ) - _method( LLVMGetInitializer ) - _method( LLVMSetInitializer ) - _method( LLVMSetThreadLocal ) - _method( LLVMIsThreadLocal ) - _method( LLVMSetGlobalConstant ) - _method( LLVMIsGlobalConstant ) - - /* Functions */ - _method( LLVMAddFunction ) - _method( LLVMGetNamedFunction ) - _method( LLVMGetFirstFunction ) - _method( LLVMGetNextFunction ) - _method( LLVMDeleteFunction ) - _method( LLVMGetIntrinsicID ) - _method( LLVMGetFunctionCallConv ) - _method( LLVMSetFunctionCallConv ) - _method( LLVMGetGC ) - _method( LLVMSetGC ) - _method( LLVMGetDoesNotThrow ) - _method( LLVMSetDoesNotThrow ) - _method( LLVMVerifyFunction ) - _method( LLVMViewFunctionCFG ) - _method( LLVMViewFunctionCFGOnly ) - _method( LLVMAddFunctionAttr ) - _method( LLVMRemoveFunctionAttr ) - - /* Arguments */ - _method( LLVMCountParams ) - _method( LLVMGetFirstParam ) - _method( LLVMGetNextParam ) - _method( LLVMGetParamParent ) - _method( LLVMAddAttribute ) - _method( LLVMRemoveAttribute ) - _method( LLVMSetParamAlignment ) - _method( LLVMGetParamAlignment ) - - /* Basic Blocks */ - _method( LLVMGetBasicBlockParent ) - _method( LLVMCountBasicBlocks ) - _method( LLVMGetFirstBasicBlock ) - _method( LLVMGetNextBasicBlock ) - _method( LLVMGetEntryBasicBlock ) - _method( LLVMAppendBasicBlock ) - _method( LLVMInsertBasicBlock ) - _method( LLVMDeleteBasicBlock ) - - /* MetaData */ - _method( LLVMMetaDataGet ) - _method( LLVMGetNamedMetadataOperands ) - _method( LLVMAddNamedMetadataOperand ) - _method( LLVMMetaDataGetOperand ) - _method( LLVMMetaDataGetNumOperands ) - _method( LLVMMetaDataStringGet ) - - /* Instructions */ - _method( LLVMGetInstructionParent ) - _method( LLVMGetFirstInstruction ) - _method( LLVMGetNextInstruction ) - _method( LLVMInstIsTerminator ) - _method( LLVMInstIsBinaryOp ) - _method( LLVMInstIsShift ) - _method( LLVMInstIsCast ) - _method( LLVMInstIsLogicalShift ) - _method( LLVMInstIsArithmeticShift ) - _method( LLVMInstIsAssociative ) - _method( LLVMInstIsCommutative ) - _method( LLVMInstIsVolatile ) - _method( LLVMSetVolatile ) - _method( LLVMInstGetOpcode ) - _method( LLVMInstGetOpcodeName ) - - _method( LLVMInstSetMetaData ) - - /* Call Sites (Call or Invoke) */ - _method( LLVMSetInstructionCallConv ) - _method( LLVMGetInstructionCallConv ) - _method( LLVMIsTailCall ) - _method( LLVMSetTailCall ) - _method( LLVMAddInstrAttribute ) - _method( LLVMRemoveInstrAttribute ) - _method( LLVMSetInstrParamAlignment ) - _method( LLVMInstGetCalledFunction ) - - /* PHI Nodes */ - _method( LLVMAddIncoming1 ) - _method( LLVMCountIncoming ) - _method( LLVMGetIncomingValue ) - _method( LLVMGetIncomingBlock ) - - /* Comparison Instructions */ - _method( LLVMCmpInstGetPredicate ) - - /* Instruction builders */ - _method( LLVMCreateBuilder ) - _method( LLVMPositionBuilderBefore ) - _method( LLVMPositionBuilderAtEnd ) - _method( LLVMGetInsertBlock ) - _method( LLVMDisposeBuilder ) - - /* Terminators */ - _method( LLVMBuildRetVoid ) - _method( LLVMBuildRet ) - _method( LLVMBuildRetMultiple ) - _method( LLVMBuildBr ) - _method( LLVMBuildCondBr ) - _method( LLVMBuildSwitch ) - _method( LLVMBuildInvoke ) - _method( LLVMBuildUnreachable ) - - /* Add a case to the switch instruction */ - _method( LLVMAddCase ) - - /* Arithmetic */ - _method( LLVMBuildAdd ) - _method( LLVMBuildFAdd) - _method( LLVMBuildSub ) - _method( LLVMBuildFSub) - _method( LLVMBuildMul ) - _method( LLVMBuildFMul) - _method( LLVMBuildUDiv ) - _method( LLVMBuildSDiv ) - _method( LLVMBuildFDiv ) - _method( LLVMBuildURem ) - _method( LLVMBuildSRem ) - _method( LLVMBuildFRem ) - _method( LLVMBuildShl ) - _method( LLVMBuildLShr ) - _method( LLVMBuildAShr ) - _method( LLVMBuildAnd ) - _method( LLVMBuildOr ) - _method( LLVMBuildXor ) - _method( LLVMBuildNeg ) - _method( LLVMBuildNot ) - - /* Memory */ - _method( LLVMBuildMalloc ) - _method( LLVMBuildArrayMalloc ) - _method( LLVMBuildAlloca ) - _method( LLVMBuildArrayAlloca ) - _method( LLVMBuildFree ) - _method( LLVMBuildLoad ) - _method( LLVMBuildStore ) - _method( LLVMBuildGEP ) - - _method( LLVMLdSetAlignment ) - _method( LLVMStSetAlignment ) - - /* Casts */ - _method( LLVMBuildTrunc ) - _method( LLVMBuildZExt ) - _method( LLVMBuildSExt ) - _method( LLVMBuildFPToUI ) - _method( LLVMBuildFPToSI ) - _method( LLVMBuildUIToFP ) - _method( LLVMBuildSIToFP ) - _method( LLVMBuildFPTrunc ) - _method( LLVMBuildFPExt ) - _method( LLVMBuildPtrToInt ) - _method( LLVMBuildIntToPtr ) - _method( LLVMBuildBitCast ) - - /* Comparisons */ - _method( LLVMBuildICmp ) - _method( LLVMBuildFCmp ) - - /* Atomics */ - _method( LLVMBuildAtomicCmpXchg ) - _method( LLVMBuildAtomicRMW ) - _method( LLVMBuildAtomicLoad ) - _method( LLVMBuildAtomicStore ) - _method( LLVMBuildFence ) - - /* Miscellaneous instructions */ - _method( LLVMBuildGetResult ) - _method( LLVMBuildInsertValue ) - _method( LLVMBuildPhi ) - _method( LLVMBuildCall ) - _method( LLVMBuildSelect ) - _method( LLVMBuildVAArg ) - _method( LLVMBuildExtractElement ) - _method( LLVMBuildInsertElement ) - _method( LLVMBuildShuffleVector ) - - /* Memory Buffer */ - _method( LLVMCreateMemoryBufferWithContentsOfFile ) - _method( LLVMCreateMemoryBufferWithSTDIN ) - _method( LLVMDisposeMemoryBuffer ) - - /* Pass Manager Builder */ - - _method( LLVMPassManagerBuilderCreate ) - _method( LLVMPassManagerBuilderDispose ) - - _method( LLVMPassManagerBuilderSetOptLevel ) - _method( LLVMPassManagerBuilderGetOptLevel ) - - _method( LLVMPassManagerBuilderSetSizeLevel ) - _method( LLVMPassManagerBuilderGetSizeLevel ) - - _method( LLVMPassManagerBuilderSetVectorize ) - _method( LLVMPassManagerBuilderGetVectorize ) - - - _method( LLVMPassManagerBuilderSetDisableUnitAtATime ) - _method( LLVMPassManagerBuilderGetDisableUnitAtATime ) - - _method( LLVMPassManagerBuilderSetDisableUnrollLoops ) - _method( LLVMPassManagerBuilderGetDisableUnrollLoops ) - - _method( LLVMPassManagerBuilderSetDisableSimplifyLibCalls ) - _method( LLVMPassManagerBuilderGetDisableSimplifyLibCalls ) - - _method( LLVMPassManagerBuilderUseInlinerWithThreshold ) - - _method( LLVMPassManagerBuilderPopulateFunctionPassManager ) - _method( LLVMPassManagerBuilderPopulateModulePassManager ) - - /* Pass Manager */ - _method( LLVMCreatePassManager ) - _method( LLVMCreateFunctionPassManagerForModule ) - _method( LLVMRunPassManager ) - _method( LLVMInitializeFunctionPassManager ) - _method( LLVMRunFunctionPassManager ) - _method( LLVMFinalizeFunctionPassManager ) - _method( LLVMDisposePassManager ) - _method( LLVMDumpPasses ) - _method( LLVMAddPassByName ) - _method( LLVMInitializePasses ) - - _method( LLVMInitializeNativeTarget ) - _method( LLVMInitializeNativeTargetAsmPrinter ) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX - _method( LLVMInitializeNVPTXTarget ) - _method( LLVMInitializeNVPTXTargetInfo ) - _method( LLVMInitializeNVPTXTargetMC ) - _method( LLVMInitializeNVPTXAsmPrinter ) -# else - _method( LLVMInitializePTXTarget ) - _method( LLVMInitializePTXTargetInfo ) - _method( LLVMInitializePTXTargetMC ) - _method( LLVMInitializePTXAsmPrinter ) -# endif -#endif - /* Passes */ - - /* - _pass( AAEval ) - _pass( AggressiveDCE ) - _pass( AliasAnalysisCounter ) - _pass( AlwaysInliner ) - _pass( ArgumentPromotion ) - _pass( BasicAliasAnalysis ) - _pass( BlockPlacement ) - _pass( BreakCriticalEdges ) - _pass( CFGSimplification ) - _pass( CodeGenPrepare ) - _pass( ConstantMerge ) - _pass( ConstantPropagation ) - _pass( DbgInfoPrinter ) - _pass( DeadArgElimination ) - _pass( DeadCodeElimination ) - _pass( DeadInstElimination ) - _pass( DeadStoreElimination ) - _pass( DemoteRegisterToMemory ) - _pass( DomOnlyPrinter ) - _pass( DomOnlyViewer ) - _pass( DomPrinter ) - _pass( DomViewer ) - _pass( EdgeProfiler ) - _pass( FunctionAttrs ) - _pass( FunctionInlining ) - //_pass( GEPSplitter ) - _pass( GlobalDCE ) - _pass( GlobalOptimizer ) - _pass( GlobalsModRef ) - _pass( GVN ) - _pass( IndVarSimplify ) - _pass( InstCount ) - _pass( InstructionCombining ) - _pass( InstructionNamer ) - _pass( IPConstantPropagation ) - _pass( IPSCCP ) - _pass( JumpThreading ) - _pass( LazyValueInfo ) - _pass( LCSSA ) - _pass( LICM ) - //_pass( LiveValues ) - _pass( LoopDeletion ) - _pass( LoopDependenceAnalysis ) - _pass( LoopExtractor ) - //_pass( LoopIndexSplit ) - _pass( LoopRotate ) - _pass( LoopSimplify ) - _pass( LoopStrengthReduce ) - _pass( LoopUnroll ) - _pass( LoopUnswitch ) - _pass( LowerInvoke ) - _pass( LowerSwitch ) - _pass( MemCpyOpt ) - _pass( MergeFunctions ) - _pass( NoAA ) - _pass( NoProfileInfo ) - _pass( OptimalEdgeProfiler ) - _pass( PartialInlining ) - //_pass( PartialSpecialization ) - _pass( PostDomOnlyPrinter ) - _pass( PostDomOnlyViewer ) - _pass( PostDomPrinter ) - _pass( PostDomViewer ) - _pass( ProfileEstimator ) - _pass( ProfileLoader ) - _pass( ProfileVerifier ) - _pass( PromoteMemoryToRegister ) - _pass( PruneEH ) - _pass( Reassociate ) - _pass( ScalarEvolutionAliasAnalysis ) - _pass( ScalarReplAggregates ) - _pass( SCCP ) - //_pass( SimplifyHalfPowrLibCalls ) - _pass( SimplifyLibCalls ) - _pass( SingleLoopExtractor ) - _pass( StripDeadPrototypes ) - _pass( StripNonDebugSymbols ) - _pass( StripSymbols ) - //_pass( StructRetPromotion ) - _pass( TailCallElimination ) - //_pass( TailDuplication ) - _pass( UnifyFunctionExitNodes ) - - _pass( Internalize2 ) - */ - - /* Target Machine */ - _method( LLVMTargetMachineFromEngineBuilder ) - _method( LLVMDisposeTargetMachine ) - _method( LLVMTargetMachineLookup ) - _method( LLVMTargetMachineEmitFile ) - _method( LLVMTargetMachineGetTargetData ) - _method( LLVMTargetMachineGetTargetName ) - _method( LLVMTargetMachineGetTargetShortDescription ) - _method( LLVMTargetMachineGetTriple ) - _method( LLVMTargetMachineGetCPU ) - _method( LLVMTargetMachineGetFS ) - - _method( LLVMPrintRegisteredTargetsForVersion ) - _method( LLVMGetHostCPUName ) - - /* Target Data */ - _method( LLVMCreateTargetData ) - _method( LLVMDisposeTargetData ) - _method( LLVMTargetDataAsString ) - _method( LLVMAddTargetData ) - _method( LLVMByteOrder ) - _method( LLVMPointerSize ) - _method( LLVMIntPtrType ) - _method( LLVMSizeOfTypeInBits ) - _method( LLVMStoreSizeOfType ) - _method( LLVMABISizeOfType ) - _method( LLVMABIAlignmentOfType ) - _method( LLVMCallFrameAlignmentOfType ) - _method( LLVMPreferredAlignmentOfType ) - _method( LLVMPreferredAlignmentOfGlobal ) - _method( LLVMElementAtOffset ) - _method( LLVMOffsetOfElement ) - - /* Engine Builder */ - - _method( LLVMCreateEngineBuilder ) - _method( LLVMDisposeEngineBuilder ) - _method( LLVMEngineBuilderForceJIT ) - _method( LLVMEngineBuilderForceInterpreter ) - _method( LLVMEngineBuilderSetOptLevel ) - _method( LLVMEngineBuilderSetMCPU ) - _method( LLVMEngineBuilderSetMAttrs ) - _method( LLVMEngineBuilderCreate ) - - /* Execution Engine */ - _method( LLVMCreateExecutionEngine ) - _method( LLVMDisposeExecutionEngine ) - _method( LLVMRunFunction2 ) - _method( LLVMGetPointerToFunction ) - _method( LLVMGetExecutionEngineTargetData ) - _method( LLVMRunStaticConstructors ) - _method( LLVMRunStaticDestructors ) - _method( LLVMFreeMachineCodeForFunction ) - _method( LLVMAddModule ) - _method( LLVMRemoveModule2 ) - - /* Generic Value */ - _method( LLVMCreateGenericValueOfInt ) - _method( LLVMCreateGenericValueOfFloat ) - _method( LLVMCreateGenericValueOfPointer ) - _method( LLVMGenericValueToInt ) - _method( LLVMGenericValueToFloat ) - _method( LLVMGenericValueToPointer ) - _method( LLVMDisposeGenericValue ) - - /* Misc */ - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) - _method( LLVMParseEnvOpts ) - - _method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - { NULL } -}; - - - -// Module main function, hairy because of py3k port -extern "C" { - -#if (PY_MAJOR_VERSION >= 3) -struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_core", - NULL, - -1, - core_methods, - NULL, NULL, NULL, NULL -}; -#define INITERROR return NULL -PyObject * -PyInit__core(void) -#else -#define INITERROR return -PyMODINIT_FUNC -init_core(void) -#endif -{ - LLVMLinkInJIT(); - LLVMLinkInInterpreter(); - LLVMInitializeNativeTarget(); -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create( &module_def ); -#else - PyObject *module = Py_InitModule("_core", core_methods); -#endif - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - - return module; -#endif -} - -} // end extern C diff --git a/llvm/_util.py b/llvm/_util.py deleted file mode 100644 index 8f06122..0000000 --- a/llvm/_util.py +++ /dev/null @@ -1,103 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Utility functions and classes. - -Used only in other modules, not for public use.""" - -import llvm -import llvm._core as _core # for PyCObjectVoidPtrToPyLong - - -#===----------------------------------------------------------------------=== -# A set of helpers to check various things. Raises exceptions on -# failures. -#===----------------------------------------------------------------------=== - -def check_gen(obj, typ): - if not isinstance(obj, typ): - typ_str = typ.__name__ - msg = "argument not an instance of llvm.core.%s" % typ_str - raise TypeError(msg) - -def check_is_unowned(ownable): - if ownable.owner: - raise llvm.LLVMException("object is already owned") - - -#===----------------------------------------------------------------------=== -# A set of helpers to unpack a list of Python wrapper objects -# into a list of PyCObject wrapped objects, checking types along -# the way. -#===----------------------------------------------------------------------=== - -def unpack_gen(objlist, check_fn): - for obj in objlist: check_fn(obj) - return [ obj.ptr for obj in objlist ] - -def unpack_gen_allow_none(objlist, check_fn): - for obj in objlist: - if obj is not None: - check_fn(obj) - return [ (obj.ptr if obj is not None else None) for obj in objlist ] - -#===----------------------------------------------------------------------=== -# Helper to wrap over iterables (LLVMFirstXXX, LLVMNextXXX). This used -# to be a generator, but that loses subscriptability of the result, so -# we now return a list. -#===----------------------------------------------------------------------=== - -def wrapiter(first, next, container, wrapper): - ret = [] - ptr = first(container) - while ptr: - ret.append(wrapper(ptr)) - ptr = next(ptr) - return ret - - -#===----------------------------------------------------------------------=== -# Py2/3 compatibility string check -#===----------------------------------------------------------------------=== -def _isstring_py2(x): - return isinstance(x, basestring) - -def _isstring_py3(x): - return isinstance(x, str) - -def _isstring_choose(): - try: - basestring - return _isstring_py2 - except: - return _isstring_py3 - -isstring = _isstring_choose() - diff --git a/llvm/_version.py b/llvm/_version.py new file mode 100644 index 0000000..a90c5b8 --- /dev/null +++ b/llvm/_version.py @@ -0,0 +1,193 @@ + +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by github's download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "$Format:%d$" +git_full = "$Format:%H$" +GIT = "git" + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "" +parentdir_prefix = "llvmpy-" +versionfile_source = "llvm/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver diff --git a/llvm/capsulethunk.h b/llvm/capsulethunk.h deleted file mode 100644 index 6b20564..0000000 --- a/llvm/capsulethunk.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef __CAPSULETHUNK_H -#define __CAPSULETHUNK_H - -#if ( (PY_VERSION_HEX < 0x02070000) \ - || ((PY_VERSION_HEX >= 0x03000000) \ - && (PY_VERSION_HEX < 0x03010000)) ) - -#define __PyCapsule_GetField(capsule, field, default_value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field) \ - : (default_value) \ - ) \ - -#define __PyCapsule_SetField(capsule, field, value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field = value), 1 \ - : 0 \ - ) \ - - -#define PyCapsule_Type PyCObject_Type - -#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule)) - - -#define PyCapsule_New(pointer, name, destructor) \ - (PyCObject_FromVoidPtr(pointer, destructor)) - - -#define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) - -/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */ -#define PyCapsule_SetPointer(capsule, pointer) \ - __PyCapsule_SetField(capsule, cobject, pointer) - - -#define PyCapsule_GetDestructor(capsule) \ - __PyCapsule_GetField(capsule, destructor) - -#define PyCapsule_SetDestructor(capsule, dtor) \ - __PyCapsule_SetField(capsule, destructor, dtor) - - -/* - * Sorry, there's simply no place - * to store a Capsule "name" in a CObject. - */ -#define PyCapsule_GetName(capsule) NULL - -static int -PyCapsule_SetName(PyObject *capsule, const char *unused) -{ - unused = unused; - PyErr_SetString(PyExc_NotImplementedError, - "can't use PyCapsule_SetName with CObjects"); - return 1; -} - - - -#define PyCapsule_GetContext(capsule) \ - __PyCapsule_GetField(capsule, descr) - -#define PyCapsule_SetContext(capsule, context) \ - __PyCapsule_SetField(capsule, descr, context) - - -static void * -PyCapsule_Import(const char *name, int no_block) -{ - PyObject *object = NULL; - void *return_value = NULL; - char *trace; - size_t name_length = (strlen(name) + 1) * sizeof(char); - char *name_dup = (char *)PyMem_MALLOC(name_length); - - if (!name_dup) { - return NULL; - } - - memcpy(name_dup, name, name_length); - - trace = name_dup; - while (trace) { - char *dot = strchr(trace, '.'); - if (dot) { - *dot++ = '\0'; - } - - if (object == NULL) { - if (no_block) { - object = PyImport_ImportModuleNoBlock(trace); - } else { - object = PyImport_ImportModule(trace); - if (!object) { - PyErr_Format(PyExc_ImportError, - "PyCapsule_Import could not " - "import module \"%s\"", trace); - } - } - } else { - PyObject *object2 = PyObject_GetAttrString(object, trace); - Py_DECREF(object); - object = object2; - } - if (!object) { - goto EXIT; - } - - trace = dot; - } - - if (PyCObject_Check(object)) { - PyCObject *cobject = (PyCObject *)object; - return_value = cobject->cobject; - } else { - PyErr_Format(PyExc_AttributeError, - "PyCapsule_Import \"%s\" is not valid", - name); - } - -EXIT: - Py_XDECREF(object); - if (name_dup) { - PyMem_FREE(name_dup); - } - return return_value; -} - -#endif /* #if PY_VERSION_HEX < 0x02070000 */ - -#endif /* __CAPSULETHUNK_H */ diff --git a/llvm/core.py b/llvm/core.py index da260a3..4db8135 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -28,156 +28,216 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -"""Core classes of LLVM. +from io import BytesIO +try: + from StringIO import StringIO +except ImportError: + try: + from cStringIO import StringIO + except ImportError: + from io import StringIO -The llvm.core module contains classes and constants required to build the -in-memory intermediate representation (IR) data structures.""" - - -import llvm # top-level, for common stuff -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions +import contextlib, weakref +import llvm +from llvm._intrinsic_ids import * +from llvm.deprecated import deprecated +from llvmpy import api #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== +class Enum(int): + '''Overload integer to print the name of the enum. + ''' + def __repr__(self): + return '%s(%d)' % (type(self).__name__, self) -# type kinds (LLVMTypeKind enum) -TYPE_VOID = 0 -TYPE_HALF = 1 -TYPE_FLOAT = 2 -TYPE_DOUBLE = 3 -TYPE_X86_FP80 = 4 -TYPE_FP128 = 5 -TYPE_PPC_FP128 = 6 -TYPE_LABEL = 7 -TYPE_INTEGER = 8 -TYPE_FUNCTION = 9 -TYPE_STRUCT = 10 -TYPE_ARRAY = 11 -TYPE_POINTER = 12 -TYPE_VECTOR = 13 -TYPE_METADATA = 14 -TYPE_X86_MMX = 15 + @classmethod + def declare(cls): + declared = cls._declared_ = {} + scope = globals() + for name in filter(lambda s: s.startswith(cls.prefix), dir(cls)): + n = getattr(cls, name) + typ = type(name, (cls,), {}) + obj = typ(n) + declared[n] = obj + scope[name] = obj + + @classmethod + def get(cls, num): + return cls._declared_[num] + +# type id (llvm::Type::TypeID) +class TypeEnum(Enum): + prefix = 'TYPE_' + TypeID = api.llvm.Type.TypeID + + TYPE_VOID = TypeID.VoidTyID + TYPE_HALF = TypeID.HalfTyID + TYPE_FLOAT = TypeID.FloatTyID + TYPE_DOUBLE = TypeID.DoubleTyID + TYPE_X86_FP80 = TypeID.X86_FP80TyID + TYPE_FP128 = TypeID.FP128TyID + TYPE_PPC_FP128 = TypeID.PPC_FP128TyID + TYPE_LABEL = TypeID.LabelTyID + TYPE_INTEGER = TypeID.IntegerTyID + TYPE_FUNCTION = TypeID.FunctionTyID + TYPE_STRUCT = TypeID.StructTyID + TYPE_ARRAY = TypeID.ArrayTyID + TYPE_POINTER = TypeID.PointerTyID + TYPE_VECTOR = TypeID.VectorTyID + TYPE_METADATA = TypeID.MetadataTyID + TYPE_X86_MMX = TypeID.X86_MMXTyID + +TypeEnum.declare() # value IDs (llvm::Value::ValueTy enum) -VALUE_ARGUMENT = 0 -VALUE_BASIC_BLOCK = 1 -VALUE_FUNCTION = 2 -VALUE_GLOBAL_ALIAS = 3 -VALUE_GLOBAL_VARIABLE = 4 -VALUE_UNDEF_VALUE = 5 -VALUE_BLOCK_ADDRESS = 6 -VALUE_CONSTANT_EXPR = 7 -VALUE_CONSTANT_AGGREGATE_ZERO = 8 -VALUE_CONSTANT_DATA_ARRAY = 9 -VALUE_CONSTANT_DATA_VECTOR = 10 -VALUE_CONSTANT_INT = 11 -VALUE_CONSTANT_FP = 12 -VALUE_CONSTANT_ARRAY = 13 -VALUE_CONSTANT_STRUCT = 14 -VALUE_CONSTANT_VECTOR = 15 -VALUE_CONSTANT_POINTER_NULL = 16 -VALUE_MD_NODE = 17 -VALUE_MD_STRING = 18 -VALUE_INLINE_ASM = 19 -VALUE_PSEUDO_SOURCE_VALUE = 20 -VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = 21 -VALUE_INSTRUCTION = 22 +# According to the doxygen docs, it is not a good idea to use these enums. +# There are more values than those declared. +class ValueEnum(Enum): + prefix = 'VALUE_' + ValueTy = api.llvm.Value.ValueTy + + VALUE_ARGUMENT = ValueTy.ArgumentVal + VALUE_BASIC_BLOCK = ValueTy.BasicBlockVal + VALUE_FUNCTION = ValueTy.FunctionVal + VALUE_GLOBAL_ALIAS = ValueTy.GlobalAliasVal + VALUE_GLOBAL_VARIABLE = ValueTy.GlobalVariableVal + VALUE_UNDEF_VALUE = ValueTy.UndefValueVal + VALUE_BLOCK_ADDRESS = ValueTy.BlockAddressVal + VALUE_CONSTANT_EXPR = ValueTy.ConstantExprVal + VALUE_CONSTANT_AGGREGATE_ZERO = ValueTy.ConstantAggregateZeroVal + VALUE_CONSTANT_DATA_ARRAY = ValueTy.ConstantDataArrayVal + VALUE_CONSTANT_DATA_VECTOR = ValueTy.ConstantDataVectorVal + VALUE_CONSTANT_INT = ValueTy.ConstantIntVal + VALUE_CONSTANT_FP = ValueTy.ConstantFPVal + VALUE_CONSTANT_ARRAY = ValueTy.ConstantArrayVal + VALUE_CONSTANT_STRUCT = ValueTy.ConstantStructVal + VALUE_CONSTANT_VECTOR = ValueTy.ConstantVectorVal + VALUE_CONSTANT_POINTER_NULL = ValueTy.ConstantPointerNullVal + VALUE_MD_NODE = ValueTy.MDNodeVal + VALUE_MD_STRING = ValueTy.MDStringVal + VALUE_INLINE_ASM = ValueTy.InlineAsmVal + VALUE_PSEUDO_SOURCE_VALUE = ValueTy.PseudoSourceValueVal + VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = ValueTy.FixedStackPseudoSourceValueVal + VALUE_INSTRUCTION = ValueTy.InstructionVal + +ValueEnum.declare() # instruction opcodes (from include/llvm/Instruction.def) -OPCODE_RET = 1 -OPCODE_BR = 2 -OPCODE_SWITCH = 3 -OPCODE_INDIRECT_BR = 4 -OPCODE_INVOKE = 5 -OPCODE_RESUME = 6 -OPCODE_UNREACHABLE = 7 -OPCODE_ADD = 8 -OPCODE_FADD = 9 -OPCODE_SUB = 10 -OPCODE_FSUB = 11 -OPCODE_MUL = 12 -OPCODE_FMUL = 13 -OPCODE_UDIV = 14 -OPCODE_SDIV = 15 -OPCODE_FDIV = 16 -OPCODE_UREM = 17 -OPCODE_SREM = 18 -OPCODE_FREM = 19 -OPCODE_SHL = 20 -OPCODE_LSHR = 21 -OPCODE_ASHR = 22 -OPCODE_AND = 23 -OPCODE_OR = 24 -OPCODE_XOR = 25 -OPCODE_ALLOCA = 26 -OPCODE_LOAD = 27 -OPCODE_STORE = 28 -OPCODE_GETELEMENTPTR = 29 -OPCODE_FENCE = 30 -OPCODE_ATOMICCMPXCHG = 31 -OPCODE_ATOMICRMW = 32 -OPCODE_TRUNC = 33 -OPCODE_ZEXT = 34 -OPCODE_SEXT = 35 -OPCODE_FPTOUI = 36 -OPCODE_FPTOSI = 37 -OPCODE_UITOFP = 38 -OPCODE_SITOFP = 39 -OPCODE_FPTRUNC = 40 -OPCODE_FPEXT = 41 -OPCODE_PTRTOINT = 42 -OPCODE_INTTOPTR = 43 -OPCODE_BITCAST = 44 -OPCODE_ICMP = 45 -OPCODE_FCMP = 46 -OPCODE_PHI = 47 -OPCODE_CALL = 48 -OPCODE_SELECT = 49 -OPCODE_USEROP1 = 50 -OPCODE_USEROP2 = 51 -OPCODE_VAARG = 52 -OPCODE_EXTRACTELEMENT = 53 -OPCODE_INSERTELEMENT = 54 -OPCODE_SHUFFLEVECTOR = 55 -OPCODE_EXTRACTVALUE = 56 -OPCODE_INSERTVALUE = 57 -OPCODE_LANDINGPAD = 58 +class OpcodeEnum(Enum): + prefix = 'OPCODE_' + + OPCODE_RET = 1 + OPCODE_BR = 2 + OPCODE_SWITCH = 3 + OPCODE_INDIRECT_BR = 4 + OPCODE_INVOKE = 5 + OPCODE_RESUME = 6 + OPCODE_UNREACHABLE = 7 + OPCODE_ADD = 8 + OPCODE_FADD = 9 + OPCODE_SUB = 10 + OPCODE_FSUB = 11 + OPCODE_MUL = 12 + OPCODE_FMUL = 13 + OPCODE_UDIV = 14 + OPCODE_SDIV = 15 + OPCODE_FDIV = 16 + OPCODE_UREM = 17 + OPCODE_SREM = 18 + OPCODE_FREM = 19 + OPCODE_SHL = 20 + OPCODE_LSHR = 21 + OPCODE_ASHR = 22 + OPCODE_AND = 23 + OPCODE_OR = 24 + OPCODE_XOR = 25 + OPCODE_ALLOCA = 26 + OPCODE_LOAD = 27 + OPCODE_STORE = 28 + OPCODE_GETELEMENTPTR = 29 + OPCODE_FENCE = 30 + OPCODE_ATOMICCMPXCHG = 31 + OPCODE_ATOMICRMW = 32 + OPCODE_TRUNC = 33 + OPCODE_ZEXT = 34 + OPCODE_SEXT = 35 + OPCODE_FPTOUI = 36 + OPCODE_FPTOSI = 37 + OPCODE_UITOFP = 38 + OPCODE_SITOFP = 39 + OPCODE_FPTRUNC = 40 + OPCODE_FPEXT = 41 + OPCODE_PTRTOINT = 42 + OPCODE_INTTOPTR = 43 + OPCODE_BITCAST = 44 + OPCODE_ICMP = 45 + OPCODE_FCMP = 46 + OPCODE_PHI = 47 + OPCODE_CALL = 48 + OPCODE_SELECT = 49 + OPCODE_USEROP1 = 50 + OPCODE_USEROP2 = 51 + OPCODE_VAARG = 52 + OPCODE_EXTRACTELEMENT = 53 + OPCODE_INSERTELEMENT = 54 + OPCODE_SHUFFLEVECTOR = 55 + OPCODE_EXTRACTVALUE = 56 + OPCODE_INSERTVALUE = 57 + OPCODE_LANDINGPAD = 58 + +OpcodeEnum.declare() # calling conventions -CC_C = 0 -CC_FASTCALL = 8 -CC_COLDCALL = 9 -CC_GHC = 10 -CC_X86_STDCALL = 64 -CC_X86_FASTCALL = 65 -CC_ARM_APCS = 66 -CC_ARM_AAPCS = 67 -CC_ARM_AAPCS_VFP = 68 -CC_MSP430_INTR = 69 -CC_X86_THISCALL = 70 -CC_PTX_KERNEL = 71 -CC_PTX_DEVICE = 72 -CC_MBLAZE_INTR = 73 -CC_MBLAZE_SVOL = 74 +class CCEnum(Enum): + prefix = 'CC_' + + ID = api.llvm.CallingConv.ID + + CC_C = ID.C + CC_FASTCALL = ID.Fast + CC_COLDCALL = ID.Cold + CC_GHC = ID.GHC + CC_X86_STDCALL = ID.X86_StdCall + CC_X86_FASTCALL = ID.X86_FastCall + CC_ARM_APCS = ID.ARM_APCS + CC_ARM_AAPCS = ID.ARM_AAPCS + CC_ARM_AAPCS_VFP = ID.ARM_AAPCS_VFP + CC_MSP430_INTR = ID.MSP430_INTR + CC_X86_THISCALL = ID.X86_ThisCall + CC_PTX_KERNEL = ID.PTX_Kernel + CC_PTX_DEVICE = ID.PTX_Device + + if llvm.version <= (3, 3): + CC_MBLAZE_INTR = ID.MBLAZE_INTR + CC_MBLAZE_SVOL = ID.MBLAZE_SVOL + +CCEnum.declare() # int predicates -ICMP_EQ = 32 -ICMP_NE = 33 -ICMP_UGT = 34 -ICMP_UGE = 35 -ICMP_ULT = 36 -ICMP_ULE = 37 -ICMP_SGT = 38 -ICMP_SGE = 39 -ICMP_SLT = 40 -ICMP_SLE = 41 +class ICMPEnum(Enum): + prefix = 'ICMP_' + Predicate = api.llvm.CmpInst.Predicate + + ICMP_EQ = Predicate.ICMP_EQ + ICMP_NE = Predicate.ICMP_NE + ICMP_UGT = Predicate.ICMP_UGT + ICMP_UGE = Predicate.ICMP_UGE + ICMP_ULT = Predicate.ICMP_ULT + ICMP_ULE = Predicate.ICMP_ULE + ICMP_SGT = Predicate.ICMP_SGT + ICMP_SGE = Predicate.ICMP_SGE + ICMP_SLT = Predicate.ICMP_SLT + ICMP_SLE = Predicate.ICMP_SLE + +ICMPEnum.declare() # same as ICMP_xx, for backward compatibility + IPRED_EQ = ICMP_EQ IPRED_NE = ICMP_NE IPRED_UGT = ICMP_UGT @@ -190,24 +250,33 @@ IPRED_SLT = ICMP_SLT IPRED_SLE = ICMP_SLE # real predicates -FCMP_FALSE = 0 -FCMP_OEQ = 1 -FCMP_OGT = 2 -FCMP_OGE = 3 -FCMP_OLT = 4 -FCMP_OLE = 5 -FCMP_ONE = 6 -FCMP_ORD = 7 -FCMP_UNO = 8 -FCMP_UEQ = 9 -FCMP_UGT = 10 -FCMP_UGE = 11 -FCMP_ULT = 12 -FCMP_ULE = 13 -FCMP_UNE = 14 -FCMP_TRUE = 15 + +class FCMPEnum(Enum): + prefix = 'FCMP_' + + Predicate = api.llvm.CmpInst.Predicate + + FCMP_FALSE = Predicate.FCMP_FALSE + FCMP_OEQ = Predicate.FCMP_OEQ + FCMP_OGT = Predicate.FCMP_OGT + FCMP_OGE = Predicate.FCMP_OGE + FCMP_OLT = Predicate.FCMP_OLT + FCMP_OLE = Predicate.FCMP_OLE + FCMP_ONE = Predicate.FCMP_ONE + FCMP_ORD = Predicate.FCMP_ORD + FCMP_UNO = Predicate.FCMP_UNO + FCMP_UEQ = Predicate.FCMP_UEQ + FCMP_UGT = Predicate.FCMP_UGT + FCMP_UGE = Predicate.FCMP_UGE + FCMP_ULT = Predicate.FCMP_ULT + FCMP_ULE = Predicate.FCMP_ULE + FCMP_UNE = Predicate.FCMP_UNE + FCMP_TRUE = Predicate.FCMP_TRUE + +FCMPEnum.declare() # real predicates + RPRED_FALSE = FCMP_FALSE RPRED_OEQ = FCMP_OEQ RPRED_OGT = FCMP_OGT @@ -225,101 +294,78 @@ RPRED_ULE = FCMP_ULE RPRED_UNE = FCMP_UNE RPRED_TRUE = FCMP_TRUE -# linkages (see llvm-c/Core.h) -LINKAGE_EXTERNAL = 0 -LINKAGE_AVAILABLE_EXTERNALLY = 1 -LINKAGE_LINKONCE_ANY = 2 -LINKAGE_LINKONCE_ODR = 3 -LINKAGE_WEAK_ANY = 4 -LINKAGE_WEAK_ODR = 5 -LINKAGE_APPENDING = 6 -LINKAGE_INTERNAL = 7 -LINKAGE_PRIVATE = 8 -LINKAGE_DLLIMPORT = 9 -LINKAGE_DLLEXPORT = 10 -LINKAGE_EXTERNAL_WEAK = 11 -LINKAGE_GHOST = 12 -LINKAGE_COMMON = 13 -LINKAGE_LINKER_PRIVATE = 14 -LINKAGE_LINKER_PRIVATE_WEAK = 15 -LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 +# linkages (see llvm::GlobalValue::LinkageTypes) +class LinkageEnum(Enum): + prefix = 'LINKAGE_' + LinkageTypes = api.llvm.GlobalValue.LinkageTypes + + LINKAGE_EXTERNAL = LinkageTypes.ExternalLinkage + LINKAGE_AVAILABLE_EXTERNALLY = LinkageTypes.AvailableExternallyLinkage + LINKAGE_LINKONCE_ANY = LinkageTypes.LinkOnceAnyLinkage + LINKAGE_LINKONCE_ODR = LinkageTypes.LinkOnceODRLinkage + LINKAGE_WEAK_ANY = LinkageTypes.WeakAnyLinkage + LINKAGE_WEAK_ODR = LinkageTypes.WeakODRLinkage + LINKAGE_APPENDING = LinkageTypes.AppendingLinkage + LINKAGE_INTERNAL = LinkageTypes.InternalLinkage + LINKAGE_PRIVATE = LinkageTypes.PrivateLinkage + LINKAGE_DLLIMPORT = LinkageTypes.DLLImportLinkage + LINKAGE_DLLEXPORT = LinkageTypes.DLLExportLinkage + LINKAGE_EXTERNAL_WEAK = LinkageTypes.ExternalWeakLinkage + LINKAGE_COMMON = LinkageTypes.CommonLinkage + LINKAGE_LINKER_PRIVATE = LinkageTypes.LinkerPrivateLinkage + LINKAGE_LINKER_PRIVATE_WEAK = LinkageTypes.LinkerPrivateWeakLinkage + +LinkageEnum.declare() # visibility (see llvm/GlobalValue.h) -VISIBILITY_DEFAULT = 0 -VISIBILITY_HIDDEN = 1 -VISIBILITY_PROTECTED = 2 +class VisibilityEnum(Enum): + prefix = 'VISIBILITY_' -# parameter attributes (see llvm/Attributes.h) -ATTR_NONE = 0 -ATTR_ZEXT = 1 -ATTR_SEXT = 2 -ATTR_NO_RETURN = 4 -ATTR_IN_REG = 8 -ATTR_STRUCT_RET = 16 -ATTR_NO_UNWIND = 32 -ATTR_NO_ALIAS = 64 -ATTR_BY_VAL = 128 -ATTR_NEST = 256 -ATTR_READ_NONE = 512 -ATTR_READONLY = 1024 -ATTR_NO_INLINE = 1<<11 -ATTR_ALWAYS_INLINE = 1<<12 -ATTR_OPTIMIZE_FOR_SIZE = 1<<13 -ATTR_STACK_PROTECT = 1<<14 -ATTR_STACK_PROTECT_REQ = 1<<15 -ATTR_ALIGNMENT = 1<<16 -ATTR_NO_CAPTURE = 1<<21 -ATTR_NO_REDZONE = 1<<22 -ATTR_NO_IMPLICIT_FLOAT = 1<<23 -ATTR_NAKED = 1<<24 -ATTR_INLINE_HINT = 1<<25 -ATTR_STACK_ALIGNMENT = 7<<26 -ATTR_HOTPATCH = 1<<29 + VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility + VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility + VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility -# intrinsic IDs -from llvm._intrinsic_ids import * +VisibilityEnum.declare() +# parameter attributes +# LLVM 3.2 llvm::Attributes::AttrVal (see llvm/Attributes.h) +# LLVM 3.3 llvm::Attribute::AttrKind (see llvm/Attributes.h) +class AttrEnum(Enum): + prefix = 'ATTR_' -#===----------------------------------------------------------------------=== -# Helpers (for internal use) -#===----------------------------------------------------------------------=== - -def check_is_type(obj): _util.check_gen(obj, Type) -def check_is_type_struct(obj): _util.check_gen(obj, StructType) -def check_is_value(obj): _util.check_gen(obj, Value) -def check_is_constant(obj): _util.check_gen(obj, Constant) -def check_is_function(obj): _util.check_gen(obj, Function) -def check_is_basic_block(obj): _util.check_gen(obj, BasicBlock) -def check_is_module(obj): _util.check_gen(obj, Module) - -def unpack_types(objlst): return _util.unpack_gen(objlst, check_is_type) -def unpack_values(objlst): return _util.unpack_gen(objlst, check_is_value) -def unpack_constants(objlst): return _util.unpack_gen(objlst, check_is_constant) - -def unpack_values_or_none(objlst): - return _util.unpack_gen_allow_none(objlst, check_is_value) - -def check_is_callable(obj): - if isinstance(obj, Function): - return - typ = obj.type - if isinstance(typ, PointerType) and \ - isinstance(typ.pointee, FunctionType): - return - raise TypeError("argument is neither a function nor a function pointer") - -def _to_int(v): - if v: - return 1 + if llvm.version >= (3, 3): + AttrVal = api.llvm.Attribute.AttrKind else: - return 0 + AttrVal = api.llvm.Attributes.AttrVal + ATTR_NONE = AttrVal.None_ + ATTR_ZEXT = AttrVal.ZExt + ATTR_SEXT = AttrVal.SExt + ATTR_NO_RETURN = AttrVal.NoReturn + ATTR_IN_REG = AttrVal.InReg + ATTR_STRUCT_RET = AttrVal.StructRet + ATTR_NO_UNWIND = AttrVal.NoUnwind + ATTR_NO_ALIAS = AttrVal.NoAlias + ATTR_BY_VAL = AttrVal.ByVal + ATTR_NEST = AttrVal.Nest + ATTR_READ_NONE = AttrVal.ReadNone + ATTR_READONLY = AttrVal.ReadOnly + ATTR_NO_INLINE = AttrVal.NoInline + ATTR_ALWAYS_INLINE = AttrVal.AlwaysInline + ATTR_OPTIMIZE_FOR_SIZE = AttrVal.OptimizeForSize + ATTR_STACK_PROTECT = AttrVal.StackProtect + ATTR_STACK_PROTECT_REQ = AttrVal.StackProtectReq + ATTR_ALIGNMENT = AttrVal.Alignment + ATTR_NO_CAPTURE = AttrVal.NoCapture + ATTR_NO_REDZONE = AttrVal.NoRedZone + ATTR_NO_IMPLICIT_FLOAT = AttrVal.NoImplicitFloat + ATTR_NAKED = AttrVal.Naked + ATTR_INLINE_HINT = AttrVal.InlineHint + ATTR_STACK_ALIGNMENT = AttrVal.StackAlignment -#===----------------------------------------------------------------------=== -# Module -#===----------------------------------------------------------------------=== +AttrEnum.declare() -class Module(llvm.Ownable, llvm.Cacheable): +class Module(llvm.Wrapper): """A Module instance stores all the information related to an LLVM module. Modules are the top level container of all other LLVM Intermediate @@ -333,6 +379,16 @@ class Module(llvm.Ownable, llvm.Cacheable): module_obj = Module.new('my_module') """ + __slots__ = '__weakref__' + __cache = weakref.WeakValueDictionary() + + def __new__(cls, ptr): + cached = cls.__cache.get(ptr) + if cached: + return cached + obj = object.__new__(cls) + cls.__cache[ptr] = obj + return obj @staticmethod def new(id): @@ -340,7 +396,9 @@ class Module(llvm.Ownable, llvm.Cacheable): Creates an instance of Module, having the id `id'. """ - return Module(_core.LLVMModuleCreateWithName(id)) + context = api.llvm.getGlobalContext() + m = api.llvm.Module.new(id, context) + return Module(m) @staticmethod def from_bitcode(fileobj_or_str): @@ -348,20 +406,20 @@ class Module(llvm.Ownable, llvm.Cacheable): file. fileobj_or_str -- takes a file-like object or string that contains - a module represented in bitcode. + a module represented in bitcode. """ + if isinstance(fileobj_or_str, str): + bc = fileobj_or_str + else: + bc = fileobj_or_str.read() + errbuf = BytesIO() + context = api.llvm.getGlobalContext() + m = api.llvm.ParseBitCodeFile(bc, context, errbuf) + if not m: + raise Exception(errbuf.getvalue()) + errbuf.close() + return Module(m) - if isinstance(fileobj_or_str, basestring): - data = fileobj_or_str - else: - data = fileobj_or_str.read() - ret = _core.LLVMGetModuleFromBitcode(data) - if not ret: - raise llvm.LLVMException("Unable to create module from bitcode") - elif _util.isstring(ret): - raise llvm.LLVMException(ret) - else: - return Module(ret) @staticmethod def from_assembly(fileobj_or_str): @@ -370,81 +428,70 @@ class Module(llvm.Ownable, llvm.Cacheable): fileobj_or_str -- takes a file-like object or string that contains - a module represented in llvm-ir assembly. + a module represented in llvm-ir assembly. """ - - if isinstance(fileobj_or_str, basestring): - data = fileobj_or_str + if isinstance(fileobj_or_str, str): + ir = fileobj_or_str else: - data = fileobj_or_str.read() - ret = _core.LLVMGetModuleFromAssembly(data) - if not ret: - raise llvm.LLVMException("Unable to create module from assembly") - elif isinstance(ret, str): - raise llvm.LLVMException(ret) - else: - return Module(ret) - - def __init__(self, ptr): - """DO NOT CALL DIRECTLY. - - Use the static method `Module.new' instead. - """ - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule) + ir = fileobj_or_str.read() + errbuf = BytesIO() + context = api.llvm.getGlobalContext() + m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDiagnostic.new(), + context) + errbuf.close() + return Module(m) def __str__(self): """Text representation of a module. - Returns the textual representation (`llvm assembly') of the - module. Use it like this: + Returns the textual representation (`llvm assembly') of the + module. Use it like this: - ll = str(module_obj) - print module_obj # same as `print ll' - """ - return _core.LLVMDumpModuleToString(self.ptr) + ll = str(module_obj) + print module_obj # same as `print ll' + """ + return str(self._ptr) + + def __hash__(self): + return id(self._ptr) def __eq__(self, rhs): if isinstance(rhs, Module): - return str(self) == str(rhs) - else: - return False + return self._ptr == rhs._ptr def __ne__(self, rhs): - return not self == rhs + return not (self == rhs) + def _get_target(self): - return _core.LLVMGetTarget(self.ptr) + return self._ptr.getTargetTriple() def _set_target(self, value): - return _core.LLVMSetTarget(self.ptr, value) + return self._ptr.setTargetTriple(value) target = property(_get_target, _set_target, - """The target triple string describing the target host.""" - ) + doc="The target triple string describing the target host.") + def _get_data_layout(self): - return _core.LLVMGetDataLayout(self.ptr) + return self._ptr.getDataLayout() def _set_data_layout(self, value): - _core.LLVMSetDataLayout(self.ptr, value) + return self._ptr.setDataLayout(value) data_layout = property(_get_data_layout, _set_data_layout, - """The data layout string for the module's target platform. + doc = """The data layout string for the module's target platform. - The data layout strings is an encoded representation of - the type sizes and alignments expected by this module. - """ - ) + The data layout strings is an encoded representation of + the type sizes and alignments expected by this module. + """ + ) @property def pointer_size(self): - """Pointer size of target platform. + return self._ptr.getPointerSize() - Can be 0, 32 or 64. Zero represents - llvm::Module::AnyPointerSize.""" - return _core.LLVMModuleGetPointerSize(self.ptr) - - def link_in(self, other): + def link_in(self, other, preserve=False): """Link the `other' module into this one. The `other' module is linked into this one such that types, @@ -456,157 +503,246 @@ class Module(llvm.Ownable, llvm.Cacheable): In the future, this API might be replaced with a full-fledged Linker class. """ - check_is_module(other) - other.forget() # remove it from object cache - ret = _core.LLVMLinkModules(self.ptr, other.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - # Do not try to destroy the other module's llvm::Module*. - other._own(llvm.DummyOwner()) + assert isinstance(other, Module) + enum_mode = api.llvm.Linker.LinkerMode + mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource + + with contextlib.closing(BytesIO()) as errmsg: + failed = api.llvm.Linker.LinkModules(self._ptr, + other._ptr, + mode, + errmsg) + if failed: + raise llvm.LLVMException(errmsg.getvalue()) def get_type_named(self, name): - """Return a Type object with the given name.""" - ptr = _core.LLVMGetTypeByName(self.ptr, name) - if ptr: - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - return None + typ = self._ptr.getTypeByName(name) + if typ: + return StructType(typ) - def add_global_variable(self, ty, name): + def add_global_variable(self, ty, name, addrspace=0): """Add a global variable of given type with given name.""" - return GlobalVariable.new(self, ty, name) + external = api.llvm.GlobalVariable.LinkageTypes.ExternalLinkage + notthreadlocal = api.llvm.GlobalVariable.ThreadLocalMode.NotThreadLocal + init = None + insertbefore = None + ptr = api.llvm.GlobalVariable.new(self._ptr, + ty._ptr, + False, + external, + init, + name, + insertbefore, + notthreadlocal, + addrspace) + return _make_value(ptr) def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" - return GlobalVariable.get(self, name) + ptr = self._ptr.getNamedGlobal(name) + if ptr is None: + raise llvm.LLVMException("No global named: %s" % name) + return _make_value(ptr) @property def global_variables(self): - """All global variables in this module.""" - return _util.wrapiter(_core.LLVMGetFirstGlobal, - _core.LLVMGetNextGlobal, self.ptr, _make_value) + return list(map(_make_value, self._ptr.list_globals())) def add_function(self, ty, name): """Add a function of given type with given name.""" return Function.new(self, ty, name) +# fn = self.get_function_named(name) +# if fn is not None: +# raise llvm.LLVMException("Duplicated function %s" % name) +# return self.get_or_insert_function(ty, name) def get_function_named(self, name): """Return a Function object representing function with given name.""" return Function.get(self, name) +# fn = self._ptr.getFunction(name) +# if fn is not None: +# return _make_value(fn) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if - function is not present.""" + function is not present.""" return Function.get_or_insert(self, ty, name) +# constant = self._ptr.getOrInsertFunction(name, ty._ptr) +# try: +# fn = constant._downcast(api.llvm.Function) +# except ValueError: +# # bitcasted to function type +# return _make_value(constant) +# else: +# return _make_value(fn) @property def functions(self): """All functions in this module.""" - return _util.wrapiter(_core.LLVMGetFirstFunction, - _core.LLVMGetNextFunction, self.ptr, _make_value) + return list(map(_make_value, self._ptr.list_functions())) def verify(self): """Verify module. - Checks module for errors. Raises `llvm.LLVMException' on any - error.""" - ret = _core.LLVMVerifyModule(self.ptr) - if ret != "": - raise llvm.LLVMException(ret) + Checks module for errors. Raises `llvm.LLVMException' on any + error.""" + action = api.llvm.VerifierFailureAction.ReturnStatusAction + errio = BytesIO() + broken = api.llvm.verifyModule(self._ptr, action, errio) + if broken: + raise llvm.LLVMException(errio.getvalue()) def to_bitcode(self, fileobj=None): """Write bitcode representation of module to given file-like object. fileobj -- A file-like object to where the bitcode is written. - If it is None, the bitcode is returned. + If it is None, the bitcode is returned. Return value -- Returns None if fileobj is not None. - Otherwise, return the bitcode as a bytestring. + Otherwise, return the bitcode as a bytestring. """ - - data = _core.LLVMGetBitcodeFromModule(self.ptr) - if not data: - raise llvm.LLVMException("Unable to create bitcode") - if fileobj is not None: - fileobj.write(data) - else: - return data - - def add_library(self, name): - return _core.LLVMModuleAddLibrary(self.ptr, name) + ret = False + if fileobj is None: + ret = True + fileobj = BytesIO() + api.llvm.WriteBitcodeToFile(self._ptr, fileobj) + if ret: + return fileobj.getvalue() def _get_id(self): - return _core.LLVMGetModuleIdentifier(self.ptr) + return self._ptr.getModuleIdentifier() def _set_id(self, string): - _core.LLVMSetModuleIdentifier(self.ptr, string) + self._ptr.setModuleIdentifier(string) id = property(_get_id, _set_id) - def to_native_object(self): - '''returns byte string of the module as native object code + def _to_native_something(self, fileobj, cgft): + + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_ObjectFile + + from llvm.ee import TargetMachine + from llvm.passes import PassManager + from llvmpy import extra + tm = TargetMachine.new()._ptr + pm = PassManager.new()._ptr + formatted + failed = tm.addPassesToEmitFile(pm, fileobj, cgft, False) + + if failed: + raise llvm.LLVMException("Failed to write native object file") + if ret: + return fileobj.getvalue() + + + def to_native_object(self, fileobj=None): + '''Outputs the byte string of the module as native object code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned ''' - return _core.LLVMGetNativeCodeFromModule(self.ptr, 0) + ret = False + if fileobj is None: + ret = True + fileobj = BytesIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + fileobj.write(tm.emit_object(self)) + if ret: + return fileobj.getvalue() - def to_native_assembly(self): - '''returns byte string of the module as native assembly code + + def to_native_assembly(self, fileobj=None): + '''Outputs the byte string of the module as native assembly code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned ''' - return _core.LLVMGetNativeCodeFromModule(self.ptr, 1) + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + asm = tm.emit_assembly(self) + fileobj.write(asm) + if ret: + return fileobj.getvalue() -#===----------------------------------------------------------------------=== -# Types -#===----------------------------------------------------------------------=== -class Type(object): + def get_or_insert_named_metadata(self, name): + return NamedMetaData(self._ptr.getOrInsertNamedMetadata(name)) + + def get_named_metadata(self, name): + md = self._ptr.getNamedMetadata(name) + if md: + return NamedMetaData(md) + + def clone(self): + return Module(api.llvm.CloneModule(self._ptr)) + +class Type(llvm.Wrapper): """Represents a type, like a 32-bit integer or an 80-bit x86 float. Use one of the static methods to create an instance. Example: - ty = Type.double() + ty = Type.double() """ + __slots__ = '__name__' + _type_ = api.llvm.Type + + def __init__(self, ptr): + ptr = ptr._downcast(type(self)._type_) + super(Type, self).__init__(ptr) + + @property + def kind(self): + return self._ptr.getTypeID() @staticmethod def int(bits=32): """Create an integer type having the given bit width.""" - if bits == 1: - return _make_type(_core.LLVMInt1Type(), TYPE_INTEGER) - elif bits == 8: - return _make_type(_core.LLVMInt8Type(), TYPE_INTEGER) - elif bits == 16: - return _make_type(_core.LLVMInt16Type(), TYPE_INTEGER) - elif bits == 32: - return _make_type(_core.LLVMInt32Type(), TYPE_INTEGER) - elif bits == 64: - return _make_type(_core.LLVMInt64Type(), TYPE_INTEGER) - else: - bits = int(bits) # bits must be an int - return _make_type(_core.LLVMIntType(bits), TYPE_INTEGER) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getIntNTy(context, bits) + return Type(ptr) @staticmethod def float(): """Create a 32-bit floating point type.""" - return _make_type(_core.LLVMFloatType(), TYPE_FLOAT) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFloatTy(context) + return Type(ptr) @staticmethod def double(): """Create a 64-bit floating point type.""" - return _make_type(_core.LLVMDoubleType(), TYPE_DOUBLE) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getDoubleTy(context) + return Type(ptr) @staticmethod def x86_fp80(): """Create a 80-bit x86 floating point type.""" - return _make_type(_core.LLVMX86FP80Type(), TYPE_X86_FP80) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getX86_FP80Ty(context) + return Type(ptr) @staticmethod def fp128(): """Create a 128-bit floating point type (with 112-bit - mantissa).""" - return _make_type(_core.LLVMFP128Type(), TYPE_FP128) + mantissa).""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFP128Ty(context) + return Type(ptr) @staticmethod def ppc_fp128(): """Create a 128-bit floating point type (two 64-bits).""" - return _make_type(_core.LLVMPPCFP128Type(), TYPE_PPC_FP128) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getPPC_FP128Ty(context) + return Type(ptr) + @staticmethod def function(return_ty, param_tys, var_arg=False): @@ -616,20 +752,19 @@ class Type(object): `return_ty', takes arguments of types as given in the iterable `param_tys'. Set `var_arg' to True (default is False) for a variadic function.""" - check_is_type(return_ty) - var_arg = _to_int(var_arg) # ensure int - params = unpack_types(param_tys) - return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, - var_arg), TYPE_FUNCTION) + ptr = api.llvm.FunctionType.get(return_ty._ptr, + llvm._extract_ptrs(param_tys), + var_arg) + return FunctionType(ptr) @staticmethod def opaque(name): """Create a opaque StructType""" + context = api.llvm.getGlobalContext() if not name: - raise llvm.LLVMException("Must specify a name") - - objptr = _core.LLVMStructTypeIdentified(name) - return _make_type(objptr, TYPE_STRUCT) + raise llvm.LLVMException("Opaque type must have a non-empty name") + ptr = api.llvm.StructType.create(context, name) + return StructType(ptr) @staticmethod def struct(element_tys, name=''): # not packed @@ -641,7 +776,18 @@ class Type(object): If name is not '', creates a identified type; otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=False, name=name) + context = api.llvm.getGlobalContext() + is_packed = False + if name: + ptr = api.llvm.StructType.create(context, name) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) + else: + ptr = api.llvm.StructType.get(context, + llvm._extract_ptrs(element_tys), + is_packed) + + + return StructType(ptr) @staticmethod def packed_struct(element_tys, name=''): @@ -653,21 +799,11 @@ class Type(object): If name is not '', creates a identified type; otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=True, name=name) - - @staticmethod - def __struct(element_tys, packed, name): - elems = unpack_types(element_tys) - packed = int(bool(packed)) - - if name: # create Identified StructType - objptr = _core.LLVMStructTypeIdentified(name) - _core.LLVMSetStructBody(objptr, elems, packed) - else: # create Literal StructType - objptr = _core.LLVMStructType(elems, packed) - - return _make_type(objptr, TYPE_STRUCT) - + context = api.llvm.getGlobalContext() + is_packed = True + ptr = api.llvm.StructType.create(context, name) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) + return StructType(ptr) @staticmethod def array(element_ty, count): @@ -675,10 +811,8 @@ class Type(object): Creates a type for an array of elements of type `element_ty', having 'count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMArrayType(element_ty.ptr, count), - TYPE_ARRAY) + ptr = api.llvm.ArrayType.get(element_ty._ptr, count) + return ArrayType(ptr) @staticmethod def pointer(pointee_ty, addr_space=0): @@ -686,10 +820,8 @@ class Type(object): Creates a pointer type, which can point to values of type `pointee_ty', in the address space `addr_space'.""" - check_is_type(pointee_ty) - addr_space = int(addr_space) # must be an int - return _make_type(_core.LLVMPointerType(pointee_ty.ptr, - addr_space), TYPE_POINTER) + ptr = api.llvm.PointerType.get(pointee_ty._ptr, addr_space) + return PointerType(ptr) @staticmethod def vector(element_ty, count): @@ -697,222 +829,227 @@ class Type(object): Creates a type for a vector of elements of type `element_ty', having `count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMVectorType(element_ty.ptr, count), - TYPE_VECTOR) + ptr = api.llvm.VectorType.get(element_ty._ptr, count) + return VectorType(ptr) @staticmethod def void(): """Create a void type. Represents the `void' type.""" - return _make_type(_core.LLVMVoidType(), TYPE_VOID) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getVoidTy(context) + return Type(ptr) @staticmethod def label(): """Create a label type.""" - return _make_type(_core.LLVMLabelType(), TYPE_LABEL) + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getLabelTy(context) + return Type(ptr) - def __init__(self, ptr, kind): - """DO NOT CALL DIRECTLY. + def __new__(cls, ptr): + tyid = ptr.getTypeID() - Use one of the static methods instead.""" - self.ptr = ptr - self.kind = kind - """An enum (int) value denoting which type this is. + idmap = { + TYPE_HALF: IntegerType, + TYPE_INTEGER: IntegerType, + TYPE_FUNCTION: FunctionType, + TYPE_STRUCT: StructType, + TYPE_ARRAY: ArrayType, + TYPE_POINTER: PointerType, + TYPE_VECTOR: VectorType, + } - Use the symbolic constants TYPE_* defined in llvm.core - module.""" + try: + newcls = idmap[tyid] + except KeyError: + newcls = Type + obj = llvm.Wrapper.__new__(newcls) + return obj def __str__(self): - """Text representation of a type. + return str(self._ptr) - Returns the textual representation (`llvm assembly') of the type.""" - return _core.LLVMDumpTypeToString(self.ptr) + def __hash__(self): + return hash(self._ptr) def __eq__(self, rhs): - if isinstance(rhs, Type): - return str(self) == str(rhs) - else: - return False + return self._ptr is rhs._ptr def __ne__(self, rhs): - return not self == rhs - + return not (self == rhs) class IntegerType(Type): """Represents an integer type.""" + __slots__ = () + _type_ = api.llvm.IntegerType @property def width(self): """The width of the integer type, in bits.""" - return _core.LLVMGetIntTypeWidth(self.ptr) - + return self._ptr.getIntegerBitWidth() class FunctionType(Type): """Represents a function type.""" + __slots__ = () + _type_ = api.llvm.FunctionType @property def return_type(self): """The type of the value returned by this function.""" - ptr = _core.LLVMGetReturnType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) + return Type(self._ptr.getReturnType()) @property def vararg(self): """True if this function is variadic.""" - return _core.LLVMIsFunctionVarArg(self.ptr) != 0 + return self._ptr.isVarArg() @property def args(self): """An iterable that yields Type objects, representing the types of the - arguments accepted by this function, in order.""" - pp = _core.LLVMGetFunctionTypeParams(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] + arguments accepted by this function, in order.""" + return [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] @property def arg_count(self): """Number of arguments accepted by this function. - Same as len(obj.args), but faster.""" - return _core.LLVMCountParamTypes(self.ptr) + Same as len(obj.args), but faster.""" + return self._ptr.getNumParams() class StructType(Type): """Represents a structure type.""" + _type_ = api.llvm.StructType + __slots__ = () @property def element_count(self): """Number of elements (members) in the structure. - Same as len(obj.elements), but faster.""" - return _core.LLVMCountStructElementTypes(self.ptr) + Same as len(obj.elements), but faster.""" + return self._ptr.getNumElements() @property def elements(self): - """An iterable that yieldsd Type objects, representing the types of the - elements (members) of the structure, in order.""" - pp = _core.LLVMGetStructElementTypes(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] + """An iterable that yields Type objects, representing the types of the + elements (members) of the structure, in order.""" + return [Type(self._ptr.getElementType(i)) + for i in range(self._ptr.getNumElements())] def set_body(self, elems, packed=False): """Filled the body of a opaque type. - """ + """ # check if not self.is_opaque: raise llvm.LLVMException("Body is already defined.") - # prepare arguments - elems = unpack_types(elems) - if packed: - packed = 1 - else: - packed = 0 - - # call c API - _core.LLVMSetStructBody(self.ptr, elems, packed) + self._ptr.setBody(llvm._extract_ptrs(elems), packed) @property def packed(self): """True if the structure is packed, False otherwise.""" - return _core.LLVMIsPackedStruct(self.ptr) != 0 + return self._ptr.isPacked() def _set_name(self, name): - _core.LLVMSetStructName(self.ptr, name) + self._ptr.setName(name) def _get_name(self): - return _core.LLVMGetStructName(self.ptr) + if self._ptr.isLiteral(): + return "" + else: + return self._ptr.getName() name = property(_get_name, _set_name) @property def is_literal(self): - return bool(_core.LLVMIsLiteralStruct(self.ptr)) + return self._ptr.isLiteral() @property def is_identified(self): - return not _core.LLVMIsLiteralStruct(self.ptr) + return not self.is_literal @property def is_opaque(self): - return bool(_core.LLVMIsOpaqueStruct(self.ptr)) + return self._ptr.isOpaque() + + def is_layout_identical(self, other): + return self._ptr.isLayoutIdentical(other._ptr) class ArrayType(Type): """Represents an array type.""" + _type_ = api.llvm.ArrayType + __slots__ = () @property def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) + return Type(self._ptr.getArrayElementType()) @property def count(self): - return _core.LLVMGetArrayLength(self.ptr) - + return self._ptr.getNumElements() class PointerType(Type): + _type_ = api.llvm.PointerType + __slots__ = () @property def pointee(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) + return Type(self._ptr.getPointerElementType()) @property def address_space(self): - return _core.LLVMGetPointerAddressSpace(self.ptr) - + return self._ptr.getAddressSpace() class VectorType(Type): + _type_ = api.llvm.VectorType + __slots__ = () @property def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) + return Type(self._ptr.getVectorElementType()) @property def count(self): - return _core.LLVMGetVectorSize(self.ptr) + return self._ptr.getNumElements() +class Value(llvm.Wrapper): + _type_ = api.llvm.Value + __slots__ = '__weakref__' -#===----------------------------------------------------------------------=== -# Type factory method -#===----------------------------------------------------------------------=== + def __init__(self, builder, ptr): + assert builder is _ValueFactory -# type ID -> class map -__class_for_typeid = { - TYPE_INTEGER : IntegerType, - TYPE_FUNCTION : FunctionType, - TYPE_STRUCT : StructType, - TYPE_ARRAY : ArrayType, - TYPE_POINTER : PointerType, - TYPE_VECTOR : VectorType, -} - -def _make_type(ptr, kind): - class_obj = __class_for_typeid.get(kind) - if class_obj: - return class_obj(ptr, kind) - else: - # "generic" type - return Type(ptr, kind) - - -#===----------------------------------------------------------------------=== -# Values -#===----------------------------------------------------------------------=== - -class Value(llvm.Cacheable): - - def __init__(self, ptr): - self.ptr = ptr + if type(self._type_) is type: + if isinstance(ptr, self._type_): # is not downcast + casted = ptr + else: + casted = ptr._downcast(self._type_) + else: + try: + for ty in self._type_: + if isinstance(ptr, ty): # is not downcast + casted = ptr + else: + try: + casted = ptr._downcast(ty) + except ValueError: + pass + else: + break + else: + casted = ptr + except TypeError: + casted = ptr + super(Value, self).__init__(casted) def __str__(self): - return _core.LLVMDumpValueToString(self.ptr) + return str(self._ptr) + + def __hash__(self): + return hash(self._ptr) def __eq__(self, rhs): if isinstance(rhs, Value): @@ -924,1039 +1061,1263 @@ class Value(llvm.Cacheable): return not self == rhs def _get_name(self): - return _core.LLVMGetValueName(self.ptr) + return self._ptr.getName() def _set_name(self, value): - return _core.LLVMSetValueName(self.ptr, value) + return self._ptr.setName(value) name = property(_get_name, _set_name) @property def value_id(self): - return _core.LLVMValueGetID(self.ptr) + return self._ptr.getValueID() @property def type(self): - ptr = _core.LLVMTypeOf(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) + return Type(self._ptr.getType()) @property def use_count(self): - return _core.LLVMValueGetNumUses(self.ptr) + return self._ptr.getNumUses() @property def uses(self): - return [ _make_value(v) for v in _core.LLVMValueGetUses(self.ptr) ] - + return list(map(_make_value, self._ptr.list_use())) class User(Value): + _type_ = api.llvm.User + __slots__ = () @property def operand_count(self): - return _core.LLVMUserGetNumOperands(self.ptr) + return self._ptr.getNumOperands() @property def operands(self): """Yields operands of this instruction.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) + return [_make_value(self._ptr.getOperand(i)) + for i in range(self.operand_count)] class Constant(User): + _type_ = api.llvm.Constant + __slots__ = () @staticmethod def null(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstNull(ty.ptr)) + return _make_value(api.llvm.Constant.getNullValue(ty._ptr)) @staticmethod def all_ones(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstAllOnes(ty.ptr)) + return _make_value(api.llvm.Constant.getAllOnesValue(ty._ptr)) @staticmethod def undef(ty): - check_is_type(ty) - return _make_value(_core.LLVMGetUndef(ty.ptr)) + return _make_value(api.llvm.UndefValue.get(ty._ptr)) @staticmethod def int(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 0)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), False)) @staticmethod def int_signextend(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 1)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), True)) @staticmethod def real(ty, value): - check_is_type(ty) - if isinstance(value, str): - return _make_value(_core.LLVMConstRealOfString(ty.ptr, value)) - else: - return _make_value(_core.LLVMConstReal(ty.ptr, value)) + return _make_value(api.llvm.ConstantFP.get(ty._ptr, float(value))) @staticmethod def string(strval): # dont_null_terminate=True - return _make_value(_core.LLVMConstString(strval, 1)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, False)) @staticmethod def stringz(strval): # dont_null_terminate=False - return _make_value(_core.LLVMConstString(strval, 0)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, True)) @staticmethod def array(ty, consts): - check_is_type(ty) - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstArray(ty.ptr, const_ptrs)) + aryty = Type.array(ty, len(consts)) + return _make_value(api.llvm.ConstantArray.get(aryty._ptr, + llvm._extract_ptrs(consts))) @staticmethod def struct(consts): # not packed - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 0)) + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) @staticmethod def packed_struct(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 1)) + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) @staticmethod def vector(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstVector(const_ptrs)) + return _make_value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) @staticmethod def sizeof(ty): - check_is_type(ty) - return _make_value(_core.LLVMSizeOf(ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) def neg(self): - return _make_value(_core.LLVMConstNeg(self.ptr)) + return _make_value(api.llvm.ConstantExpr.getNeg(self._ptr)) def not_(self): - return _make_value(_core.LLVMConstNot(self.ptr)) + return _make_value(api.llvm.ConstantExpr.getNot(self._ptr)) def add(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAdd(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) def fadd(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFAdd(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) def sub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSub(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) def fsub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFSub(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) def mul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstMul(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) def fmul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFMul(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) def udiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstUDiv(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) def sdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSDiv(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) def fdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFDiv(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) def urem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstURem(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) def srem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSRem(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) def frem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFRem(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) def and_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAnd(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) def or_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstOr(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) def xor(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstXor(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) def icmp(self, int_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstICmp(int_pred, self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) def fcmp(self, real_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFCmp(real_pred, self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) def shl(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstShl(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) def lshr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstLShr(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) def ashr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAShr(self.ptr, rhs.ptr)) + return _make_value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) def gep(self, indices): - index_ptrs = unpack_constants(indices) - return _make_value(_core.LLVMConstGEP(self.ptr, index_ptrs)) + indices = llvm._extract_ptrs(indices) + return _make_value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) def trunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstTrunc(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty._ptr)) def sext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSExt(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getSExt(self._ptr, ty._ptr)) def zext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstZExt(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getZExt(self._ptr, ty._ptr)) def fptrunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPTrunc(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty._ptr)) def fpext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPExt(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty._ptr)) def uitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstUIToFP(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty._ptr)) def sitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSIToFP(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty._ptr)) def fptoui(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToUI(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty._ptr)) def fptosi(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToSI(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty._ptr)) def ptrtoint(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstPtrToInt(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty._ptr)) def inttoptr(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstIntToPtr(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty._ptr)) def bitcast(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstBitCast(self.ptr, ty.ptr)) + return _make_value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty._ptr)) def select(self, true_const, false_const): - check_is_constant(true_const) - check_is_constant(false_const) - return _make_value( - _core.LLVMConstSelect(self.ptr, true_const.ptr, false_const.ptr)) + return _make_value(api.llvm.ConstantExpr.getSelect(self._ptr, + true_const._ptr, + false_const._ptr)) def extract_element(self, index): # note: self must be a _vector_ constant - check_is_constant(index) - return _make_value( - _core.LLVMConstExtractElement(self.ptr, index.ptr)) + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) def insert_element(self, value, index): - # note: self must be a _vector_ constant - check_is_constant(value) - check_is_constant(index) - return _make_value( - _core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr)) + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, + value._ptr, + index._ptr)) def shuffle_vector(self, vector_b, mask): - # note: self must be a _vector_ constant - check_is_constant(vector_b) - # note: vector_b must be a _vector_ constant - check_is_constant(mask) - return _make_value( - _core.LLVMConstShuffleVector(self.ptr, vector_b.ptr, mask.ptr)) - + return _make_value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, + vector_b._ptr, + mask._ptr)) class ConstantExpr(Constant): + _type_ = api.llvm.ConstantExpr + __slots__ = () + @property def opcode(self): - return _core.LLVMGetConstExprOpcode(self.ptr) + return self._ptr.getOpcode() @property def opcode_name(self): - return _core.LLVMGetConstExprOpcodeName(self.ptr) - + return self._ptr.getOpcodeName() class ConstantAggregateZero(Constant): - pass + __slots__ = () class ConstantDataArray(Constant): - pass + __slots__ = () class ConstantDataVector(Constant): - pass + __slots__ = () + class ConstantInt(Constant): + _type_ = api.llvm.ConstantInt + __slots__ = () + @property def z_ext_value(self): '''Obtain the zero extended value for an integer constant value.''' # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetZExtValue(self.ptr) + return self._ptr.getZExtValue() @property def s_ext_value(self): '''Obtain the sign extended value for an integer constant value.''' # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetSExtValue(self.ptr) + return self._ptr.getSExtValue() class ConstantFP(Constant): - pass + __slots__ = () class ConstantArray(Constant): - pass + __slots__ = () class ConstantStruct(Constant): - pass + __slots__ = () class ConstantVector(Constant): - pass + __slots__ = () class ConstantPointerNull(Constant): - pass + __slots__ = () class UndefValue(Constant): - pass + __slots__ = () class GlobalValue(Constant): - - def __init__(self, ptr): - Constant.__init__(self, ptr) - # Hang on to the module, don't let it die before we do. - # It is nice to have just a map of functions without - # retaining a ref to the owning module. - self._module_obj = self.module - - def _delete(self): - # Called in subclass delete() methods. - self._module_obj = None + _type_ = api.llvm.GlobalValue + __slots__ = () def _get_linkage(self): - return _core.LLVMGetLinkage(self.ptr) + return self._ptr.getLinkage() + def _set_linkage(self, value): - _core.LLVMSetLinkage(self.ptr, value) + self._ptr.setLinkage(value) + linkage = property(_get_linkage, _set_linkage) def _get_section(self): - return _core.LLVMGetSection(self.ptr) + return self._ptr.getSection() + def _set_section(self, value): - return _core.LLVMSetSection(self.ptr, value) + return self._ptr.setSection(value) + section = property(_get_section, _set_section) def _get_visibility(self): - return _core.LLVMGetVisibility(self.ptr) + return self._ptr.getVisibility() + def _set_visibility(self, value): - return _core.LLVMSetVisibility(self.ptr, value) + return self._ptr.setVisibility(value) + visibility = property(_get_visibility, _set_visibility) def _get_alignment(self): - return _core.LLVMGetAlignment(self.ptr) + return self._ptr.getAlignment() + def _set_alignment(self, value): - return _core.LLVMSetAlignment(self.ptr, value) + return self._ptr.setAlignment(value) + alignment = property(_get_alignment, _set_alignment) @property def is_declaration(self): - return _core.LLVMIsDeclaration(self.ptr) != 0 + return self._ptr.isDeclaration() @property def module(self): - return Module(_core.LLVMGetGlobalParent(self.ptr)) + return Module(self._ptr.getParent()) + + class GlobalVariable(GlobalValue): + _type_ = api.llvm.GlobalVariable + __slots__ = () @staticmethod - def new(module, ty, name): - check_is_module(module) - check_is_type(ty) - return _make_value(_core.LLVMAddGlobal(module.ptr, ty.ptr, name)) + def new(module, ty, name, addrspace=0): + linkage = api.llvm.GlobalValue.LinkageTypes + external_linkage = linkage.ExternalLinkage + tlmode = api.llvm.GlobalVariable.ThreadLocalMode + not_threadlocal = tlmode.NotThreadLocal + gv = api.llvm.GlobalVariable.new(module._ptr, + ty._ptr, + False, # is constant + external_linkage, + None, # initializer + name, + None, # insert before + not_threadlocal, + addrspace) + return _make_value(gv) @staticmethod def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedGlobal(module.ptr, name) - if not ptr: - raise llvm.LLVMException("no global named `%s`" % name) - return _make_value(ptr) + gv = _make_value(module._ptr.getNamedGlobal(name)) + if not gv: + llvm.LLVMException("no global named `%s`" % name) + return gv def delete(self): - self._delete() - _core.LLVMDeleteGlobal(self.ptr) - self.forget() - self.ptr = None + _ValueFactory.delete(self._ptr) + self._ptr.eraseFromParent() def _get_initializer(self): - if _core.LLVMHasInitializer(self.ptr): - return _make_value(_core.LLVMGetInitializer(self.ptr)) - else: + if not self._ptr.hasInitializer(): return None + return _make_value(self._ptr.getInitializer()) def _set_initializer(self, const): - check_is_constant(const) - _core.LLVMSetInitializer(self.ptr, const.ptr) + self._ptr.setInitializer(const._ptr) def _del_initializer(self): - check_is_constant(const) + self._ptr.setInitializer(None) initializer = property(_get_initializer, _set_initializer) def _get_is_global_constant(self): - return _core.LLVMIsGlobalConstant(self.ptr) + return self._ptr.isConstant() def _set_is_global_constant(self, value): - value = _to_int(value) - _core.LLVMSetGlobalConstant(self.ptr, value) + self._ptr.setConstant(value) - global_constant = \ - property(_get_is_global_constant, _set_is_global_constant) + global_constant = property(_get_is_global_constant, + _set_is_global_constant) def _get_thread_local(self): - return bool(_core.LLVMIsThreadLocal(self.ptr)) + return self._ptr.isThreadLocal() + def _set_thread_local(self, value): - value = _to_int(value) - _core.LLVMSetThreadLocal(self.ptr, value) + return self._ptr.setThreadLocal(value) thread_local = property(_get_thread_local, _set_thread_local) class Argument(Value): + __slots__ = () + _type_ = api.llvm.Argument + _valid_attrs = frozenset([ATTR_BY_VAL, ATTR_NEST, ATTR_NO_ALIAS, + ATTR_NO_CAPTURE, ATTR_STRUCT_RET]) - def add_attribute(self, attr): - _core.LLVMAddAttribute(self.ptr, attr) + if llvm.version >= (3, 3): + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) - def remove_attribute(self, attr): - _core.LLVMRemoveAttribute(self.ptr, attr) + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) - def _set_alignment(self, align): - _core.LLVMSetParamAlignment(self.ptr, align) + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.AttributeSet.get(context, 0, attrbldr) + self._ptr.addAttr(attrs) + else: + def add_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + if attr not in self: + raise ValueError("Attribute %r is not valid for arg %s" % + (attr, self)) + + def remove_attribute(self, attr): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) def _get_alignment(self): - return _core.LLVMGetParamAlignment(self.ptr) + return self._ptr.getParamAlignment() - alignment = \ - property(_get_alignment, _set_alignment) + alignment = property(_get_alignment, + _set_alignment) + @property + def attributes(self): + '''Returns a set of defined attributes. + ''' + return set(attr for attr in self._valid_attrs if attr in self) + + def __contains__(self, attr): + if attr == ATTR_BY_VAL: + return self.has_by_val() + elif attr == ATTR_NEST: + return self.has_nest() + elif attr == ATTR_NO_ALIAS: + return self.has_no_alias() + elif attr == ATTR_NO_CAPTURE: + return self.has_no_capture() + elif attr == ATTR_STRUCT_RET: + return self.has_struct_ret() + else: + raise ValueError('invalid attribute for argument') + + @property + def arg_no(self): + return self._ptr.getArgNo() + + def has_by_val(self): + return self._ptr.hasByValAttr() + + def has_nest(self): + return self._ptr.hasNestAttr() + + def has_no_alias(self): + return self._ptr.hasNoAliasAttr() + + def has_no_capture(self): + return self._ptr.hasNoCaptureAttr() + + def has_struct_ret(self): + return self._ptr.hasStructRetAttr() class Function(GlobalValue): + __slots__ = () + _type_ = api.llvm.Function @staticmethod def new(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMAddFunction(module.ptr, name, - func_ty.ptr)) + try: + fn = Function.get(module, name) + except llvm.LLVMException: + return Function.get_or_insert(module, func_ty, name) + else: + raise llvm.LLVMException("Duplicated function %s" % name) + @staticmethod def get_or_insert(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMModuleGetOrInsertFunction(module.ptr, - name, func_ty.ptr)) + constant = module._ptr.getOrInsertFunction(name, func_ty._ptr) + try: + fn = constant._downcast(api.llvm.Function) + except ValueError: + # bitcasted to function type + return _make_value(constant) + else: + return _make_value(fn) @staticmethod def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedFunction(module.ptr, name) - if not ptr: + fn = module._ptr.getFunction(name) + if fn is None: raise llvm.LLVMException("no function named `%s`" % name) - return _make_value(ptr) + else: + return _make_value(fn) @staticmethod def intrinsic(module, intrinsic_id, types): - check_is_module(module) - ptrs = unpack_types(types) - return _make_value( - _core.LLVMGetIntrinsic(module.ptr, intrinsic_id, ptrs)) + fn = api.llvm.Intrinsic.getDeclaration(module._ptr, + intrinsic_id, + llvm._extract_ptrs(types)) + return _make_value(fn) def delete(self): - self._delete() - _core.LLVMDeleteFunction(self.ptr) - self.forget() - self.ptr = None + _ValueFactory.delete(self._ptr) + self._ptr.eraseFromParent() @property def intrinsic_id(self): - return _core.LLVMGetIntrinsicID(self.ptr) + self._ptr.getIntrinsicID() + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + self._ptr.setCallingConv(value) - def _get_cc(self): return _core.LLVMGetFunctionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetFunctionCallConv(self.ptr, value) calling_convention = property(_get_cc, _set_cc) - def _get_coll(self): return _core.LLVMGetGC(self.ptr) - def _set_coll(self, value): _core.LLVMSetGC(self.ptr, value) + def _get_coll(self): + return self._ptr.getGC() + + def _set_coll(self, value): + return self._ptr.setGC(value) + collector = property(_get_coll, _set_coll) # the nounwind attribute: - def _get_does_not_throw(self): return _core.LLVMGetDoesNotThrow(self.ptr) - def _set_does_not_throw(self,value): _core.LLVMSetDoesNotThrow(self.ptr, value) + def _get_does_not_throw(self): + return self._ptr.doesNotThrow() + + def _set_does_not_throw(self,value): + assert value + self._ptr.setDoesNotThrow() + does_not_throw = property(_get_does_not_throw, _set_does_not_throw) @property def args(self): - return _util.wrapiter(_core.LLVMGetFirstParam, - _core.LLVMGetNextParam, self.ptr, _make_value) + args = self._ptr.getArgumentList() + return list(map(_make_value, args)) @property def basic_block_count(self): - return _core.LLVMCountBasicBlocks(self.ptr) + return len(self.basic_blocks) @property def entry_basic_block(self): - if self.basic_block_count == 0: - return None - return _make_value(_core.LLVMGetEntryBasicBlock(self.ptr)) + assert self.basic_block_count + return _make_value(self._ptr.getEntryBlock()) def get_entry_basic_block(self): - """Deprecated, use entry_basic_block property.""" + "Deprecated. Use entry_basic_block instead" return self.entry_basic_block def append_basic_block(self, name): - return _make_value(_core.LLVMAppendBasicBlock(self.ptr, name)) + context = api.llvm.getGlobalContext() + bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) + return _make_value(bb) @property def basic_blocks(self): - return _util.wrapiter(_core.LLVMGetFirstBasicBlock, - _core.LLVMGetNextBasicBlock, self.ptr, _make_value) + return list(map(_make_value, self._ptr.getBasicBlockList())) def viewCFG(self): - return _core.LLVMViewFunctionCFG(self.ptr) + return self._ptr.viewCFG() def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self.ptr, attr) + self._ptr.addFnAttr(attr) def remove_attribute(self, attr): - _core.LLVMRemoveFunctionAttr(self.ptr, attr) + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + if llvm.version >= (3, 3): + attrs = api.llvm.Attribute.get(context, attrbldr) + else: + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeFnAttr(attrs) def viewCFGOnly(self): - return _core.LLVMViewFunctionCFGOnly(self.ptr) + return self._ptr.viewCFGOnly() def verify(self): # Although we're just asking LLVM to return the success or # failure, it appears to print result to stderr and abort. - return _core.LLVMVerifyFunction(self.ptr) != 0 + + # Note: LLVM has a bug in preverifier that will always abort + # the process upon failure. + actions = api.llvm.VerifierFailureAction + broken = api.llvm.verifyFunction(self._ptr, + actions.ReturnStatusAction) + if broken: + # If broken, then re-run to print the message + api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) + raise llvm.LLVMException("Function %s failed verification" % + self.name) + +#===----------------------------------------------------------------------=== +# InlineAsm +#===----------------------------------------------------------------------=== + +class InlineAsm(Value): + __slots__ = () + _type_ = api.llvm.InlineAsm + + @staticmethod + def get(functype, asm, constrains, side_effect=False, + align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): + ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, constrains, + side_effect, align_stack, dialect) + return _make_value(ilasm) #===----------------------------------------------------------------------=== # MetaData #===----------------------------------------------------------------------=== class MetaData(Value): + __slots__ = () + _type_ = api.llvm.MDNode + @staticmethod def get(module, values): ''' values -- must be an iterable of Constant or None. None is treated as "null". ''' - vs = unpack_values_or_none(values) - ptr = _core.LLVMMetaDataGet(module.ptr, vs) - return MetaData(ptr) + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDNode.get(context, llvm._extract_ptrs(values)) + return _make_value(ptr) @staticmethod def get_named_operands(module, name): - lst = _core.LLVMGetNamedMetadataOperands(module.ptr, name) - return [MetaData(ptr) for ptr in lst] + namedmd = module.get_named_metadata(name) + if not namedmd: + return [] + return [_make_value(namedmd._ptr.getOperand(i)) + for i in range(namedmd._ptr.getNumOperands())] @staticmethod def add_named_operand(module, name, operand): - _core.LLVMAddNamedMetadataOperand(module.ptr, name, operand.ptr) + namedmd = module.get_or_insert_named_metadata(name)._ptr + namedmd.addOperand(operand._ptr) @property def operand_count(self): - return _core.LLVMMetaDataGetNumOperands(self.ptr) + return self._ptr.getNumOperands() @property def operands(self): """Yields operands of this metadata.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - val = _core.LLVMMetaDataGetOperand(self.ptr, i) - if val: # metadata operands can be None - return _make_value(val) + res = [] + for i in range(self.operand_count): + op = self._ptr.getOperand(i) + if op is None: + res.append(None) + else: + res.append(_make_value(op)) + return res class MetaDataString(Value): + _type_ = api.llvm.MDString + @staticmethod def get(module, s): - ptr = _core.LLVMMetaDataStringGet(module.ptr, s) - return MetaDataString(ptr) + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDString.get(context, s) + return _make_value(ptr) @property def string(self): '''Same as MDString::getString''' - return self.name + return self._ptr.getString() + + +class NamedMetaData(llvm.Wrapper): + __slots__ = () + + @staticmethod + def get_or_insert(mod, name): + return mod.get_or_insert_named_metadata(name) + + @staticmethod + def get(mod, name): + return mod.get_named_metadata(name) + + def delete(self): + _ValueFactory.delete(self._ptr) + self._ptr.eraseFromParent() + + @property + def name(self): + return self._ptr.getName() + + def __str__(self): + return str(self._ptr) + + def add(self, operand): + self._ptr.addOperand(operand._ptr) + #===----------------------------------------------------------------------=== # Instruction #===----------------------------------------------------------------------=== class Instruction(User): + __slots__ = () + _type_ = api.llvm.Instruction @property def basic_block(self): - return _make_value(_core.LLVMGetInstructionParent(self.ptr)) + return _make_value(self._ptr.getParent()) @property def is_terminator(self): - return _core.LLVMInstIsTerminator(self.ptr) != 0 + return self._ptr.isTerminator() @property def is_binary_op(self): - return _core.LLVMInstIsBinaryOp(self.ptr) != 0 + return self._ptr.isBinaryOp() @property def is_shift(self): - return _core.LLVMInstIsShift(self.ptr) != 0 + return self._ptr.isShift() @property def is_cast(self): - return _core.LLVMInstIsCast(self.ptr) != 0 + return self._ptr.isCast() @property def is_logical_shift(self): - return _core.LLVMInstIsLogicalShift(self.ptr) != 0 + return self._ptr.isLogicalShift() @property def is_arithmetic_shift(self): - return _core.LLVMInstIsArithmeticShift(self.ptr) != 0 + return self._ptr.isArithmeticShift() @property def is_associative(self): - return _core.LLVMInstIsAssociative(self.ptr) != 0 + return self._ptr.isAssociative() @property def is_commutative(self): - return _core.LLVMInstIsCommutative(self.ptr) != 0 + return self._ptr.isCommutative() @property def is_volatile(self): """True if this is a volatile load or store.""" - return _core.LLVMInstIsVolatile(self.ptr) != 0 + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).isVolatile() + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).isVolatile() + else: + return False def set_volatile(self, flag): - return _core.LLVMSetVolatile(self.ptr, int(bool(flag))) + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).setVolatile(flag) + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).setVolatile(flag) + else: + return False def set_metadata(self, kind, metadata): - return _core.LLVMInstSetMetaData(self.ptr, kind, metadata.ptr) + self._ptr.setMetadata(kind, metadata._ptr) + + def has_metadata(self): + return self._ptr.hasMetadata() + + def get_metadata(self, kind): + return self._ptr.getMetadata(kind) @property def opcode(self): - return _core.LLVMInstGetOpcode(self.ptr) + return self._ptr.getOpcode() @property def opcode_name(self): - return _core.LLVMInstGetOpcodeName(self.ptr) + return self._ptr.getOpcodeName() + + def erase_from_parent(self): + return self._ptr.eraseFromParent() + + def replace_all_uses_with(self, inst): + self._ptr.replaceAllUsesWith(inst) class CallOrInvokeInstruction(Instruction): + __slots__ = () + _type_ = api.llvm.CallInst, api.llvm.InvokeInst + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + return self._ptr.setCallingConv(value) - def _get_cc(self): return _core.LLVMGetInstructionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value) calling_convention = property(_get_cc, _set_cc) def add_parameter_attribute(self, idx, attr): - _core.LLVMAddInstrAttribute(self.ptr, idx, attr) + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + if llvm.version >= (3, 3): + attrs = api.llvm.Attribute.get(context, attrbldr) + else: + attrs = api.llvm.Attributes.get(context, attrbldr) + + self._ptr.addAttribute(idx, attrs) def remove_parameter_attribute(self, idx, attr): - _core.LLVMRemoveInstrAttribute(self.ptr, idx, attr) + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAttribute(attr) + if llvm.version >= (3, 3): + attrs = api.llvm.Attribute.get(context, attrbldr) + else: + attrs = api.llvm.Attributes.get(context, attrbldr) + + self._ptr.removeAttribute(idx, attrs) def set_parameter_alignment(self, idx, align): - _core.LLVMSetInstrParamAlignment(self.ptr, idx, align) + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() + attrbldr.addAlignmentAttr(align) + if llvm.version >= (3, 3): + attrs = api.llvm.Attribute.get(context, attrbldr) + else: + attrs = api.llvm.Attributes.get(context, attrbldr) - @property - def called_function(self): - function = _core.LLVMInstGetCalledFunction(self.ptr) + self._ptr.addAttribute(idx, attrs) + + def _get_called_function(self): + function = self._ptr.getCalledFunction() if function: # Return value can be None on indirect call/invoke return _make_value(function) - # tail call is valid only for 'call', not 'invoke' - # disabled for now - #def _get_tc(self): return _core.LLVMIsTailCall(self.ptr) - #def _set_tc(self, value): _core.LLVMSetTailCall(self.ptr, value) - #tail_call = property(_get_tc, _set_tc) + def _set_called_function(self, function): + self._ptr.setCalledFunction(function._ptr) + + called_function = property(_get_called_function, _set_called_function) class PHINode(Instruction): + __slots__ = () + _type_ = api.llvm.PHINode @property def incoming_count(self): - return _core.LLVMCountIncoming(self.ptr) + return self._ptr.getNumIncomingValues() def add_incoming(self, value, block): - check_is_value(value) - check_is_basic_block(block) - _core.LLVMAddIncoming1(self.ptr, value.ptr, block.ptr) + self._ptr.addIncoming(value._ptr, block._ptr) def get_incoming_value(self, idx): - return _make_value(_core.LLVMGetIncomingValue(self.ptr, idx)) + return _make_value(self._ptr.getIncomingValue(idx)) def get_incoming_block(self, idx): - return _make_value(_core.LLVMGetIncomingBlock(self.ptr, idx)) + return _make_value(self._ptr.getIncomingBlock(idx)) class SwitchInstruction(Instruction): + __slots__ = () + _type_ = api.llvm.SwitchInst def add_case(self, const, bblk): - check_is_constant(const) # and has to be an int too - check_is_basic_block(bblk) - _core.LLVMAddCase(self.ptr, const.ptr, bblk.ptr) + self._ptr.addCase(const._ptr, bblk._ptr) class CompareInstruction(Instruction): + __slots__ = () + _type_ = api.llvm.CmpInst @property def predicate(self): - return _core.LLVMCmpInstGetPredicate(self.ptr) + n = self._ptr.getPredicate() + try: + return ICMPEnum.get(n) + except KeyError: + return FCMPEnum.get(n) +class AllocaInstruction(Instruction): + __slots__ = () + _type_ = api.llvm.AllocaInst + + @property + def alignment(self): + return self._ptr.getAlignment() + + @alignment.setter + def alignment(self, n): + self._ptr.setAlignment(n) + + @property + def array_size(self): + return self._ptr.getArraySize() + + @array_size.setter + def array_size(self, value): + return self._ptr.setArraySize(value._ptr)._ptr + + @property + def is_array(self): + return self._ptr.isArrayAllocation() + + @property + def is_static(self): + return self._ptr.isStaticAlloca() + #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== class BasicBlock(Value): + __slots__ = () + _type_ = api.llvm.BasicBlock def insert_before(self, name): - return _make_value(_core.LLVMInsertBasicBlock(self.ptr, name)) + context = api.llvm.getGlobalContext() + ptr = api.llvm.BasicBlock.Create(context, name, self.function._ptr, + self._ptr) + return _make_value(ptr) def delete(self): - _core.LLVMDeleteBasicBlock(self.ptr) - self.forget() - self.ptr = None + _ValueFactory.delete(self._ptr) + self._ptr.eraseFromParent() @property def function(self): - func_ptr = _core.LLVMGetBasicBlockParent(self.ptr) - return _make_value(func_ptr) + return _make_value(self._ptr.getParent()) @property def instructions(self): - return _util.wrapiter(_core.LLVMGetFirstInstruction, - _core.LLVMGetNextInstruction, self.ptr, _make_value) - + return list(map(_make_value, self._ptr.getInstList())) #===----------------------------------------------------------------------=== # Value factory method #===----------------------------------------------------------------------=== -# value ID -> class map -__class_for_valueid = { - VALUE_ARGUMENT : Argument, - VALUE_BASIC_BLOCK : BasicBlock, - VALUE_FUNCTION : Function, - VALUE_GLOBAL_ALIAS : GlobalValue, - VALUE_GLOBAL_VARIABLE : GlobalVariable, - VALUE_UNDEF_VALUE : UndefValue, - VALUE_CONSTANT_EXPR : ConstantExpr, - VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, - VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, - VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, - VALUE_CONSTANT_INT : ConstantInt, - VALUE_CONSTANT_FP : ConstantFP, - VALUE_CONSTANT_ARRAY : ConstantArray, - VALUE_CONSTANT_STRUCT : ConstantStruct, - VALUE_CONSTANT_VECTOR : ConstantVector, - VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, - VALUE_MD_NODE : MetaData, - VALUE_MD_STRING : MetaDataString, - VALUE_INSTRUCTION + OPCODE_PHI : PHINode, - VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, - VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, - VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction -} + +class _ValueFactory(object): + __slots__ = () + cache = weakref.WeakValueDictionary() + + # value ID -> class map + class_for_valueid = { + VALUE_ARGUMENT : Argument, + VALUE_BASIC_BLOCK : BasicBlock, + VALUE_FUNCTION : Function, + VALUE_GLOBAL_ALIAS : GlobalValue, + VALUE_GLOBAL_VARIABLE : GlobalVariable, + VALUE_UNDEF_VALUE : UndefValue, + VALUE_CONSTANT_EXPR : ConstantExpr, + VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, + VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, + VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, + VALUE_CONSTANT_INT : ConstantInt, + VALUE_CONSTANT_FP : ConstantFP, + VALUE_CONSTANT_ARRAY : ConstantArray, + VALUE_CONSTANT_STRUCT : ConstantStruct, + VALUE_CONSTANT_VECTOR : ConstantVector, + VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, + VALUE_MD_NODE : MetaData, + VALUE_MD_STRING : MetaDataString, + VALUE_INLINE_ASM : InlineAsm, + VALUE_INSTRUCTION + OPCODE_PHI : PHINode, + VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, + VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, + VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction, + VALUE_INSTRUCTION + OPCODE_ALLOCA : AllocaInstruction, + } + + @classmethod + def build(cls, ptr): + # try to look in the cache + addr = ptr._capsule.pointer + id = ptr.getValueID() + key = id, addr + try: + obj = cls.cache[key] + return obj + except KeyError: + pass + # find class by value id + ctorcls = cls.class_for_valueid.get(id) + if not ctorcls: + if id > VALUE_INSTRUCTION: # "generic" instruction + ctorcls = Instruction + else: # "generic" value + ctorcls = Value + # cache the obj + obj = ctorcls(_ValueFactory, ptr) + cls.cache[key] = obj + return obj + + @classmethod + def delete(cls, ptr): + del cls.cache[(ptr.getValueID(), ptr._capsule.pointer)] def _make_value(ptr): - kind = _core.LLVMValueGetID(ptr) - # based on kind, create one of the Value subclasses - class_obj = __class_for_valueid.get(kind) - if class_obj: - return class_obj(ptr) - elif kind > VALUE_INSTRUCTION: - # "generic" instruction - return Instruction(ptr) - else: - # "generic" value - return Value(ptr) - + return _ValueFactory.build(ptr) #===----------------------------------------------------------------------=== # Builder #===----------------------------------------------------------------------=== -class Builder(object): +_atomic_orderings = { + 'unordered' : api.llvm.AtomicOrdering.Unordered, + 'monotonic' : api.llvm.AtomicOrdering.Monotonic, + 'acquire' : api.llvm.AtomicOrdering.Acquire, + 'release' : api.llvm.AtomicOrdering.Release, + 'acq_rel' : api.llvm.AtomicOrdering.AcquireRelease, + 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent +} + +class Builder(llvm.Wrapper): + __slots__ = () @staticmethod def new(basic_block): - check_is_basic_block(basic_block) - b = Builder(_core.LLVMCreateBuilder()) - b.position_at_end(basic_block) - return b - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeBuilder(self.ptr) + context = api.llvm.getGlobalContext() + ptr = api.llvm.IRBuilder.new(context) + ptr.SetInsertPoint(basic_block._ptr) + return Builder(ptr) def position_at_beginning(self, bblk): """Position the builder at the beginning of the given block. Next instruction inserted will be first one in the block.""" - check_is_basic_block(bblk) - # Avoids using "blk.instructions", which will fetch all the - # instructions into a list. Don't try this at home, though. - inst_ptr = _core.LLVMGetFirstInstruction(bblk.ptr) - if inst_ptr: - # Issue #10: inst_ptr can be None if b/b has no insts. - inst = _make_value(inst_ptr) - self.position_before(inst) + + # Instruction list won't be long anyway, + # Does not matter much to build a list of all instructions + instrs = bblk.instructions + if instrs: + self.position_before(instrs[0]) + else: + self.position_at_end(bblk) def position_at_end(self, bblk): """Position the builder at the end of the given block. Next instruction inserted will be last one in the block.""" - _core.LLVMPositionBuilderAtEnd(self.ptr, bblk.ptr) + + self._ptr.SetInsertPoint(bblk._ptr) def position_before(self, instr): """Position the builder before the given instruction. - The instruction can belong to a basic block other than the - current one.""" - _core.LLVMPositionBuilderBefore(self.ptr, instr.ptr) - - @property - def block(self): - """Deprecated, use basic_block property instead.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) + The instruction can belong to a basic block other than the + current one.""" + self._ptr.SetInsertPoint(instr._ptr) @property def basic_block(self): """The basic block where the builder is positioned.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) + return _make_value(self._ptr.GetInsertBlock()) # terminator instructions + def _guard_terminators(self): + if __debug__: + import warnings + for instr in self.basic_block.instructions: + if instr.is_terminator: + warnings.warn("BasicBlock can only have one terminator") def ret_void(self): - return _make_value(_core.LLVMBuildRetVoid(self.ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateRetVoid()) def ret(self, value): - check_is_value(value) - return _make_value(_core.LLVMBuildRet(self.ptr, value.ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateRet(value._ptr)) def ret_many(self, values): - vs = unpack_values(values) - return _make_value(_core.LLVMBuildRetMultiple(self.ptr, vs)) + self._guard_terminators() + values = llvm._extract_ptrs(values) + return _make_value(self._ptr.CreateAggregateRet(values, len(values))) def branch(self, bblk): - check_is_basic_block(bblk) - return _make_value(_core.LLVMBuildBr(self.ptr, bblk.ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateBr(bblk._ptr)) def cbranch(self, if_value, then_blk, else_blk): - check_is_value(if_value) - check_is_basic_block(then_blk) - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildCondBr(self.ptr, - if_value.ptr, then_blk.ptr, else_blk.ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateCondBr(if_value._ptr, + then_blk._ptr, + else_blk._ptr)) def switch(self, value, else_blk, n=10): - check_is_value(value) # value has to be of any 'int' type - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildSwitch(self.ptr, value.ptr, else_blk.ptr, n)) + self._guard_terminators() + return _make_value(self._ptr.CreateSwitch(value._ptr, + else_blk._ptr, + n)) def invoke(self, func, args, then_blk, catch_blk, name=""): - check_is_callable(func) - check_is_basic_block(then_blk) - check_is_basic_block(catch_blk) - args2 = unpack_values(args) - return _make_value( - _core.LLVMBuildInvoke(self.ptr, func.ptr, args2, - then_blk.ptr, catch_blk.ptr, name)) + self._guard_terminators() + return _make_value(self._ptr.CreateInvoke(func._ptr, + then_blk._ptr, + catch_blk._ptr, + llvm._extract_ptrs(args))) def unreachable(self): - return _make_value(_core.LLVMBuildUnreachable(self.ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateUnreachable()) # arithmethic, bitwise and logical - def add(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildAdd(self.ptr, lhs.ptr, rhs.ptr, name)) + def add(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fadd(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFAdd(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) - def sub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildSub(self.ptr, lhs.ptr, rhs.ptr, name)) + def sub(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fsub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFSub(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) - def mul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildMul(self.ptr, lhs.ptr, rhs.ptr, name)) + def mul(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name, + nuw, nsw)) def fmul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFMul(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) - def udiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildUDiv(self.ptr, lhs.ptr, rhs.ptr, name)) + def udiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name, + exact)) - def sdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSDiv(self.ptr, lhs.ptr, rhs.ptr, name)) + def sdiv(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name, + exact)) def fdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFDiv(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) def urem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildURem(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) def srem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSRem(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) def frem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFRem(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) - def shl(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildShl(self.ptr, lhs.ptr, rhs.ptr, name)) + def shl(self, lhs, rhs, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name, + nuw, nsw)) - def lshr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildLShr(self.ptr, lhs.ptr, rhs.ptr, name)) + def lshr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name, + exact)) - def ashr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAShr(self.ptr, lhs.ptr, rhs.ptr, name)) + def ashr(self, lhs, rhs, name="", exact=False): + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name, + exact)) def and_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAnd(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) def or_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildOr(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) def xor(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildXor(self.ptr, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) - def neg(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNeg(self.ptr, val.ptr, name)) + def neg(self, val, name="", nuw=False, nsw=False): + return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw)) def not_(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNot(self.ptr, val.ptr, name)) + return _make_value(self._ptr.CreateNot(val._ptr, name)) # memory def malloc(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildMalloc(self.ptr, ty.ptr, name)) + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + None, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) def malloc_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayMalloc(self.ptr, ty.ptr, size.ptr, name)) + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + size._ptr, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) - def alloca(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildAlloca(self.ptr, ty.ptr, name)) + def alloca(self, ty, size=None, name=""): + sizeptr = size._ptr if size else None + return _make_value(self._ptr.CreateAlloca(ty._ptr, sizeptr, name)) + @deprecated def alloca_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayAlloca(self.ptr, ty.ptr, size.ptr, name)) + return self.alloca(ty, size, name=name) def free(self, ptr): - check_is_value(ptr) - return _make_value(_core.LLVMBuildFree(self.ptr, ptr.ptr)) + free = api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr) + inst = self._ptr.Insert(free) + return _make_value(inst) def load(self, ptr, name="", align=0, volatile=False, invariant=False): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name)) + inst = _make_value(self._ptr.CreateLoad(ptr._ptr, name)) if align: - _core.LLVMLdSetAlignment(inst.ptr, align) + inst._ptr.setAlignment(align) if volatile: inst.set_volatile(volatile) if invariant: @@ -1966,195 +2327,141 @@ class Builder(object): return inst def store(self, value, ptr, align=0, volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr)) + inst = _make_value(self._ptr.CreateStore(value._ptr, ptr._ptr)) if align: - _core.LLVMStSetAlignment(inst.ptr, align) + inst._ptr.setAlignment(align) if volatile: inst.set_volatile(volatile) return inst - def gep(self, ptr, indices, name=""): - check_is_value(ptr) - index_ptrs = unpack_values(indices) - return _make_value( - _core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name)) + def gep(self, ptr, indices, name="", inbounds=False): + if inbounds: + ret = self._ptr.CreateInBoundsGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + else: + ret = self._ptr.CreateGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + return _make_value(ret) # casts and extensions def trunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) def zext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildZExt(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateZExt(value._ptr, dest_ty._ptr, name)) def sext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSExt(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateSExt(value._ptr, dest_ty._ptr, name)) def fptoui(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToUI(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) def fptosi(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToSI(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) def uitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildUIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) def sitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) def fptrunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) def fpext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPExt(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) def ptrtoint(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildPtrToInt(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) def inttoptr(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildIntToPtr(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) def bitcast(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildBitCast(self.ptr, value.ptr, dest_ty.ptr, name)) + return _make_value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) # comparisons def icmp(self, ipred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildICmp(self.ptr, ipred, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) def fcmp(self, rpred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFCmp(self.ptr, rpred, lhs.ptr, rhs.ptr, name)) + return _make_value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) # misc def extract_value(self, retval, idx, name=""): - check_is_value(retval) - return _make_value( - _core.LLVMBuildGetResult(self.ptr, retval.ptr, idx, name)) + if not isinstance(idx, (tuple, list)): + idx = [idx] + return _make_value(self._ptr.CreateExtractValue(retval._ptr, idx, + name)) # obsolete synonym for extract_value getresult = extract_value def insert_value(self, retval, rhs, idx, name=""): - check_is_value(retval) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildInsertValue(self.ptr, retval.ptr, rhs.ptr, idx, - name)) + if not isinstance(idx, (tuple, list)): + idx = [idx] + return _make_value(self._ptr.CreateInsertValue(retval._ptr, + rhs._ptr, + idx, + name)) def phi(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildPhi(self.ptr, ty.ptr, name)) + return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) def call(self, fn, args, name=""): - check_is_callable(fn) - err_template = 'Argument type mismatch: expected %s but got %s' + for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): if t != v.type: raise TypeError(err_template % (t, v.type)) - arg_ptrs = unpack_values(args) - return _make_value( - _core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name)) + arg_ptrs = llvm._extract_ptrs(args) + return _make_value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) def select(self, cond, then_value, else_value, name=""): - check_is_value(cond) - check_is_value(then_value) - check_is_value(else_value) - return _make_value( - _core.LLVMBuildSelect(self.ptr, cond.ptr, - then_value.ptr, else_value.ptr, name)) + return _make_value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, + else_value._ptr, name)) def vaarg(self, list_val, ty, name=""): - check_is_value(list_val) - check_is_type(ty) - return _make_value( - _core.LLVMBuildVAArg(self.ptr, list_val.ptr, ty.ptr, name)) + return _make_value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) def extract_element(self, vec_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildExtractElement(self.ptr, vec_val.ptr, - idx_val.ptr, name)) + return _make_value(self._ptr.CreateExtractElement(vec_val._ptr, + idx_val._ptr, + name)) + def insert_element(self, vec_val, elt_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(elt_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildInsertElement(self.ptr, vec_val.ptr, - elt_val.ptr, idx_val.ptr, name)) + return _make_value(self._ptr.CreateInsertElement(vec_val._ptr, + elt_val._ptr, + idx_val._ptr, + name)) def shuffle_vector(self, vecA, vecB, mask, name=""): - check_is_value(vecA) - check_is_value(vecB) - check_is_value(mask) - return _make_value( - _core.LLVMBuildShuffleVector(self.ptr, - vecA.ptr, vecB.ptr, mask.ptr, name)) - + return _make_value(self._ptr.CreateShuffleVector(vecA._ptr, + vecB._ptr, + mask._ptr, + name)) # atomics def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(old) - check_is_value(new) - inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr, - ordering.lower(), - int(bool(crossthread))) - return _make_value(inst) + return _make_value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, + old._ptr, + new._ptr, + _atomic_orderings[ordering], + _sync_scope(crossthread))) def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(val) - inst = _core.LLVMBuildAtomicRMW(self.ptr, op.lower(), ptr.ptr, val.ptr, - ordering.lower(), int(bool(crossthread))) - return _make_value(inst) + op_dict = dict((k.lower(), v) + for k, v in vars(api.llvm.AtomicRMWInst.BinOp).items()) + op = op_dict[op] + return _make_value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, + _atomic_orderings[ordering], + _sync_scope(crossthread))) def atomic_xchg(self, *args, **kwargs): return self.atomic_rmw('xchg', *args, **kwargs) @@ -2189,69 +2496,31 @@ class Builder(object): def atomic_umin(self, *args, **kwargs): return self.atomic_rmw('umin', *args, **kwargs) - def atomic_load(self, ptr, ordering, align=1, crossthread=True, volatile=False, name=""): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicLoad( - self.ptr, ptr.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) - if inst: - inst.name = name + inst = self.load(ptr, align=align, volatile=volatile, name=name) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicStore( - self.ptr, ptr.ptr, value.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) + inst = self.store(value, ptr, align=align, volatile=volatile) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst + def fence(self, ordering, crossthread=True): - inst = _make_value(_core.LLVMBuildFence(self.ptr, ordering.lower(), - int(bool(crossthread)))) - return inst + return _make_value(self._ptr.CreateFence(_atomic_orderings[ordering], + _sync_scope(crossthread))) -#===----------------------------------------------------------------------=== -# Memory buffer -#===----------------------------------------------------------------------=== - -class MemoryBuffer(object): - - @staticmethod - def from_file(fname): - ret = _core.LLVMCreateMemoryBufferWithContentsOfFile(fname) - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - @staticmethod - def from_stdin(): - ret = _core.LLVMCreateMemoryBufferWithSTDIN() - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeMemoryBuffer(self.ptr) - - -#===----------------------------------------------------------------------=== -# Misc -#===----------------------------------------------------------------------=== +def _sync_scope(crossthread): + if crossthread: + scope = api.llvm.SynchronizationScope.CrossThread + else: + scope = api.llvm.SynchronizationScope.SingleThread + return scope def load_library_permanently(filename): """Load a shared library. @@ -2259,45 +2528,27 @@ def load_library_permanently(filename): Load the given shared library (filename argument specifies the full path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" - - ret = _core.LLVMLoadLibraryPermanently(filename) - if isinstance(ret, str): - raise llvm.LLVMException(ret) + with contextlib.closing(BytesIO()) as errmsg: + failed = api.llvm.sys.DynamicLibrary.LoadPermanentLibrary(filename, + errmsg) + if failed: + raise llvm.LLVMException(errmsg.getvalue()) def inline_function(call): - check_is_value(call) - return bool(_core.LLVMInlineFunction(call.ptr)) + info = api.llvm.InlineFunctionInfo.new() + return api.llvm.InlineFunction(call._ptr, info) def parse_environment_options(progname, envname): - _core.LLVMParseEnvOpts(progname, envname) + api.llvm.cl.ParseEnvironmentOptions(progname, envname) -#===----------------------------------------------------------------------=== -# Initialization -#===----------------------------------------------------------------------=== -if _core.LLVMInitializeNativeTarget(): +if api.llvm.InitializeNativeTarget(): raise llvm.LLVMException("No native target!?") -if _core.LLVMInitializeNativeTargetAsmPrinter(): +if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") - - -HAS_PTX = HAS_NVPTX = False -if True: # use PTX? - try: - _core.LLVMInitializePTXTarget() - _core.LLVMInitializePTXTargetInfo() - _core.LLVMInitializePTXTargetMC() - _core.LLVMInitializePTXAsmPrinter() - HAS_PTX = True - except AttributeError: - try: - _core.LLVMInitializeNVPTXTarget() - _core.LLVMInitializeNVPTXTargetInfo() - _core.LLVMInitializeNVPTXTargetMC() - _core.LLVMInitializeNVPTXAsmPrinter() - HAS_NVPTX = True - except AttributeError: - pass - - +if api.llvm.InitializeNativeTargetAsmParser(): + # required by MCJIT? + # should this be an optional feature? + # should user trigger the initialization? + raise llvm.LLVMException("No native asm parser!?") diff --git a/llvm/deprecated.py b/llvm/deprecated.py new file mode 100644 index 0000000..6db5fe7 --- /dev/null +++ b/llvm/deprecated.py @@ -0,0 +1,25 @@ +""" +Shameless borrowed from Smart_deprecation_warnings +https://wiki.python.org/moin/PythonDecoratorLibrary +""" + +import warnings +import functools + + +def deprecated(func): + """This is a decorator which can be used to mark functions + as deprecated. It will result in a warning being emitted + when the function is used.""" + + @functools.wraps(func) + def new_func(*args, **kwargs): + warnings.warn_explicit( + "Call to deprecated function %s." % (func.__name__,), + category=DeprecationWarning, + filename=func.func_code.co_filename, + lineno=func.func_code.co_firstlineno + 1 + ) + return func(*args, **kwargs) + + return new_func diff --git a/llvm/ee.py b/llvm/ee.py index a23aaf4..f615b61 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -28,122 +28,54 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -"""Execution Engine and related classes. +"Execution Engine and related classes." -""" +import sys -import llvm # top-level, for common stuff -import llvm.core as core # module, function etc. -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions -import logging - -logger = logging.getLogger(__name__) +import llvm +from llvm import core +from llvm.passes import TargetData, TargetTransformInfo +from llvmpy import api, extra #===----------------------------------------------------------------------=== -# Enumerations +# import items which were moved to target module #===----------------------------------------------------------------------=== - -BO_BIG_ENDIAN = 0 -BO_LITTLE_ENDIAN = 1 - - -#===----------------------------------------------------------------------=== -# Target data -#===----------------------------------------------------------------------=== - -class TargetData(llvm.Ownable): - - @staticmethod - def new(strrep): - return TargetData(_core.LLVMCreateTargetData(strrep)) - - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetData) - - def __str__(self): - return _core.LLVMTargetDataAsString(self.ptr) - - @property - def byte_order(self): - return _core.LLVMByteOrder(self.ptr) - - @property - def pointer_size(self): - return _core.LLVMPointerSize(self.ptr) - - @property - def target_integer_type(self): - ptr = _core.LLVMIntPtrType(self.ptr); - return core.IntegerType(ptr, core.TYPE_INTEGER) - - def size(self, ty): - core.check_is_type(ty) - return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr) - - def store_size(self, ty): - core.check_is_type(ty) - return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr) - - def abi_size(self, ty): - core.check_is_type(ty) - return _core.LLVMABISizeOfType(self.ptr, ty.ptr) - - def abi_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr) - - def callframe_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr) - - def preferred_alignment(self, ty_or_gv): - if isinstance(ty_or_gv, core.Type): - return _core.LLVMPreferredAlignmentOfType(self.ptr, - ty_or_gv.ptr) - elif isinstance(ty_or_gv, core.GlobalVariable): - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: - raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) - ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): - core.check_is_type_struct(ty) - el = int(el) # el should be an int - return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el) +from llvm.target import (initialize_all, initialize_target, + print_registered_targets, get_host_cpu_name, get_default_triple, + TargetMachine, + BO_BIG_ENDIAN, BO_LITTLE_ENDIAN, + CM_DEFAULT, CM_JITDEFAULT, CM_SMALL, CM_KERNEL, CM_MEDIUM, CM_LARGE, + RELOC_DEFAULT, RELOC_STATIC, RELOC_PIC, RELOC_DYNAMIC_NO_PIC) #===----------------------------------------------------------------------=== # Generic value #===----------------------------------------------------------------------=== -class GenericValue(object): +class GenericValue(llvm.Wrapper): @staticmethod def int(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 0) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False) return GenericValue(ptr) @staticmethod def int_signed(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 1) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True) return GenericValue(ptr) @staticmethod def real(ty, floatval): - core.check_is_type(ty) # only float or double - ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval) + if str(ty) == 'float': + ptr = api.llvm.GenericValue.CreateFloat(float(floatval)) + elif str(ty) == 'double': + ptr = api.llvm.GenericValue.CreateDouble(float(floatval)) + else: + raise Exception('Unreachable') return GenericValue(ptr) @staticmethod - def pointer(*args): + def pointer(addr): ''' One argument version takes (addr). Two argument version takes (ty, addr). [Deprecated] @@ -151,78 +83,46 @@ class GenericValue(object): `ty` is unused. `addr` is an integer representing an address. - TODO: remove two argument version. ''' - if len(args)==2: - logger.warning("Deprecated: Two argument version of " - "GenericValue.pointer() is deprecated.") - addr = args[1] - elif len(args)!=1: - raise TypeError("pointer() takes 1 or 2 arguments.") - else: - addr = args[0] - ptr = _core.LLVMCreateGenericValueOfPointer(addr) + ptr = api.llvm.GenericValue.CreatePointer(int(addr)) return GenericValue(ptr) - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeGenericValue(self.ptr) - def as_int(self): - return _core.LLVMGenericValueToInt(self.ptr, 0) + return self._ptr.toUnsignedInt() def as_int_signed(self): - return _core.LLVMGenericValueToInt(self.ptr, 1) + return self._ptr.toSignedInt() def as_real(self, ty): - core.check_is_type(ty) # only float or double - return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr) + return self._ptr.toFloat(ty._ptr) def as_pointer(self): - return _core.LLVMGenericValueToPointer(self.ptr) - - -# helper functions for generic value objects -def check_is_generic_value(obj): _util.check_gen(obj, GenericValue) -def _unpack_generic_values(objlist): - return _util.unpack_gen(objlist, check_is_generic_value) - + return self._ptr.toPointer() #===----------------------------------------------------------------------=== # Engine builder #===----------------------------------------------------------------------=== -class EngineBuilder(object): +class EngineBuilder(llvm.Wrapper): @staticmethod def new(module): - core.check_is_module(module) - _util.check_is_unowned(module) - obj = _core.LLVMCreateEngineBuilder(module.ptr) - return EngineBuilder(obj, module) - - def __init__(self, ptr, module): - self.ptr = ptr - self._module = module - - def __del__(self): - _core.LLVMDisposeEngineBuilder(self.ptr) + ptr = api.llvm.EngineBuilder.new(module._ptr) + return EngineBuilder(ptr) def force_jit(self): - _core.LLVMEngineBuilderForceJIT(self.ptr) + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT) return self def force_interpreter(self): - _core.LLVMEngineBuilderForceInterpreter(self.ptr) + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter) return self def opt(self, level): ''' level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] ''' - assert level in range(4) - _core.LLVMEngineBuilderSetOptLevel(self.ptr, level) + assert 0 <= level <= 3 + self._ptr.setOptLevel(level) return self def mattrs(self, string): @@ -230,156 +130,135 @@ class EngineBuilder(object): e.g: +sse,-3dnow ''' - _core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' ')) + self._ptr.setMAttrs(string.split(',')) return self - def create(self): - ret = _core.LLVMEngineBuilderCreate(self.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - return ExecutionEngine(ret, self._module) - - def select_target(self): - '''get the corresponding target machine + def create(self, tm=None): ''' - ptr = _core.LLVMTargetMachineFromEngineBuilder(self.ptr) + tm --- Optional. Provide a TargetMachine. Ownership is transfered + to the returned execution engine. + ''' + if tm is not None: + engine = self._ptr.create(tm._ptr) + elif (sys.platform.startswith('win32') and + getattr(self, '_use_mcjit', False)): + # force ELF generation on MCJIT on win32 + triple = get_default_triple() + tm = TargetMachine.new('%s-elf' % triple) + engine = self._ptr.create(tm._ptr) + else: + engine = self._ptr.create() + ee = ExecutionEngine(engine) + ee.finalize_object() # no effect for legacy JIT + return ee + + def select_target(self, *args): + '''get the corresponding target machine + + Accept no arguments or (triple, march, mcpu, mattrs) + ''' + if args: + triple, march, mcpu, mattrs = args + ptr = self._ptr.selectTarget(triple, march, mcpu, + mattrs.split(',')) + else: + ptr = self._ptr.selectTarget() return TargetMachine(ptr) + def mcjit(self, enable): + '''Enable/disable MCJIT + ''' + self._ptr.setUseMCJIT(enable) + self._use_mcjit = True + return self + #===----------------------------------------------------------------------=== # Execution engine #===----------------------------------------------------------------------=== -class ExecutionEngine(object): +class ExecutionEngine(llvm.Wrapper): @staticmethod def new(module, force_interpreter=False): - core.check_is_module(module) - _util.check_is_unowned(module) - ret = _core.LLVMCreateExecutionEngine(module.ptr, int(force_interpreter)) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - return ExecutionEngine(ret, module) + eb = EngineBuilder.new(module) + if force_interpreter: + eb.force_interpreter() + return eb.create() - def __init__(self, ptr, module): - self.ptr = ptr - module._own(self) - - def __del__(self): - _core.LLVMDisposeExecutionEngine(self.ptr) + def disable_lazy_compilation(self, disabled=True): + self._ptr.DisableLazyCompilation(disabled) def run_function(self, fn, args): - core.check_is_function(fn) - ptrs = _unpack_generic_values(args) - gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs) - return GenericValue(gvptr) + ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args))) + return GenericValue(ptr) + + def get_pointer_to_named_function(self, name, abort=True): + return self._ptr.getPointerToNamedFunction(name, abort) def get_pointer_to_function(self, fn): - core.check_is_function(fn) - return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr) + return self._ptr.getPointerToFunction(fn._ptr) + + def get_pointer_to_global(self, val): + return self._ptr.getPointerToGlobal(val._ptr) + + def add_global_mapping(self, gvar, addr): + assert addr >= 0, "Address cannot not be negative" + self._ptr.addGlobalMapping(gvar._ptr, addr) def run_static_ctors(self): - _core.LLVMRunStaticConstructors(self.ptr) + self._ptr.runStaticConstructorsDestructors(False) def run_static_dtors(self): - _core.LLVMRunStaticDestructors(self.ptr) + self._ptr.runStaticConstructorsDestructors(True) def free_machine_code_for(self, fn): - core.check_is_function(fn) - _core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr) + self._ptr.freeMachineCodeForFunction(fn._ptr) def add_module(self, module): - core.check_is_module(module) - _core.LLVMAddModule(self.ptr, module.ptr) - module._own(self) + self._ptr.addModule(module._ptr) def remove_module(self, module): - core.check_is_module(module) - if module.owner != self: - raise llvm.LLVMException("module is not owned by self") - ret = _core.LLVMRemoveModule2(self.ptr, module.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - return core.Module(ret) + return self._ptr.removeModule(module._ptr) + + def finalize_object(self): + return self._ptr.finalizeObject() @property def target_data(self): - td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr)) - td._own(self) - return td - - -#===----------------------------------------------------------------------=== -# Target machine -#===----------------------------------------------------------------------=== - -def print_registered_targets(): - ''' - Note: print directly to stdout - ''' - _core.LLVMPrintRegisteredTargetsForVersion() - -def get_host_cpu_name(): - '''return the string name of the host CPU - ''' - return _core.LLVMGetHostCPUName() - -class TargetMachine(object): - - @staticmethod - def lookup(arch, cpu='', features='', opt=2): - '''create a targetmachine given an architecture name - - For a list of architectures, - use: `llc -help` - - For a list of available CPUs, - use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help` - - For a list of available attributes (features), - use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` - ''' - ptr = _core.LLVMTargetMachineLookup(arch, cpu, features, opt) - return TargetMachine(ptr) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeTargetMachine(self.ptr) - - def emit_assembly(self, module): - '''returns byte string of the module as assembly code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, True) - - def emit_object(self, module): - '''returns byte string of the module as native code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, False) - - @property - def target_data(self): - '''get target data of this machine - ''' - ptr = _core.LLVMTargetMachineGetTargetData(self.ptr) + ptr = self._ptr.getDataLayout() return TargetData(ptr) - @property - def target_name(self): - return _core.LLVMTargetMachineGetTargetName(self.ptr) - @property - def target_short_description(self): - return _core.LLVMTargetMachineGetTargetShortDescription(self.ptr) +#===----------------------------------------------------------------------=== +# Dynamic Library +#===----------------------------------------------------------------------=== - @property - def triple(self): - return _core.LLVMTargetMachineGetTriple(self.ptr) +def dylib_add_symbol(name, ptr): + api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr) - @property - def cpu(self): - return _core.LLVMTargetMachineGetCPU(self.ptr) +def dylib_address_of_symbol(name): + return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name) - @property - def feature_string(self): - return _core.LLVMTargetMachineGetFS(self.ptr) +def dylib_import_library(filename): + """Permanently import a dynamic library. + + Returns a DynamicLibrary object + + Raises RuntimeError + """ + return DynamicLibrary(filename) + + +class DynamicLibrary(object): + def __init__(self, filename): + """ + Raises RuntimeError + """ + self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary( + filename) + + def get_address_of_symbol(self, symbol): + """ + Get the address of `symbol` (str) as integer + """ + return self._ptr.getAddressOfSymbol(symbol) diff --git a/llvm/extra.cpp b/llvm/extra.cpp deleted file mode 100644 index 537eae2..0000000 --- a/llvm/extra.cpp +++ /dev/null @@ -1,1155 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -// standard includes -#include -#include -#include -#include -#include - -// LLVM includes -#include "llvm/LLVMContext.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Casting.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalVariable.h" -//#include "llvm/TypeSymbolTable.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Host.h" - -#include "llvm/IntrinsicInst.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/PassManager.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/DomPrinter.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Linker.h" -#include "llvm/Support/SourceMgr.h" - -// LLVM-C includes -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" - -// our includes -#include "extra.h" -#include "llvm_c_extra.h" - -namespace llvm{ -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) - -template -inline T **unwrap(LLVMTypeRef *Tys, unsigned Length) { - (void)Length; - return reinterpret_cast(Tys); -} - -} - -/* - * For use in LLVMDumpPasses to dump passes. - */ -class PassRegistryPrinter : public llvm::PassRegistrationListener{ -public: - std::ostringstream stringstream; - - void passEnumerate(const llvm::PassInfo * pass_info){ - stringstream << pass_info->getPassArgument() - << "\t" - << pass_info->getPassName() - << "\n"; - } -}; - - -/* Helper method for LLVMDumpXXXToString() methods. */ -template -char *do_print(W obj) -{ - std::string s; - llvm::raw_string_ostream buf(s); - UW *p = llvm::unwrap(obj); - assert(p); - p->print(buf); - return strdup(buf.str().c_str()); -} - -namespace { -using namespace llvm; -const CodeGenOpt::Level OptLevelMap[] = { - CodeGenOpt::None, - CodeGenOpt::Less, - CodeGenOpt::Default, - CodeGenOpt::Aggressive, -}; -} // end anony namespace - - -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref) -{ - using namespace llvm; - unwrap(instref)->setMetadata(mdkind, unwrap(metaref)); -} - -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct) -{ - using namespace llvm; - LLVMContext & context = unwrap(modref)->getContext(); - MDNode * const node = MDNode::get( - context, - makeArrayRef(unwrap(valrefs, valct), valct)); - return wrap(node); -} - -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index) -{ - return wrap(llvm::unwrap(mdref)->getOperand(index)); -} - -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref) -{ - return llvm::unwrap(mdref)->getNumOperands(); -} - -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s) -{ - LLVMContext & context = unwrap(modref)->getContext(); - MDString * const mdstring = MDString::get(context, s); - return wrap(mdstring); -} - -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcodeName(); -} - -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcode(); -} - -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -const char * LLVMGetHostCPUName() -{ - return strdup(llvm::sys::getHostCPUName().c_str()); -} - -const char * LLVMGetHostCPUFeatures() -{ - // placeholder - // TODO not implemented even in LLVM3.2svn - // llvm::sys::getHostCPUFeatures - return NULL; -} - -int LLVMInitializeNativeTargetAsmPrinter() -{ - return llvm::InitializeNativeTargetAsmPrinter(); -} - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - std::string &error) -{ - using namespace llvm; - Triple TheTriple; - - // begin borrow from LLVM 3.2 code - // because we don't have 3 argument version of lookup() in 3.1 - const Target * TheTarget = NULL; - - const std::string ArchName(arch); - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - if (ArchName == it->getName()) { - TheTarget = &*it; - break; - } - } - - if (!TheTarget) { - error = "Unknown arch"; - return NULL; - } - - Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); - - if (Type != Triple::UnknownArch){ - TheTriple.setArch(Type); - } - // end borrow from LLVM 3.2 code - - if (!TheTarget->hasTargetMachine()){ - error = "No target machine for the arch"; - return NULL; - } - - TargetOptions no_target_options; - TargetMachine * tm = TheTarget->createTargetMachine( - TheTriple.str(), cpu, features, - no_target_options, - Reloc::Default, CodeModel::Default, - OptLevelMap[opt]); - - if (!tm){ - error = "Cannot create target machine"; - return NULL; - } - return wrap(tm); -} - - -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - TargetMachine * tm = unwrap(eb)->selectTarget(); - return wrap(tm); -} - -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm){ - delete llvm::unwrap(tm); -} - - -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(modref); - assert(modulep); - - // get objectcode into a string - std::string s; - raw_string_ostream buf(s); - - formatted_raw_ostream fso(buf); - - TargetMachine * tm = unwrap(tmref); - - PassManager pm; - - if (!tm->getTargetData()){ - error = "No target data in target machine"; - return NULL; - } - - pm.add(new TargetData(*tm->getTargetData())); - - bool failed; - if( assembly ) { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_AssemblyFile); - } else { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_ObjectFile); - } - - if ( failed ) { - error = "No support for emit file"; - return NULL; - } - - pm.run(*modulep); - - // flush all streams - fso.flush(); - buf.flush(); - - const std::string& bc = buf.str(); - - // and then into a new buffer - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getName()); -} - -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getShortDescription()); -} - -const char* LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetTriple().str().c_str()); -} - -const char* LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetCPU().str().c_str()); -} - -const char* LLVMTargetMachineGetFS(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetFeatureString().str().c_str()); -} - -void LLVMPrintRegisteredTargetsForVersion(){ - llvm::TargetRegistry::printRegisteredTargetsForVersion(); -} - - - -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm) -{ - using namespace llvm; - return wrap(new TargetData(*unwrap(tm)->getTargetData())); -} - -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(module); - assert(modulep); - - // select native default machine - TargetMachine * tm = EngineBuilder(modulep).selectTarget(); - - return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp, error); -} - -static -llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering) -{ - using namespace llvm; - - if ( strcmp(ordering, "unordered") == 0 ) - return Unordered; - else if ( strcmp(ordering, "monotonic") == 0 ) - return Monotonic; - else if ( strcmp(ordering, "acquire") == 0 ) - return Acquire; - else if ( strcmp(ordering, "release") == 0 ) - return Release; - else if ( strcmp(ordering, "acq_rel") == 0 ) - return AcquireRelease; - else if ( strcmp(ordering, "seq_cst") == 0 ) - return SequentiallyConsistent; - else - return NotAtomic; -} - -static -llvm::SynchronizationScope sync_scope_from_int(int crossthread) -{ - if( crossthread ) - return llvm::CrossThread; - else - return llvm::SingleThread; -} - -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateFence(atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicRMWInst::BinOp op; - - if( strcmp(opname, "xchg") == 0 ) - op = AtomicRMWInst::Xchg; - else if( strcmp(opname, "add") == 0 ) - op = AtomicRMWInst::Add; - else if( strcmp(opname, "sub") == 0 ) - op = AtomicRMWInst::Sub; - else if( strcmp(opname, "and") == 0 ) - op = AtomicRMWInst::And; - else if( strcmp(opname, "nand") == 0 ) - op = AtomicRMWInst::Nand; - else if( strcmp(opname, "or") == 0 ) - op = AtomicRMWInst::Or; - else if( strcmp(opname, "xor") == 0 ) - op = AtomicRMWInst::Xor; - else if( strcmp(opname, "max") == 0 ) - op = AtomicRMWInst::Max; - else if( strcmp(opname, "min") == 0 ) - op = AtomicRMWInst::Min; - else if( strcmp(opname, "umax") == 0 ) - op = AtomicRMWInst::UMax; - else if( strcmp(opname, "umin") == 0 ) - op = AtomicRMWInst::UMin; - else - op = AtomicRMWInst::BAD_BINOP; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicRMW(op, unwrap(ptr), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - LoadInst * inst = unwrap(builder)->CreateLoad(unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicCmpXchg( - unwrap(ptr), unwrap(cmp), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod) -{ - return llvm::wrap(new EngineBuilder(unwrap(mod))); -} - -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb) -{ - delete llvm::unwrap(eb); -} - -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::JIT); -} - -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::Interpreter); -} - -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level) -{ - unwrap(eb)->setOptLevel(OptLevelMap[level]); -} - -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu) -{ // TODO add test when llvm3.2 releases - unwrap(eb)->setMCPU(mcpu); // does not work in llvm3.1 -} - -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs) -{ // TODO add test when llvm3.2 releases - std::vector tokenized; - std::istringstream iss(mattrs); - std::string buf; - while ( iss >> buf ){ - tokenized.push_back(buf); - } - unwrap(eb)->setMAttrs(tokenized); // does not work in llvm3.1 -} - -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, std::string & error) -{ - using namespace llvm; - LLVMExecutionEngineRef ret; - - ret = wrap(unwrap(eb)->setErrorStr(&error).create()); - - if ( !error.empty() ) { // error string is set - return NULL; - } else { - return ret; - } -} - -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->OptLevel; -} - -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->SizeLevel; -} - -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag) -{ - llvm::unwrap(pmb)->Vectorize = flag; -} - -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb){ - return llvm::unwrap(pmb)->Vectorize; -} - -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnitAtATime; -} - -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnrollLoops; -} - -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableSimplifyLibCalls; -} - - -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name) -{ - using namespace llvm; - const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); - if (pi){ - unwrap(pm)->add(pi->createPass()); - return 1; // success - } else { - return 0; // fail -- cannot find pass - } -} - -void LLVMInitializePasses(){ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - initializeCore(registry); - initializeScalarOpts(registry); - initializeVectorization(registry); - initializeIPO(registry); - initializeAnalysis(registry); - initializeIPA(registry); - initializeTransformUtils(registry); - initializeInstCombine(registry); - initializeInstrumentation(registry); - initializeTarget(registry); -} - -const char * LLVMDumpPasses() -{ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - PassRegistryPrinter prp; - registry.enumerateWith(&prp); - return strdup(prp.stringstream.str().c_str()); -} - - -int LLVMIsLiteralStruct(LLVMTypeRef type) -{ - return llvm::unwrap(type)->isLiteral(); -} - -LLVMTypeRef LLVMStructTypeIdentified(const char * name) -{ - using namespace llvm; - return wrap(StructType::create(getGlobalContext(), name)); -} - -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, - unsigned elemct, int is_packed) -{ - using namespace llvm; - ArrayRef elemtys_aryref(unwrap(elemtys), elemct); - unwrap(type)->setBody(elemtys_aryref, is_packed); -} - -void LLVMSetStructName(LLVMTypeRef type, const char * name) -{ - llvm::StructType *st = llvm::unwrap(type); - st->setName(name); -} - -char *LLVMGetModuleIdentifier(LLVMModuleRef module) -{ - return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str()); -} - -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name) -{ - llvm::unwrap(module)->setModuleIdentifier(name); -} - -char *LLVMDumpModuleToString(LLVMModuleRef module) -{ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::Module *p = llvm::unwrap(module); - assert(p); - p->print(buf, NULL); - return strdup(buf.str().c_str()); -} - -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name) -{ - llvm::Module *M = llvm::unwrap(module); - llvm::StringRef namestr = llvm::StringRef(name); - M->addLibrary(namestr); - return; -} - -char *LLVMDumpTypeToString(LLVMTypeRef type) -{ - return do_print(type); -} - -char *LLVMDumpValueToString(LLVMValueRef value) -{ - return do_print(value); -} - -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module) -{ - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::Module::PointerSize p = modulep->getPointerSize(); - if (p == llvm::Module::Pointer32) - return 32; - else if (p == llvm::Module::Pointer64) - return 64; - return 0; -} - -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type) -{ - assert(name); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::FunctionType *ftp = llvm::unwrap(function_type); - assert(ftp); - - llvm::Constant *f = modulep->getOrInsertFunction(name, ftp); - return wrap(f); -} - -int LLVMHasInitializer(LLVMValueRef global_var) -{ - llvm::GlobalVariable *gvp = llvm::unwrap(global_var); - assert(gvp); - - return gvp->hasInitializer(); -} - -#define inst_checkfn(ourfn, llvmfn) \ -unsigned ourfn (LLVMValueRef v) { \ - llvm::Instruction *ip = llvm::unwrap(v); \ - assert(ip); \ - return ip-> llvmfn () ? 1 : 0; \ -} - -inst_checkfn(LLVMInstIsTerminator, isTerminator) -inst_checkfn(LLVMInstIsBinaryOp, isBinaryOp) -inst_checkfn(LLVMInstIsShift, isShift) -inst_checkfn(LLVMInstIsCast, isCast) -inst_checkfn(LLVMInstIsLogicalShift, isLogicalShift) -inst_checkfn(LLVMInstIsArithmeticShift, isArithmeticShift) -inst_checkfn(LLVMInstIsAssociative, isAssociative) -inst_checkfn(LLVMInstIsCommutative, isCommutative) - -unsigned LLVMInstIsVolatile(LLVMValueRef v) -{ - using namespace llvm; - Instruction *ip = unwrap(v); - assert(ip); - return ((isa(*ip) && cast(*ip).isVolatile()) || - (isa(*ip) && cast(*ip).isVolatile()) ); -} - -const char *LLVMInstGetOpcodeName(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - assert(instp); - return instp->getOpcodeName(); -} - -unsigned LLVMInstGetOpcode(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - assert(instp); - return instp->getOpcode(); -} - -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst) -{ - llvm::CmpInst *instp = llvm::unwrap(cmpinst); - assert(instp); - return instp->getPredicate(); -} - -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - return llvm::wrap(CallSite(instp).getCalledFunction()); -} - -///* llvm::unwrap a set of `n' wrapped objects starting at `values', -// * into a vector of pointers to llvm::unwrapped objects `out'. */ -//template -//void unwrap_vec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); -// out.reserve(n); -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - -///* Same as llvm::unwrap_vec, but use a vector of const pointers. */ -//template -//void unwrap_cvec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); - -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - - -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef builder, - LLVMValueRef *values, unsigned n_values) -{ - using namespace llvm; - assert(values); - - IRBuilder<> *builderp = unwrap(builder); - assert(builderp); - - return wrap(builderp->CreateAggregateRet(unwrap(values, n_values), n_values)); -} - -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, - LLVMValueRef value, unsigned index, const char *name) -{ - assert(name); - - llvm::IRBuilder<> *builderp = llvm::unwrap(builder); - assert(builderp); - - return llvm::wrap(builderp->CreateExtractValue(llvm::unwrap(value), index, name)); -} - -unsigned LLVMValueGetID(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getValueID(); -} - - -unsigned LLVMValueGetNumUses(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getNumUses(); -} - - -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - unsigned n = valuep->getNumUses(); - if (n == 0) - return 0; - - assert(refs); - LLVMValueRef *out = new LLVMValueRef[n]; - if (!out) - return 0; - *refs = out; - - memset(out, 0, sizeof(LLVMValueRef) * n); - llvm::Value::use_iterator it = valuep->use_begin(); - while (it != valuep->use_end()) { - *out++ = llvm::wrap(*it); - ++it; - } - - return n; -} - -void LLVMDisposeValueRefArray(LLVMValueRef *refs) -{ - assert(refs); - delete [] refs; -} - -unsigned LLVMUserGetNumOperands(LLVMValueRef user) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - return userp->getNumOperands(); -} - -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - llvm::Value *operand = userp->getOperand(idx); - return llvm::wrap(operand); -} - -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return fnp->doesNotThrow(); -} - -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return fnp->setDoesNotThrow((bool)DoesNotThrow); -} - - -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef module, int id, - LLVMTypeRef *types, unsigned n_types) -{ - using namespace llvm; - assert(types); - - Module *modulep = unwrap(module); - assert(modulep); - - Function *intfunc = Intrinsic::getDeclaration(modulep, Intrinsic::ID(id), - makeArrayRef(unwrap(types, n_types), - n_types)); - - return wrap(intfunc); -} - -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtext, char **out) -{ - assert(asmtext); - assert(out); - - llvm::Module *modulep; - llvm::SMDiagnostic error; - if (!(modulep = llvm::ParseAssemblyString(asmtext, NULL, error, - llvm::getGlobalContext()))) { - std::string s; - llvm::raw_string_ostream buf(s); - error.print("llvm-py", buf); - *out = strdup(buf.str().c_str()); - return NULL; - } - - return wrap(modulep); -} - -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bitcode, unsigned bclen, - char **out) -{ - assert(bitcode); - assert(out); - - llvm::StringRef as_str(bitcode, bclen); - - llvm::MemoryBuffer *mbp; - if (!(mbp = llvm::MemoryBuffer::getMemBufferCopy(as_str))) - return NULL; - - std::string msg; - llvm::Module *modulep; - if (!(modulep = llvm::ParseBitcodeFile(mbp, llvm::getGlobalContext(), - &msg))) - *out = strdup(msg.c_str()); - - delete mbp; - return wrap(modulep); -} - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, unsigned int mode, - char **out) -{ - llvm::Module *sourcep = llvm::unwrap(src); - assert(sourcep); - llvm::Module *destinationp = llvm::unwrap(dest); - assert(destinationp); - - std::string msg; - if (llvm::Linker::LinkModules(destinationp, sourcep, mode, &msg)) { - *out = strdup(msg.c_str()); - return 0; - } - - return 1; -} -#endif - -unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *lenp) -{ - assert(lenp); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - /* get bc into a string */ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::WriteBitcodeToFile(modulep, buf); - const std::string& bc = buf.str(); - - /* and then into a new()-ed block */ - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -/* Return 0 on failure (with errmsg filled in), 1 on success. */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg) -{ - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@1"); - assert(filename); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2"); - assert(errmsg); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@3"); - - /* Note: the LLVM API returns true on failure. Don't ask why. */ - std::string msg; - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@4"); - if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename, &msg)) { - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5"); - *errmsg = strdup(msg.c_str()); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@6"); - return 0; - } - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7"); - return 1; -} - -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn) -{ - llvm::ExecutionEngine *eep = llvm::unwrap(ee); - assert(eep); - - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return eep->getPointerToFunction(fnp); -} - - -int LLVMInlineFunction(LLVMValueRef call) -{ - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - - llvm::InlineFunctionInfo unused; - - llvm::Instruction *II = llvm::dyn_cast(callp); - if (II->getOpcode() == llvm::Instruction::Call) - return llvm::InlineFunction(static_cast(II), unused); - else if (II->getOpcode() == llvm::Instruction::Invoke) - return llvm::InlineFunction(static_cast(II), unused); - else - return 0; -} - -unsigned LLVMGetParamAlignment(LLVMValueRef arg) -{ - llvm::Argument *argp = llvm::unwrap(arg); - assert(argp); - - unsigned argno = argp->getArgNo(); - - return argp->getParent()->getParamAlignment(argno + 1); -} - - -/* Passes. A few passes (listed below) are used directly from LLVM-C, - * rest are defined here. - */ -/* -#define define_pass(P) \ -void LLVMAdd ## P ## Pass (LLVMPassManagerRef passmgr) { \ - using namespace llvm; \ - llvm::PassManagerBase *pmp = llvm::unwrap(passmgr); \ - assert(pmp); \ - pmp->add( create ## P ## Pass ()); \ -} - -define_pass( AAEval ) -define_pass( AliasAnalysisCounter ) -//define_pass( AlwaysInliner ) -//define_pass( BasicAliasAnalysis ) -define_pass( BlockPlacement ) -define_pass( BreakCriticalEdges ) -define_pass( CodeGenPrepare ) -define_pass( DbgInfoPrinter ) -define_pass( DeadCodeElimination ) -define_pass( DeadInstElimination ) -define_pass( DemoteRegisterToMemory ) -define_pass( DomOnlyPrinter ) -define_pass( DomOnlyViewer ) -define_pass( DomPrinter ) -define_pass( DomViewer ) -define_pass( EdgeProfiler ) -//define_pass( GEPSplitter ) -define_pass( GlobalsModRef ) -define_pass( InstCount ) -define_pass( InstructionNamer ) -define_pass( LazyValueInfo ) -define_pass( LCSSA ) -//define_pass( LiveValues ) -define_pass( LoopDependenceAnalysis ) -define_pass( LoopExtractor ) -define_pass( LoopSimplify ) -define_pass( LoopStrengthReduce ) -define_pass( LowerInvoke ) -define_pass( LowerSwitch ) -define_pass( MergeFunctions ) -define_pass( NoAA ) -define_pass( NoProfileInfo ) -define_pass( OptimalEdgeProfiler ) -define_pass( PartialInlining ) -//define_pass( PartialSpecialization ) -define_pass( PostDomOnlyPrinter ) -define_pass( PostDomOnlyViewer ) -define_pass( PostDomPrinter ) -define_pass( PostDomViewer ) -define_pass( ProfileEstimator ) -define_pass( ProfileLoader ) -define_pass( ProfileVerifier ) -define_pass( ScalarEvolutionAliasAnalysis ) -//define_pass( SimplifyHalfPowrLibCalls ) -define_pass( SingleLoopExtractor ) -define_pass( StripNonDebugSymbols ) -//define_pass( StructRetPromotion ) -//define_pass( TailDuplication ) -define_pass( UnifyFunctionExitNodes ) -*/ -/* we support only internalize(true) */ -/* -llvm::ModulePass *createInternalize2Pass() { return llvm::createInternalizePass(true); } -define_pass( Internalize2 ) -*/ diff --git a/llvm/extra.h b/llvm/extra.h deleted file mode 100644 index 1772878..0000000 --- a/llvm/extra.h +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -#ifndef LLVM_PY_EXTRA_H -#define LLVM_PY_EXTRA_H - -// select PTX or NVPTX - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #define LLVM_HAS_NVPTX 1 -#else - #define LLVM_HAS_NVPTX 0 -#endif - -#include "llvm-c/Transforms/PassManagerBuilder.h" - -#include "llvm_c_extra.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Wraps Instruction::setMetadata() - */ -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref); - -/* - * Wraps MDNode::get() - */ -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct); - -/* - * Wraps MDNode::getOperand() - */ -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index); - -/* - * Wraps MDNode::getNumOperands() - */ -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref); - -/* - * Wraps MDString::get() - */ -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s); - -/* - * Wraps ConstantExpr::getOpcodeName() - */ -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst); - -/* - * Wraps ConstantExpr::getOpcode() - */ -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst); - -/* - * Wraps LoadInst::SetAlignment - */ -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align); - -/* - * Wraps StoreInst::SetAlignment - */ -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align); - -const char * LLVMGetHostCPUName(); - -int LLVMInitializeNativeTargetAsmPrinter(); - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - std::string &error); - -/* - * Wraps EngineBuilder::selectTarget - */ -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb); - -/* - * Wraps operator delete - */ -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error); - -/* - * Wraps TargetMachine::getTargetData - */ -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getName() - */ -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getShortDescription() - */ -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetTriple - */ -const char * LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetCPU - */ -const char * LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetFeatureString - */ -const char * LLVMTargetMachineGetFS(LLVMTargetMachineRef tm); - -/* - * Wraps TargetRegister::printRegisteredTargetsForVersion - */ -void LLVMPrintRegisteredTargetsForVersion(); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error); - -/* - * Wraps IRBuilder::CreateFence - */ -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateLoad, LoadInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread); -/* - * Wraps IRBuilder::CreateStore, StoreInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicRMW - */ -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicCmpXchg - */ -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps new EngineBuilder - */ -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod); - -/* - * Wraps delete EngineBuilder - */ -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::JIT) - */ -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb); - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::Interpreter) - */ -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setOptLevel - */ -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level); - -/* - * Wraps EngineBuilder::setMCPU - */ -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu); - -/* - * Wraps EngineBuilder::setMAttrs - */ -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs); - -/* - * Wraps EngineBuilder::setErrorStr and EngineBuilder::create - */ -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, - std::string &error); - -/* - * Wraps PassManagerBuilder::OptLevel - */ -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::SizeLevel - */ -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableUnitAtATime - */ -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableUnrollLoops - */ -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableSimplifyLibCalls - */ -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManager::add - */ -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name); - -/* - * Wraps initialize* - */ -void LLVMInitializePasses(void); - -/* - * Wraps PassRegistry::enumerateWith() - * Returns a '\n' separated string of all passes available to `opt`. - */ -const char * LLVMDumpPasses(void); - -/* - * Wraps StructType::isLiteral() - */ -int LLVMIsLiteralStruct(LLVMTypeRef type); - -/* - * Wraps StructType::create() - */ -LLVMTypeRef LLVMStructTypeIdentified(const char * name); - -/* - * StructType::setBody() - */ -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed); - -/* - * Wraps llvm::StructType::setName() - */ -void LLVMSetStructName(LLVMTypeRef type, const char * name); - - -/* - * Wraps llvm::Module::getModuleIdentifier() - */ -char *LLVMGetModuleIdentifier(LLVMModuleRef module); - -/* - * Wraps llvm::Module::setModuleIdentifier() - */ -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name); - -/* Notes: - * - Some returned strings must be disposed of by LLVMDisposeMessage. These are - * indicated in the comments. Where it is not indicated, DO NOT call dispose. - */ - -/* Wraps llvm::Module::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpModuleToString(LLVMModuleRef module); - -/* Wraps llvm::Module::addLibrary(name). */ -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name); - -/* Wraps llvm::Type::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpTypeToString(LLVMTypeRef type); - -/* Wraps llvm::Value::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpValueToString(LLVMValueRef Val); - -/* Wraps llvm::IRBuilder::CreateRet(). */ -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef bulder, LLVMValueRef *values, - unsigned n_values); - -/* Wraps llvm::IRBuilder::CreateGetResult(). */ -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value, - unsigned index, const char *name); - -/* Wraps llvm::Value::getValueID(). */ -unsigned LLVMValueGetID(LLVMValueRef value); - -/* Wraps llvm::Value::getNumUses(). */ -unsigned LLVMValueGetNumUses(LLVMValueRef value); - -/* Wraps llvm::Value::use_{begin,end}. Allocates LLVMValueRef's as - * required. Number of objects are returned as return value. If that is - * greater than zero, the pointer given out must be freed by a - * subsequent call to LLVMDisposeValueRefArray(). */ -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs); - -/* See above. */ -void LLVMDisposeValueRefArray(LLVMValueRef *refs); - -/* Wraps llvm:User::getNumOperands(). */ -unsigned LLVMUserGetNumOperands(LLVMValueRef user); - -/* Wraps llvm:User::getOperand(). */ -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx); - -/* Wraps llvm::ConstantExpr::getVICmp(). */ -LLVMValueRef LLVMConstVICmp(LLVMIntPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::ConstantExpr::getVFCmp(). */ -LLVMValueRef LLVMConstVFCmp(LLVMRealPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::IRBuilder::CreateVICmp(). */ -LLVMValueRef LLVMBuildVICmp(LLVMBuilderRef builder, LLVMIntPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::IRBuilder::CreateVFCmp(). */ -LLVMValueRef LLVMBuildVFCmp(LLVMBuilderRef builder, LLVMRealPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::Intrinsic::getDeclaration(). */ -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef builder, int id, - LLVMTypeRef *types, unsigned n_types); - -/* Wraps llvm::Function::doesNotThrow(). */ -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn); - -/* Wraps llvm::Function::setDoesNotThrow(). */ -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow); - -/* Wraps llvm::Module::getPointerSize(). */ -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module); - -/* Wraps llvm::Module::getOrInsertFunction(). */ -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type); - -/* Wraps llvm::GlobalVariable::hasInitializer(). */ -int LLVMHasInitializer(LLVMValueRef global_var); - -/* The following functions wrap various llvm::Instruction::isXXX() functions. - * All of them take an instruction and return 0 (isXXX returned false) or 1 - * (isXXX returned false). */ -unsigned LLVMInstIsTerminator (LLVMValueRef inst); -unsigned LLVMInstIsBinaryOp (LLVMValueRef inst); -unsigned LLVMInstIsShift (LLVMValueRef inst); -unsigned LLVMInstIsCast (LLVMValueRef inst); -unsigned LLVMInstIsLogicalShift (LLVMValueRef inst); -unsigned LLVMInstIsArithmeticShift (LLVMValueRef inst); -unsigned LLVMInstIsAssociative (LLVMValueRef inst); -unsigned LLVMInstIsCommutative (LLVMValueRef inst); -unsigned LLVMInstIsTrapping (LLVMValueRef inst); - -/* As above, but these are wrap methods from subclasses of Instruction. */ -unsigned LLVMInstIsVolatile (LLVMValueRef inst); - -/* Wraps llvm::Instruction::getOpcodeName(). */ -const char *LLVMInstGetOpcodeName(LLVMValueRef inst); - -/* Wraps llvm::Instruction::getOpcode(). */ -unsigned LLVMInstGetOpcode(LLVMValueRef inst); - -/* Wraps llvm::CmpInst::getPredicate(). */ -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst); - -/* Wraps llvm::CallSite::getCalledFunction. - */ -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst); - -/* Wraps llvm::ParseAssemblyString(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtxt, char **out); - -/* Wraps llvm::ParseBitcodeFile(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bc, unsigned bclen, - char **out); - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -/* Wraps llvm::Linker::LinkModules(). Returns 0 on failure (with errmsg - * filled in) and 1 on success. Dispose error message after use with - * LLVMDisposeMessage(). */ -unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, - unsigned int, char **errmsg); -#endif -/* Returns pointer to a heap-allocated block of `*len' bytes containing bit code - * for the given module. NULL on error. */ -unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *len); - -/* Wraps llvm::sys::DynamicLibrary::LoadLibraryPermanently(). Returns 0 on - * failure (with errmsg filled in) and 1 on success. Dispose error message after - * use, via LLVMDisposeMessage(). */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg); - -/* Wraps llvm::ExecutionEngine::getPointerToFunction(). Returns a pointer - * to the JITted function. */ -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn); - -/* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). - */ -int LLVMInlineFunction(LLVMValueRef call); - -/* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -unsigned LLVMGetParamAlignment(LLVMValueRef arg); - -/* Passes. Some passes are used directly from LLVM-C, rest are declared - * here. */ - -/* -#define declare_pass(P) \ - void LLVMAdd ## P ## Pass (LLVMPassManagerRef PM); - -declare_pass( AAEval ) -declare_pass( AliasAnalysisCounter ) -declare_pass( AlwaysInliner ) -declare_pass( BasicAliasAnalysis ) -declare_pass( BlockPlacement ) -declare_pass( BreakCriticalEdges ) -declare_pass( CodeGenPrepare ) -declare_pass( DbgInfoPrinter ) -declare_pass( DeadCodeElimination ) -declare_pass( DeadInstElimination ) -declare_pass( DemoteRegisterToMemory ) -declare_pass( DomOnlyPrinter ) -declare_pass( DomOnlyViewer ) -declare_pass( DomPrinter ) -declare_pass( DomViewer ) -declare_pass( EdgeProfiler ) -//declare_pass( GEPSplitter ) -declare_pass( GlobalsModRef ) -declare_pass( InstCount ) -declare_pass( InstructionNamer ) -declare_pass( LazyValueInfo ) -declare_pass( LCSSA ) -//declare_pass( LiveValues ) -declare_pass( LoopDependenceAnalysis ) -declare_pass( LoopExtractor ) -declare_pass( LoopSimplify ) -declare_pass( LoopStrengthReduce ) -declare_pass( LowerInvoke ) -declare_pass( LowerSwitch ) -declare_pass( MergeFunctions ) -declare_pass( NoAA ) -declare_pass( NoProfileInfo ) -declare_pass( OptimalEdgeProfiler ) -declare_pass( PartialInlining ) -//declare_pass( PartialSpecialization ) -declare_pass( PostDomOnlyPrinter ) -declare_pass( PostDomOnlyViewer ) -declare_pass( PostDomPrinter ) -declare_pass( PostDomViewer ) -declare_pass( ProfileEstimator ) -declare_pass( ProfileLoader ) -declare_pass( ProfileVerifier ) -declare_pass( ScalarEvolutionAliasAnalysis ) -declare_pass( SimplifyHalfPowrLibCalls ) -declare_pass( SingleLoopExtractor ) -declare_pass( StripNonDebugSymbols ) -declare_pass( StructRetPromotion ) -declare_pass( TailDuplication ) -declare_pass( UnifyFunctionExitNodes ) - -declare_pass( Internalize2 ) -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LLVM_PY_EXTRA_H */ - diff --git a/llvm/llrt.py b/llvm/llrt.py new file mode 100644 index 0000000..c704a66 --- /dev/null +++ b/llvm/llrt.py @@ -0,0 +1,79 @@ +import os +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le + +def replace_divmod64(lfunc): + '''Replaces all 64-bit integer division (sdiv, udiv) and modulo (srem, urem) + ''' + int64 = lc.Type.int(64) + int64ptr = lc.Type.pointer(lc.Type.int(64)) + + functy = lc.Type.function(int64, [int64, int64]) + udiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_udiv64') + sdiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_sdiv64') + umod64 = lfunc.module.get_or_insert_function(functy, '__llrt_umod64') + smod64 = lfunc.module.get_or_insert_function(functy, '__llrt_smod64') + + builder = lc.Builder.new(lfunc.entry_basic_block) + for bb in lfunc.basic_blocks: + for inst in bb.instructions: + if inst.opcode_name == 'sdiv' and inst.type == int64: + _replace_with(builder, inst, sdiv64) + elif inst.opcode_name == 'udiv' and inst.type == int64: + _replace_with(builder, inst, udiv64) + elif inst.opcode_name == 'srem' and inst.type == int64: + _replace_with(builder, inst, smod64) + elif inst.opcode_name == 'urem' and inst.type == int64: + _replace_with(builder, inst, umod64) + +def _replace_with(builder, inst, func): + '''Replace instruction with a call to the function with the same operands + as arguments. + ''' + builder.position_before(inst) + replacement = builder.call(func, inst.operands) + inst.replace_all_uses_with(replacement._ptr) + inst.erase_from_parent() + +def load(arch): + '''Load the LLRT module corresponding to the given architecture + Creates a new module and optimizes it using the information from + the host machine. + ''' + if arch != 'x86_64': + arch = 'x86' + path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch) + with open(path) as fin: + lib = lc.Module.from_assembly(fin) + + # run passes to optimize + tm = le.TargetMachine.new() + pms = lp.build_pass_managers(tm, opt=3, fpm=False) + pms.pm.run(lib) + return lib + +class LLRT(object): + def __init__(self): + arch = le.get_default_triple().split('-', 1)[0] + self.module = load(arch) + self.engine = le.EngineBuilder.new(self.module).opt(3).create() + self.installed_symbols = set() + + def install_symbols(self): + '''Bind all the external symbols to the global symbol map. + Any future reference to these symbols will be automatically resolved + by LLVM. + ''' + for lfunc in self.module.functions: + if lfunc.linkage == lc.LINKAGE_EXTERNAL: + mangled = '__llrt_' + lfunc.name + self.installed_symbols.add(mangled) + ptr = self.engine.get_pointer_to_function(lfunc) + le.dylib_add_symbol(mangled, ptr) + + def uninstall_symbols(self): + for sym in self.installed_symbols: + le.dylib_add_symbol(sym, 0) + + diff --git a/llvm/llrt/llrt_x86.ll b/llvm/llrt/llrt_x86.ll new file mode 100644 index 0000000..5096214 --- /dev/null +++ b/llvm/llrt/llrt_x86.ll @@ -0,0 +1,371 @@ +; ModuleID = 'udivmod64_x86.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128" + +%struct.div_state_ = type { i64, i64 } + +define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp { + %1 = alloca i64, align 4 + %2 = alloca i64, align 8 + %3 = alloca i64, align 8 + %4 = alloca i64*, align 4 + %state = alloca %struct.div_state_, align 4 + %quotient = alloca i64, align 8 + %i = alloca i32, align 4 + %skipahead = alloca i32, align 4 + store i64 %dividend, i64* %2, align 8 + store i64 %divisor, i64* %3, align 8 + store i64* %remainder, i64** %4, align 4 + %5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0 + store i64 0, i64* %5, align 4 + %6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1 + %7 = load i64* %2, align 8 + store i64 %7, i64* %6, align 4 + store i64 0, i64* %quotient, align 8 + %8 = load i64* %3, align 8 + %9 = icmp eq i64 %8, 0 + br i1 %9, label %10, label %11 + +;