diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f4474f7..0000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -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 45d6a5f..5af6169 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,40 +1,3 @@ -2014-04-28 0.12.5: ---------------------- - * Fixes memory leaks (#92) - * Fixes tarball (#99) - -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 diff --git a/MANIFEST.in b/MANIFEST.in index 25a211d..295794c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ -include CHANGELOG LICENSE README.rst setup.py MANIFEST.in versioneer.py +include CHANGELOG LICENSE README setup.py MANIFEST.in recursive-include llvm * -recursive-include llvmpy * recursive-include www * recursive-include test * recursive-include tools * diff --git a/README.rst b/README.rst index a1abf84..b16249a 100644 --- a/README.rst +++ b/README.rst @@ -16,48 +16,26 @@ Other Python versions may work. Quickstart ---------- -1. Get and extract LLVM 3.2 source tarball from - `llvm.org `_. Then, ``cd`` into - the extracted directory. +1. Get 3.2 version of LLVM, build it. Make sure ``--enable-pic`` is + passed to LLVM's ``configure``. -2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``. + For LLVM 3.2, make sure that environment variable ``REQUIRES_RTTI=1`` is + defined when running ``make``. Otherwise, you may see "undefined symbol: + _ZTIN4llvm24PassRegistrationListenerE". Please refer to + http://llvm.org/docs/Packaging.html#c-features for details. - **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:: +2. 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 + $ python setup.py install Run the tests:: $ python -c "import llvm; llvm.test()" -5. See documentation at 'http://www.llvmpy.org' and examples +3. 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/buildscripts/condarecipe/bld.bat b/buildscripts/condarecipe/bld.bat deleted file mode 100644 index e9177c5..0000000 --- a/buildscripts/condarecipe/bld.bat +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 5c98fde..0000000 --- a/buildscripts/condarecipe/build.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/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 deleted file mode 100644 index 4612840..0000000 --- a/buildscripts/condarecipe/meta.yaml +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index 682b8d4..0000000 --- a/buildscripts/condarecipe/run_test.py +++ /dev/null @@ -1,22 +0,0 @@ -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 3ee5d20..dd30e28 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 = 'https://github.com/llvmpy/llvmpy-doc.git' +pages_repo = 'git@github.com:llvmpy/llvmpy-doc.git' #----------------------------------------------------------------------------- # Functions diff --git a/docs/source/doc/getting_started.rst b/docs/source/doc/getting_started.rst index 53c2982..f9b9c56 100644 --- a/docs/source/doc/getting_started.rst +++ b/docs/source/doc/getting_started.rst @@ -38,7 +38,7 @@ supported, for a variety of reasons. Versions -------- -llvmpy 0.11.2 uses LLVM 3.2 (or at least 3.1). It may not work with +llvmpy 0.9 requires version 3.1 of LLVM. It may not work with previous versions. llvmpy has been built and tested with Python 2.7 and 3.2. It should work with @@ -65,6 +65,22 @@ 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 ----------- @@ -82,34 +98,13 @@ is different from that of 'root', so even if ``llvm-config`` is in your Steps ----- -1. Get and extract LLVM 3.2 source tarball from - `llvm.org `_. Then, ``cd`` into - the extracted directory. +Get 3.1 version of LLVM, build it. Make sure '--enable-pic' is passed to +LLVM's 'configure'. -2. Run ``./configure --enable-optimized --prefix=LLVM_INSTALL_PATH``. +Get llvmpy and install it: - **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`` to build. +.. code-block:: bash - **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'. + $ git clone git@github.com:numba/llvmpy.git + $ cd llvmpy $ python setup.py install diff --git a/docs/source/doc/kaleidoscope/PythonLangImpl7.rst b/docs/source/doc/kaleidoscope/PythonLangImpl7.rst index dee1c31..7e86ee4 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 ... diff --git a/docs/source/doc/llvm.core.Constant.rst b/docs/source/doc/llvm.core.Constant.rst index 3822046..ae67fa4 100644 --- a/docs/source/doc/llvm.core.Constant.rst +++ b/docs/source/doc/llvm.core.Constant.rst @@ -26,335 +26,334 @@ 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 - - -# 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 {% + 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) + Automatically Generated Documentation ------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index fbf5c8b..7798b77 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. -llvmpy -====== +Documentation for llvmpy +======================== Contents: @@ -22,7 +22,7 @@ Contents: Indices and tables ------------------- +================== * :ref:`genindex` * :ref:`modindex` diff --git a/example/vector_instr.py b/example/vector_instr.py deleted file mode 100644 index e49d06a..0000000 --- a/example/vector_instr.py +++ /dev/null @@ -1,152 +0,0 @@ -''' -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/byte_control.py b/llpython/byte_control.py index 8ca407e..9df6d5c 100644 --- a/llpython/byte_control.py +++ b/llpython/byte_control.py @@ -1,11 +1,12 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from __future__ import absolute_import + import opcode -from . import opcode_util +import opcode_util import pprint -from .bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin -from .control_flow import ControlFlowGraph +from bytecode_visitor import BasicBlockVisitor, BenignBytecodeVisitorMixin +from control_flow import ControlFlowGraph # ______________________________________________________________________ diff --git a/llpython/byte_flow.py b/llpython/byte_flow.py index 197c839..4a878b2 100644 --- a/llpython/byte_flow.py +++ b/llpython/byte_flow.py @@ -1,10 +1,11 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from __future__ import absolute_import + import dis import opcode -from .bytecode_visitor import BasicBlockVisitor -from . import opcode_util +from bytecode_visitor import BasicBlockVisitor +import opcode_util # ______________________________________________________________________ diff --git a/llpython/byte_translator.py b/llpython/byte_translator.py index a6e5864..3922099 100644 --- a/llpython/byte_translator.py +++ b/llpython/byte_translator.py @@ -1,21 +1,22 @@ +#! /usr/bin/env python # ______________________________________________________________________ '''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 +import opcode_util +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 diff --git a/llpython/bytecode_visitor.py b/llpython/bytecode_visitor.py index 3fa3f48..dcc3a0c 100644 --- a/llpython/bytecode_visitor.py +++ b/llpython/bytecode_visitor.py @@ -1,9 +1,10 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from __future__ import absolute_import + import itertools import opcode -from .opcode_util import itercode +from opcode_util import itercode # ______________________________________________________________________ diff --git a/llpython/bytetype.py b/llpython/bytetype.py index 484d09e..211f3f8 100644 --- a/llpython/bytetype.py +++ b/llpython/bytetype.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ import ctypes diff --git a/llpython/control_flow.py b/llpython/control_flow.py index 8026aba..5ea030a 100644 --- a/llpython/control_flow.py +++ b/llpython/control_flow.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ import pprint diff --git a/llpython/gen_bytecode_visitor.py b/llpython/gen_bytecode_visitor.py index a60b345..7f922e2 100644 --- a/llpython/gen_bytecode_visitor.py +++ b/llpython/gen_bytecode_visitor.py @@ -1,6 +1,7 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from __future__ import absolute_import -from . import opcode_util + +import opcode_util # ______________________________________________________________________ diff --git a/llpython/nobitey.py b/llpython/nobitey.py index 4236d29..014216b 100644 --- a/llpython/nobitey.py +++ b/llpython/nobitey.py @@ -1,5 +1,6 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from __future__ import absolute_import + import sys import os.path import imp @@ -9,8 +10,9 @@ import types import llvm.core as lc import llvm.ee as le -from . import bytetype, byte_translator -from .pyaddfunc import pyaddfunc +import bytetype +import byte_translator +from pyaddfunc import pyaddfunc LLVM_TO_INT_PARSE_STR_MAP = { 8 : 'b', diff --git a/llpython/opcode_util.py b/llpython/opcode_util.py index 7a1972b..efd0c5c 100644 --- a/llpython/opcode_util.py +++ b/llpython/opcode_util.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ import dis diff --git a/llpython/phi_injector.py b/llpython/phi_injector.py index dfa1061..6cccb66 100644 --- a/llpython/phi_injector.py +++ b/llpython/phi_injector.py @@ -1,6 +1,7 @@ +#! /usr/bin/env python # ______________________________________________________________________ -from .bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin +from bytecode_visitor import BytecodeFlowVisitor, BenignBytecodeVisitorMixin # ______________________________________________________________________ diff --git a/llpython/pyaddfunc.py b/llpython/pyaddfunc.py index d6a2945..8e09839 100644 --- a/llpython/pyaddfunc.py +++ b/llpython/pyaddfunc.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ import ctypes diff --git a/llpython/tests/llfuncs.py b/llpython/tests/llfuncs.py index 8b5b1f3..2a8614f 100644 --- a/llpython/tests/llfuncs.py +++ b/llpython/tests/llfuncs.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ def doslice (in_string, lower, upper): diff --git a/llpython/tests/llfunctys.py b/llpython/tests/llfunctys.py index 8335044..b552cf4 100644 --- a/llpython/tests/llfunctys.py +++ b/llpython/tests/llfunctys.py @@ -1,3 +1,4 @@ +#! /usr/bin/env python # ______________________________________________________________________ import llvm.core as lc diff --git a/llrtc/Makefile b/llrtc/Makefile deleted file mode 100644 index b15eac5..0000000 --- a/llrtc/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index 539d9c3..0000000 --- a/llrtc/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 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 deleted file mode 100644 index fbcf76a..0000000 --- a/llrtc/lib/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.o -*.run -*.out -*.ll diff --git a/llrtc/lib/Makefile b/llrtc/lib/Makefile deleted file mode 100644 index 9dbfb27..0000000 --- a/llrtc/lib/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -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 deleted file mode 100644 index 8466965..0000000 --- a/llrtc/lib/div64.c +++ /dev/null @@ -1,11 +0,0 @@ -#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 deleted file mode 100644 index 4e9e348..0000000 --- a/llrtc/lib/llrt.h +++ /dev/null @@ -1,19 +0,0 @@ -#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 deleted file mode 100644 index 875f6b9..0000000 --- a/llrtc/lib/mod64.c +++ /dev/null @@ -1,15 +0,0 @@ -#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 deleted file mode 100644 index df294b3..0000000 --- a/llrtc/lib/sdivmod64.c +++ /dev/null @@ -1,40 +0,0 @@ -#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 deleted file mode 100644 index 1e804d6..0000000 --- a/llrtc/lib/test_sdivmod64.c +++ /dev/null @@ -1,21 +0,0 @@ -#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 deleted file mode 100644 index 4aa49a9..0000000 --- a/llrtc/lib/test_sdivmod64.py +++ /dev/null @@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 70b44aa..0000000 --- a/llrtc/lib/test_udivmod64.c +++ /dev/null @@ -1,20 +0,0 @@ -#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 deleted file mode 100644 index da07ccb..0000000 --- a/llrtc/lib/test_udivmod64.py +++ /dev/null @@ -1,53 +0,0 @@ -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 deleted file mode 100644 index 5936f98..0000000 --- a/llrtc/lib/udivmod64.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -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 deleted file mode 100644 index a20ba34..0000000 --- a/llrtc/tools/striptriple.py +++ /dev/null @@ -1,15 +0,0 @@ -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 3f756ee..05fc94f 100644 --- a/llvm-config-win32.py +++ b/llvm-config-win32.py @@ -2,7 +2,6 @@ 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 @@ -40,17 +39,55 @@ def libs_options(): # NOTE: instead of actually looking at the components requested, # 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 +LLVMObject +LLVMRuntimeDyld +LLVMScalarOpts +LLVMSelectionDAG +LLVMSupport +LLVMTarget +LLVMTransformUtils +LLVMVectorize +LLVMX86AsmParser +LLVMX86AsmPrinter +LLVMX86CodeGen +LLVMX86Desc +LLVMX86Disassembler +LLVMX86Info +LLVMX86Utils Advapi32 Shell32 """.split(): print('-l%s' % lib) - 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) + if isfile(join(find_llvm_prefix(), 'lib', 'LLVMPTXCodeGen.lib')): + print('-lLLVMPTXAsmPrinter') + print('-lLLVMPTXCodeGen') + print('-lLLVMPTXDesc') + print('-lLLVMPTXInfo') + + elif isfile(join(find_llvm_prefix(), 'lib', 'LLVMNVPTXCodeGen.lib')): + print('-lLLVMNVPTXAsmPrinter') + print('-lLLVMNVPTXCodeGen') + print('-lLLVMNVPTXDesc') + print('-lLLVMNVPTXInfo') + def main(): try: @@ -61,15 +98,12 @@ def main(): 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')) + ensure_file(join(incdir, 'llvm' , 'BasicBlock.h')) print(incdir) elif option == '--libdir': diff --git a/llvm/__init__.py b/llvm/__init__.py index 9b24112..e3e785f 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -4,13 +4,10 @@ del get_versions 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 @@ -34,14 +31,12 @@ def _extract_ptrs(objs): class LLVMException(Exception): pass -def test(verbosity=3, run_isolated=True): +def test(verbosity=1): """test(verbosity=1) -> TextTestResult - Run self-test, and return the number of failures + errors + Run self-test, and return unittest.runner.TextTestResult object. """ - from llvm.tests import run + from llvm.test_llvmpy import run - result = run(verbosity=verbosity, run_isolated=run_isolated) - errct = len(result.failures) + len(result.errors) + return run(verbosity=verbosity) - return errct diff --git a/llvm/core.py b/llvm/core.py index 4db8135..bbe5d01 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -41,203 +41,150 @@ 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) - - @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() +TYPE_VOID = api.llvm.Type.TypeID.VoidTyID +TYPE_HALF = api.llvm.Type.TypeID.HalfTyID +TYPE_FLOAT = api.llvm.Type.TypeID.FloatTyID +TYPE_DOUBLE = api.llvm.Type.TypeID.DoubleTyID +TYPE_X86_FP80 = api.llvm.Type.TypeID.X86_FP80TyID +TYPE_FP128 = api.llvm.Type.TypeID.FP128TyID +TYPE_PPC_FP128 = api.llvm.Type.TypeID.PPC_FP128TyID +TYPE_LABEL = api.llvm.Type.TypeID.LabelTyID +TYPE_INTEGER = api.llvm.Type.TypeID.IntegerTyID +TYPE_FUNCTION = api.llvm.Type.TypeID.FunctionTyID +TYPE_STRUCT = api.llvm.Type.TypeID.StructTyID +TYPE_ARRAY = api.llvm.Type.TypeID.ArrayTyID +TYPE_POINTER = api.llvm.Type.TypeID.PointerTyID +TYPE_VECTOR = api.llvm.Type.TypeID.VectorTyID +TYPE_METADATA = api.llvm.Type.TypeID.MetadataTyID +TYPE_X86_MMX = api.llvm.Type.TypeID.X86_MMXTyID # value IDs (llvm::Value::ValueTy enum) # 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() +VALUE_ARGUMENT = api.llvm.Value.ValueTy.ArgumentVal +VALUE_BASIC_BLOCK = api.llvm.Value.ValueTy.BasicBlockVal +VALUE_FUNCTION = api.llvm.Value.ValueTy.FunctionVal +VALUE_GLOBAL_ALIAS = api.llvm.Value.ValueTy.GlobalAliasVal +VALUE_GLOBAL_VARIABLE = api.llvm.Value.ValueTy.GlobalVariableVal +VALUE_UNDEF_VALUE = api.llvm.Value.ValueTy.UndefValueVal +VALUE_BLOCK_ADDRESS = api.llvm.Value.ValueTy.BlockAddressVal +VALUE_CONSTANT_EXPR = api.llvm.Value.ValueTy.ConstantExprVal +VALUE_CONSTANT_AGGREGATE_ZERO = api.llvm.Value.ValueTy.ConstantAggregateZeroVal +VALUE_CONSTANT_DATA_ARRAY = api.llvm.Value.ValueTy.ConstantDataArrayVal +VALUE_CONSTANT_DATA_VECTOR = api.llvm.Value.ValueTy.ConstantDataVectorVal +VALUE_CONSTANT_INT = api.llvm.Value.ValueTy.ConstantIntVal +VALUE_CONSTANT_FP = api.llvm.Value.ValueTy.ConstantFPVal +VALUE_CONSTANT_ARRAY = api.llvm.Value.ValueTy.ConstantArrayVal +VALUE_CONSTANT_STRUCT = api.llvm.Value.ValueTy.ConstantStructVal +VALUE_CONSTANT_VECTOR = api.llvm.Value.ValueTy.ConstantVectorVal +VALUE_CONSTANT_POINTER_NULL = api.llvm.Value.ValueTy.ConstantPointerNullVal +VALUE_MD_NODE = api.llvm.Value.ValueTy.MDNodeVal +VALUE_MD_STRING = api.llvm.Value.ValueTy.MDStringVal +VALUE_INLINE_ASM = api.llvm.Value.ValueTy.InlineAsmVal +VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceValueVal +VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal +VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal # instruction opcodes (from include/llvm/Instruction.def) -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() +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 # calling conventions +CC_C = api.llvm.CallingConv.ID.C +CC_FASTCALL = api.llvm.CallingConv.ID.Fast +CC_COLDCALL = api.llvm.CallingConv.ID.Cold +CC_GHC = api.llvm.CallingConv.ID.GHC +CC_X86_STDCALL = api.llvm.CallingConv.ID.X86_StdCall +CC_X86_FASTCALL = api.llvm.CallingConv.ID.X86_FastCall +CC_ARM_APCS = api.llvm.CallingConv.ID.ARM_APCS +CC_ARM_AAPCS = api.llvm.CallingConv.ID.ARM_AAPCS +CC_ARM_AAPCS_VFP = api.llvm.CallingConv.ID.ARM_AAPCS_VFP +CC_MSP430_INTR = api.llvm.CallingConv.ID.MSP430_INTR +CC_X86_THISCALL = api.llvm.CallingConv.ID.X86_ThisCall +CC_PTX_KERNEL = api.llvm.CallingConv.ID.PTX_Kernel +CC_PTX_DEVICE = api.llvm.CallingConv.ID.PTX_Device +CC_MBLAZE_INTR = api.llvm.CallingConv.ID.MBLAZE_INTR +CC_MBLAZE_SVOL = api.llvm.CallingConv.ID.MBLAZE_SVOL -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 -class ICMPEnum(Enum): - prefix = 'ICMP_' +ICMP_EQ = api.llvm.CmpInst.Predicate.ICMP_EQ +ICMP_NE = api.llvm.CmpInst.Predicate.ICMP_NE +ICMP_UGT = api.llvm.CmpInst.Predicate.ICMP_UGT +ICMP_UGE = api.llvm.CmpInst.Predicate.ICMP_UGE +ICMP_ULT = api.llvm.CmpInst.Predicate.ICMP_ULT +ICMP_ULE = api.llvm.CmpInst.Predicate.ICMP_ULE +ICMP_SGT = api.llvm.CmpInst.Predicate.ICMP_SGT +ICMP_SGE = api.llvm.CmpInst.Predicate.ICMP_SGE +ICMP_SLT = api.llvm.CmpInst.Predicate.ICMP_SLT +ICMP_SLE = api.llvm.CmpInst.Predicate.ICMP_SLE - 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 @@ -250,33 +197,24 @@ IPRED_SLT = ICMP_SLT IPRED_SLE = ICMP_SLE # real predicates - -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() +FCMP_FALSE = api.llvm.CmpInst.Predicate.FCMP_FALSE +FCMP_OEQ = api.llvm.CmpInst.Predicate.FCMP_OEQ +FCMP_OGT = api.llvm.CmpInst.Predicate.FCMP_OGT +FCMP_OGE = api.llvm.CmpInst.Predicate.FCMP_OGE +FCMP_OLT = api.llvm.CmpInst.Predicate.FCMP_OLT +FCMP_OLE = api.llvm.CmpInst.Predicate.FCMP_OLE +FCMP_ONE = api.llvm.CmpInst.Predicate.FCMP_ONE +FCMP_ORD = api.llvm.CmpInst.Predicate.FCMP_ORD +FCMP_UNO = api.llvm.CmpInst.Predicate.FCMP_UNO +FCMP_UEQ = api.llvm.CmpInst.Predicate.FCMP_UEQ +FCMP_UGT = api.llvm.CmpInst.Predicate.FCMP_UGT +FCMP_UGE = api.llvm.CmpInst.Predicate.FCMP_UGE +FCMP_ULT = api.llvm.CmpInst.Predicate.FCMP_ULT +FCMP_ULE = api.llvm.CmpInst.Predicate.FCMP_ULE +FCMP_UNE = api.llvm.CmpInst.Predicate.FCMP_UNE +FCMP_TRUE = api.llvm.CmpInst.Predicate.FCMP_TRUE # real predicates - RPRED_FALSE = FCMP_FALSE RPRED_OEQ = FCMP_OEQ RPRED_OGT = FCMP_OGT @@ -295,75 +233,68 @@ RPRED_UNE = FCMP_UNE RPRED_TRUE = FCMP_TRUE # 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() +LINKAGE_EXTERNAL = \ + api.llvm.GlobalValue.LinkageTypes.ExternalLinkage +LINKAGE_AVAILABLE_EXTERNALLY = \ + api.llvm.GlobalValue.LinkageTypes.AvailableExternallyLinkage +LINKAGE_LINKONCE_ANY = \ + api.llvm.GlobalValue.LinkageTypes.LinkOnceAnyLinkage +LINKAGE_LINKONCE_ODR = \ + api.llvm.GlobalValue.LinkageTypes.LinkOnceODRLinkage +LINKAGE_WEAK_ANY = \ + api.llvm.GlobalValue.LinkageTypes.WeakAnyLinkage +LINKAGE_WEAK_ODR = \ + api.llvm.GlobalValue.LinkageTypes.WeakODRLinkage +LINKAGE_APPENDING = \ + api.llvm.GlobalValue.LinkageTypes.AppendingLinkage +LINKAGE_INTERNAL = \ + api.llvm.GlobalValue.LinkageTypes.InternalLinkage +LINKAGE_PRIVATE = \ + api.llvm.GlobalValue.LinkageTypes.PrivateLinkage +LINKAGE_DLLIMPORT = \ + api.llvm.GlobalValue.LinkageTypes.DLLImportLinkage +LINKAGE_DLLEXPORT = \ + api.llvm.GlobalValue.LinkageTypes.DLLExportLinkage +LINKAGE_EXTERNAL_WEAK = \ + api.llvm.GlobalValue.LinkageTypes.ExternalWeakLinkage +LINKAGE_COMMON = \ + api.llvm.GlobalValue.LinkageTypes.CommonLinkage +LINKAGE_LINKER_PRIVATE = \ + api.llvm.GlobalValue.LinkageTypes.LinkerPrivateLinkage +LINKAGE_LINKER_PRIVATE_WEAK = \ + api.llvm.GlobalValue.LinkageTypes.LinkerPrivateWeakLinkage # visibility (see llvm/GlobalValue.h) -class VisibilityEnum(Enum): - prefix = 'VISIBILITY_' +VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility +VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility +VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility - VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility - VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility - VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility +# parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) +ATTR_NONE = api.llvm.Attributes.AttrVal.None_ +ATTR_ZEXT = api.llvm.Attributes.AttrVal.ZExt +ATTR_SEXT = api.llvm.Attributes.AttrVal.SExt +ATTR_NO_RETURN = api.llvm.Attributes.AttrVal.NoReturn +ATTR_IN_REG = api.llvm.Attributes.AttrVal.InReg +ATTR_STRUCT_RET = api.llvm.Attributes.AttrVal.StructRet +ATTR_NO_UNWIND = api.llvm.Attributes.AttrVal.NoUnwind +ATTR_NO_ALIAS = api.llvm.Attributes.AttrVal.NoAlias +ATTR_BY_VAL = api.llvm.Attributes.AttrVal.ByVal +ATTR_NEST = api.llvm.Attributes.AttrVal.Nest +ATTR_READ_NONE = api.llvm.Attributes.AttrVal.ReadNone +ATTR_READONLY = api.llvm.Attributes.AttrVal.ReadOnly +ATTR_NO_INLINE = api.llvm.Attributes.AttrVal.NoInline +ATTR_ALWAYS_INLINE = api.llvm.Attributes.AttrVal.AlwaysInline +ATTR_OPTIMIZE_FOR_SIZE = api.llvm.Attributes.AttrVal.OptimizeForSize +ATTR_STACK_PROTECT = api.llvm.Attributes.AttrVal.StackProtect +ATTR_STACK_PROTECT_REQ = api.llvm.Attributes.AttrVal.StackProtectReq +ATTR_ALIGNMENT = api.llvm.Attributes.AttrVal.Alignment +ATTR_NO_CAPTURE = api.llvm.Attributes.AttrVal.NoCapture +ATTR_NO_REDZONE = api.llvm.Attributes.AttrVal.NoRedZone +ATTR_NO_IMPLICIT_FLOAT = api.llvm.Attributes.AttrVal.NoImplicitFloat +ATTR_NAKED = api.llvm.Attributes.AttrVal.Naked +ATTR_INLINE_HINT = api.llvm.Attributes.AttrVal.InlineHint +ATTR_STACK_ALIGNMENT = api.llvm.Attributes.AttrVal.StackAlignment -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_' - - if llvm.version >= (3, 3): - AttrVal = api.llvm.Attribute.AttrKind - else: - 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 - -AttrEnum.declare() class Module(llvm.Wrapper): """A Module instance stores all the information related to an LLVM module. @@ -379,7 +310,6 @@ class Module(llvm.Wrapper): module_obj = Module.new('my_module') """ - __slots__ = '__weakref__' __cache = weakref.WeakValueDictionary() def __new__(cls, ptr): @@ -452,12 +382,12 @@ class Module(llvm.Wrapper): """ return str(self._ptr) - def __hash__(self): - return id(self._ptr) - def __eq__(self, rhs): + assert isinstance(rhs, Module), type(rhs) if isinstance(rhs, Module): - return self._ptr == rhs._ptr + return str(self) == str(rhs) + else: + return False def __ne__(self, rhs): return not (self == rhs) @@ -513,7 +443,7 @@ class Module(llvm.Wrapper): mode, errmsg) if failed: - raise llvm.LLVMException(errmsg.getvalue()) + raise llvm.LLVMException(errmsg) def get_type_named(self, name): typ = self._ptr.getTypeByName(name) @@ -605,7 +535,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = BytesIO() + fileobj = BytesIO api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() @@ -689,7 +619,6 @@ class Type(llvm.Wrapper): Use one of the static methods to create an instance. Example: ty = Type.double() """ - __slots__ = '__name__' _type_ = api.llvm.Type def __init__(self, ptr): @@ -801,7 +730,7 @@ class Type(llvm.Wrapper): otherwise, creates a literal type.""" context = api.llvm.getGlobalContext() is_packed = True - ptr = api.llvm.StructType.create(context, name) + ptr = api.llvm.StructType.create(context) ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) return StructType(ptr) @@ -871,9 +800,6 @@ class Type(llvm.Wrapper): def __str__(self): return str(self._ptr) - def __hash__(self): - return hash(self._ptr) - def __eq__(self, rhs): return self._ptr is rhs._ptr @@ -882,7 +808,6 @@ class Type(llvm.Wrapper): class IntegerType(Type): """Represents an integer type.""" - __slots__ = () _type_ = api.llvm.IntegerType @property @@ -892,7 +817,6 @@ class IntegerType(Type): class FunctionType(Type): """Represents a function type.""" - __slots__ = () _type_ = api.llvm.FunctionType @property @@ -922,7 +846,6 @@ class FunctionType(Type): class StructType(Type): """Represents a structure type.""" _type_ = api.llvm.StructType - __slots__ = () @property def element_count(self): @@ -956,10 +879,7 @@ class StructType(Type): self._ptr.setName(name) def _get_name(self): - if self._ptr.isLiteral(): - return "" - else: - return self._ptr.getName() + return self._ptr.getName() name = property(_get_name, _set_name) @@ -975,13 +895,9 @@ class StructType(Type): def is_opaque(self): 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): @@ -993,7 +909,6 @@ class ArrayType(Type): class PointerType(Type): _type_ = api.llvm.PointerType - __slots__ = () @property def pointee(self): @@ -1005,7 +920,6 @@ class PointerType(Type): class VectorType(Type): _type_ = api.llvm.VectorType - __slots__ = () @property def element(self): @@ -1017,7 +931,6 @@ class VectorType(Type): class Value(llvm.Wrapper): _type_ = api.llvm.Value - __slots__ = '__weakref__' def __init__(self, builder, ptr): assert builder is _ValueFactory @@ -1048,9 +961,6 @@ class Value(llvm.Wrapper): def __str__(self): return str(self._ptr) - def __hash__(self): - return hash(self._ptr) - def __eq__(self, rhs): if isinstance(rhs, Value): return str(self) == str(rhs) @@ -1086,7 +996,6 @@ class Value(llvm.Wrapper): class User(Value): _type_ = api.llvm.User - __slots__ = () @property def operand_count(self): @@ -1101,7 +1010,6 @@ class User(Value): class Constant(User): _type_ = api.llvm.Constant - __slots__ = () @staticmethod def null(ty): @@ -1287,7 +1195,6 @@ class Constant(User): class ConstantExpr(Constant): _type_ = api.llvm.ConstantExpr - __slots__ = () @property def opcode(self): @@ -1298,20 +1205,19 @@ class ConstantExpr(Constant): return self._ptr.getOpcodeName() class ConstantAggregateZero(Constant): - __slots__ = () + pass class ConstantDataArray(Constant): - __slots__ = () + pass class ConstantDataVector(Constant): - __slots__ = () + pass class ConstantInt(Constant): _type_ = api.llvm.ConstantInt - __slots__ = () @property def z_ext_value(self): @@ -1327,32 +1233,30 @@ class ConstantInt(Constant): class ConstantFP(Constant): - __slots__ = () + pass class ConstantArray(Constant): - __slots__ = () + pass class ConstantStruct(Constant): - __slots__ = () + pass class ConstantVector(Constant): - __slots__ = () + pass class ConstantPointerNull(Constant): - __slots__ = () + pass class UndefValue(Constant): - __slots__ = () - + pass class GlobalValue(Constant): _type_ = api.llvm.GlobalValue - __slots__ = () def _get_linkage(self): return self._ptr.getLinkage() @@ -1398,7 +1302,6 @@ class GlobalValue(Constant): class GlobalVariable(GlobalValue): _type_ = api.llvm.GlobalVariable - __slots__ = () @staticmethod def new(module, ty, name, addrspace=0): @@ -1459,60 +1362,28 @@ class GlobalVariable(GlobalValue): 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]) - 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 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 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 _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 self._ptr.getParamAlignment() @@ -1520,47 +1391,7 @@ class Argument(Value): 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 @@ -1670,10 +1501,7 @@ class Function(GlobalValue): 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) + attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeFnAttr(attrs) def viewCFGOnly(self): @@ -1699,7 +1527,6 @@ class Function(GlobalValue): #===----------------------------------------------------------------------=== class InlineAsm(Value): - __slots__ = () _type_ = api.llvm.InlineAsm @staticmethod @@ -1714,7 +1541,6 @@ class InlineAsm(Value): #===----------------------------------------------------------------------=== class MetaData(Value): - __slots__ = () _type_ = api.llvm.MDNode @staticmethod @@ -1771,7 +1597,6 @@ class MetaDataString(Value): class NamedMetaData(llvm.Wrapper): - __slots__ = () @staticmethod def get_or_insert(mod, name): @@ -1801,7 +1626,6 @@ class NamedMetaData(llvm.Wrapper): #===----------------------------------------------------------------------=== class Instruction(User): - __slots__ = () _type_ = api.llvm.Instruction @property @@ -1861,12 +1685,6 @@ class Instruction(User): def set_metadata(self, kind, metadata): 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 self._ptr.getOpcode() @@ -1878,12 +1696,8 @@ class Instruction(User): 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): @@ -1898,33 +1712,21 @@ class CallOrInvokeInstruction(Instruction): 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) - + attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) def remove_parameter_attribute(self, 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) - + attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeAttribute(idx, attrs) def set_parameter_alignment(self, 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) - + attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) def _get_called_function(self): @@ -1939,7 +1741,6 @@ class CallOrInvokeInstruction(Instruction): class PHINode(Instruction): - __slots__ = () _type_ = api.llvm.PHINode @property @@ -1957,60 +1758,21 @@ class PHINode(Instruction): class SwitchInstruction(Instruction): - __slots__ = () - _type_ = api.llvm.SwitchInst def add_case(self, const, bblk): self._ptr.addCase(const._ptr, bblk._ptr) class CompareInstruction(Instruction): - __slots__ = () - _type_ = api.llvm.CmpInst @property def predicate(self): - 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() - + return self._ptr.getPredicate() #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== class BasicBlock(Value): - __slots__ = () _type_ = api.llvm.BasicBlock def insert_before(self, name): @@ -2037,7 +1799,6 @@ class BasicBlock(Value): class _ValueFactory(object): - __slots__ = () cache = weakref.WeakValueDictionary() # value ID -> class map @@ -2066,8 +1827,7 @@ class _ValueFactory(object): 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, + VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction } @classmethod @@ -2114,7 +1874,6 @@ _atomic_orderings = { } class Builder(llvm.Wrapper): - __slots__ = () @staticmethod def new(basic_block): @@ -2205,34 +1964,29 @@ class Builder(llvm.Wrapper): # arithmethic, bitwise and logical - def add(self, lhs, rhs, name="", nuw=False, nsw=False): - return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name, - nuw, nsw)) + def add(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) def fadd(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFAdd(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 sub(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) def fsub(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFSub(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 mul(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) def fmul(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFMul(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 udiv(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateUDiv(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 sdiv(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) def fdiv(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) @@ -2246,17 +2000,14 @@ class Builder(llvm.Wrapper): def frem(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateFRem(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 shl(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateShl(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 lshr(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateLShr(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 ashr(self, lhs, rhs, name=""): + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) def and_(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) @@ -2267,8 +2018,8 @@ class Builder(llvm.Wrapper): def xor(self, lhs, rhs, name=""): return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) - def neg(self, val, name="", nuw=False, nsw=False): - return _make_value(self._ptr.CreateNeg(val._ptr, name, nuw, nsw)) + def neg(self, val, name=""): + return _make_value(self._ptr.CreateNeg(val._ptr, name)) def not_(self, val, name=""): return _make_value(self._ptr.CreateNot(val._ptr, name)) @@ -2276,6 +2027,7 @@ class Builder(llvm.Wrapper): # memory def malloc(self, ty, name=""): + context = api.llvm.getGlobalContext() allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) ity = allocsz.getType() malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, @@ -2289,6 +2041,7 @@ class Builder(llvm.Wrapper): return _make_value(inst) def malloc_array(self, ty, size, name=""): + context = api.llvm.getGlobalContext() allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) ity = allocsz.getType() malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, @@ -2301,13 +2054,12 @@ class Builder(llvm.Wrapper): inst = self._ptr.Insert(malloc, name) return _make_value(inst) - def alloca(self, ty, size=None, name=""): - sizeptr = size._ptr if size else None - return _make_value(self._ptr.CreateAlloca(ty._ptr, sizeptr, name)) + def alloca(self, ty, name=""): + intty = Type.int() + return _make_value(self._ptr.CreateAlloca(ty._ptr, None, name)) - @deprecated def alloca_array(self, ty, size, name=""): - return self.alloca(ty, size, name=name) + return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) def free(self, ptr): free = api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr) @@ -2394,20 +2146,15 @@ class Builder(llvm.Wrapper): # misc def extract_value(self, retval, idx, name=""): - if not isinstance(idx, (tuple, list)): - idx = [idx] - return _make_value(self._ptr.CreateExtractValue(retval._ptr, idx, - name)) + 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=""): - if not isinstance(idx, (tuple, list)): - idx = [idx] return _make_value(self._ptr.CreateInsertValue(retval._ptr, rhs._ptr, - idx, + [idx], name)) def phi(self, ty, name=""): @@ -2547,8 +2294,29 @@ if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") -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!?") + +#===----------------------------------------------------------------------=== +# Initialization +#===----------------------------------------------------------------------=== + +HAS_PTX = HAS_NVPTX = False + +if True: # use PTX? + try: + api.LLVMInitializePTXTarget() + api.LLVMInitializePTXTargetInfo() + api.LLVMInitializePTXTargetMC() + api.LLVMInitializePTXAsmPrinter() + HAS_PTX = True + except AttributeError: + try: + api.LLVMInitializeNVPTXTarget() + api.LLVMInitializeNVPTXTargetInfo() + api.LLVMInitializeNVPTXTargetMC() + api.LLVMInitializeNVPTXAsmPrinter() + HAS_NVPTX = True + except AttributeError: + pass + + + diff --git a/llvm/deprecated.py b/llvm/deprecated.py deleted file mode 100644 index 6db5fe7..0000000 --- a/llvm/deprecated.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -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 f615b61..9531427 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -30,23 +30,33 @@ "Execution Engine and related classes." -import sys +from io import BytesIO +import contextlib import llvm from llvm import core from llvm.passes import TargetData, TargetTransformInfo from llvmpy import api, extra - #===----------------------------------------------------------------------=== -# import items which were moved to target module +# Enumerations #===----------------------------------------------------------------------=== -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) +BO_BIG_ENDIAN = 0 +BO_LITTLE_ENDIAN = 1 + +# CodeModel +CM_DEFAULT = api.llvm.CodeModel.Model.Default +CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault +CM_SMALL = api.llvm.CodeModel.Model.Small +CM_KERNEL = api.llvm.CodeModel.Model.Kernel +CM_MEDIUM = api.llvm.CodeModel.Model.Medium +CM_LARGE = api.llvm.CodeModel.Model.Large + +# Reloc +RELOC_DEFAULT = api.llvm.Reloc.Model.Default +RELOC_STATIC = api.llvm.Reloc.Model.Static +RELOC_PIC = api.llvm.Reloc.Model.PIC_ +RELOC_DYNAMIC_NO_PIC = api.llvm.Reloc.Model.DynamicNoPIC #===----------------------------------------------------------------------=== # Generic value @@ -122,7 +132,7 @@ class EngineBuilder(llvm.Wrapper): level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] ''' assert 0 <= level <= 3 - self._ptr.setOptLevel(level) + self._ptr.setOptLevel = level return self def mattrs(self, string): @@ -140,17 +150,9 @@ class EngineBuilder(llvm.Wrapper): ''' 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 + return ExecutionEngine(engine) def select_target(self, *args): '''get the corresponding target machine @@ -165,12 +167,6 @@ class EngineBuilder(llvm.Wrapper): 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 @@ -192,9 +188,6 @@ class ExecutionEngine(llvm.Wrapper): 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): return self._ptr.getPointerToFunction(fn._ptr) @@ -220,45 +213,133 @@ class ExecutionEngine(llvm.Wrapper): def remove_module(self, module): return self._ptr.removeModule(module._ptr) - def finalize_object(self): - return self._ptr.finalizeObject() - @property def target_data(self): ptr = self._ptr.getDataLayout() return TargetData(ptr) - #===----------------------------------------------------------------------=== -# Dynamic Library +# Target machine #===----------------------------------------------------------------------=== -def dylib_add_symbol(name, ptr): - api.llvm.sys.DynamicLibrary.AddSymbol(name, ptr) +def print_registered_targets(): + ''' + Note: print directly to stdout + ''' + api.llvm.TargetRegistry.printRegisteredTargetsForVersion() -def dylib_address_of_symbol(name): - return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name) +def get_host_cpu_name(): + '''return the string name of the host CPU + ''' + return api.llvm.sys.getHostCPUName() -def dylib_import_library(filename): - """Permanently import a dynamic library. - - Returns a DynamicLibrary object - - Raises RuntimeError - """ - return DynamicLibrary(filename) +def get_default_triple(): + '''return the target triple of the host in str-rep + ''' + return api.llvm.sys.getDefaultTargetTriple() -class DynamicLibrary(object): - def __init__(self, filename): - """ - Raises RuntimeError - """ - self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary( - filename) +class TargetMachine(llvm.Wrapper): + + @staticmethod + def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT, + reloc=RELOC_DEFAULT): + if not triple: + triple = get_default_triple() + if not cpu: + cpu = get_host_cpu_name() + with contextlib.closing(BytesIO()) as error: + target = api.llvm.TargetRegistry.lookupTarget(triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions.new() + tm = target.createTargetMachine(triple, cpu, features, + target_options, + reloc, cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(tm) + + @staticmethod + def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT, + reloc=RELOC_DEFAULT): + '''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` + ''' + triple = api.llvm.Triple.new() + with contextlib.closing(BytesIO()) as error: + target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions.new() + tm = target.createTargetMachine(str(triple), cpu, features, + target_options, + reloc, cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(tm) + + def _emit_file(self, module, cgft): + pm = api.llvm.PassManager.new() + os = extra.make_raw_ostream_for_printing() + pm.add(api.llvm.DataLayout.new(str(self.target_data))) + failed = self._ptr.addPassesToEmitFile(pm, os, cgft) + pm.run(module) + + + CGFT = api.llvm.TargetMachine.CodeGenFileType + if cgft == CGFT.CGFT_ObjectFile: + return os.bytes() + else: + return os.str() + + def emit_assembly(self, module): + '''returns byte string of the module as assembly code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile) + + def emit_object(self, module): + '''returns byte string of the module as native code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile) + + @property + def target_data(self): + '''get target data of this machine + ''' + return TargetData(self._ptr.getDataLayout()) + + @property + def target_name(self): + return self._ptr.getTarget().getName() + + @property + def target_short_description(self): + return self._ptr.getTarget().getShortDescription() + + @property + def triple(self): + return self._ptr.getTargetTriple() + + @property + def cpu(self): + return self._ptr.getTargetCPU() + + @property + def feature_string(self): + return self._ptr.getTargetFeatureString() - def get_address_of_symbol(self, symbol): - """ - Get the address of `symbol` (str) as integer - """ - return self._ptr.getAddressOfSymbol(symbol) diff --git a/llvm/llrt.py b/llvm/llrt.py deleted file mode 100644 index c704a66..0000000 --- a/llvm/llrt.py +++ /dev/null @@ -1,79 +0,0 @@ -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 deleted file mode 100644 index 5096214..0000000 --- a/llvm/llrt/llrt_x86.ll +++ /dev/null @@ -1,371 +0,0 @@ -; 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 - -;