diff --git a/.gitattributes b/.gitattributes index 8966ad8ea2c84f792a1965b189a3605bdd14a866..39283779a6be0638423d8f887be6c18e2bfc82f6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text lib/python3.11/site-packages/llvmlite/binding/libllvmlite.dylib filter=lfs diff=lfs merge=lfs -text +lib/python3.11/site-packages/mlx/core.cpython-311-darwin.so filter=lfs diff=lfs merge=lfs -text diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/INSTALLER b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/INSTALLER new file mode 100644 index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/LICENSE b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..8e94a0168f400c07fa64094adc17eae54b913fd1 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2014-, Continuum Analytics, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/METADATA b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/METADATA new file mode 100644 index 0000000000000000000000000000000000000000..e12994ead07a08fe9dc2f6ce84ff04c824082d9d --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/METADATA @@ -0,0 +1,136 @@ +Metadata-Version: 2.1 +Name: llvmlite +Version: 0.41.1 +Summary: lightweight wrapper around basic LLVM functionality +Home-page: http://llvmlite.readthedocs.io +License: BSD +Project-URL: Source, https://github.com/numba/llvmlite +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Topic :: Software Development :: Code Generators +Classifier: Topic :: Software Development :: Compilers +Requires-Python: >=3.8 +License-File: LICENSE + +======== +llvmlite +======== + +.. image:: https://dev.azure.com/numba/numba/_apis/build/status/numba.llvmlite?branchName=main + :target: https://dev.azure.com/numba/numba/_build/latest?definitionId=2&branchName=main + :alt: Azure Pipelines +.. image:: https://codeclimate.com/github/numba/llvmlite/badges/gpa.svg + :target: https://codeclimate.com/github/numba/llvmlite + :alt: Code Climate +.. image:: https://coveralls.io/repos/github/numba/llvmlite/badge.svg + :target: https://coveralls.io/github/numba/llvmlite + :alt: Coveralls.io +.. image:: https://readthedocs.org/projects/llvmlite/badge/ + :target: https://llvmlite.readthedocs.io + :alt: Readthedocs.io + +A Lightweight LLVM Python Binding for Writing JIT Compilers +----------------------------------------------------------- + +.. _llvmpy: https://github.com/llvmpy/llvmpy + +llvmlite is a project originally tailored for Numba_'s needs, using the +following approach: + +* A small C wrapper around the parts of the LLVM C++ API we need that are + not already exposed by the LLVM C API. +* A ctypes Python wrapper around the C API. +* A pure Python implementation of the subset of the LLVM IR builder that we + need for Numba. + +Why llvmlite +============ + +The old llvmpy_ binding exposes a lot of LLVM APIs but the mapping of +C++-style memory management to Python is error prone. Numba_ and many JIT +compilers do not need a full LLVM API. Only the IR builder, optimizer, +and JIT compiler APIs are necessary. + +Key Benefits +============ + +* The IR builder is pure Python code and decoupled from LLVM's + frequently-changing C++ APIs. +* Materializing a LLVM module calls LLVM's IR parser which provides + better error messages than step-by-step IR building through the C++ + API (no more segfaults or process aborts). +* Most of llvmlite uses the LLVM C API which is small but very stable + (low maintenance when changing LLVM version). +* The binding is not a Python C-extension, but a plain DLL accessed using + ctypes (no need to wrestle with Python's compiler requirements and C++ 11 + compatibility). +* The Python binding layer has sane memory management. +* llvmlite is faster than llvmpy thanks to a much simpler architecture + (the Numba_ test suite is twice faster than it was). + +Compatibility +============= + +llvmlite works with Python 3.8 and greater. We attempt to test with the latest +Python version, this can be checked by looking at the public CI builds. + +As of version 0.41.0, llvmlite requires LLVM 14.x.x on all architectures + +Historical compatibility table: + +================= ======================== +llvmlite versions compatible LLVM versions +================= ======================== +0.41.0 - ... 14.x.x +0.40.0 - 0.40.1 11.x.x and 14.x.x (12.x.x and 13.x.x untested but may work) +0.37.0 - 0.39.1 11.x.x +0.34.0 - 0.36.0 10.0.x (9.0.x for ``aarch64`` only) +0.33.0 9.0.x +0.29.0 - 0.32.0 7.0.x, 7.1.x, 8.0.x +0.27.0 - 0.28.0 7.0.x +0.23.0 - 0.26.0 6.0.x +0.21.0 - 0.22.0 5.0.x +0.17.0 - 0.20.0 4.0.x +0.16.0 - 0.17.0 3.9.x +0.13.0 - 0.15.0 3.8.x +0.9.0 - 0.12.1 3.7.x +0.6.0 - 0.8.0 3.6.x +0.1.0 - 0.5.1 3.5.x +================= ======================== + +Documentation +============= + +You'll find the documentation at http://llvmlite.pydata.org + + +Pre-built binaries +================== + +We recommend you use the binaries provided by the Numba_ team for +the Conda_ package manager. You can find them in Numba's `anaconda.org +channel `_. For example:: + + $ conda install --channel=numba llvmlite + +(or, simply, the official llvmlite package provided in the Anaconda_ +distribution) + +.. _Numba: http://numba.pydata.org/ +.. _Conda: http://conda.pydata.org/ +.. _Anaconda: http://docs.continuum.io/anaconda/index.html + + +Other build methods +=================== + +If you don't want to use our pre-built packages, you can compile +and install llvmlite yourself. The documentation will teach you how: +http://llvmlite.pydata.org/en/latest/install/index.html diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/RECORD b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/RECORD new file mode 100644 index 0000000000000000000000000000000000000000..d320d3807cd1fad2ae5ed594d03102eea4d5b5b0 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/RECORD @@ -0,0 +1,81 @@ +llvmlite-0.41.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +llvmlite-0.41.1.dist-info/LICENSE,sha256=S5pyZLAROnsybuhPwkS3OZG1NbSDPkpW1YdQ8qciUNw,1298 +llvmlite-0.41.1.dist-info/METADATA,sha256=ViL9FB2NBHKaVY4Ws8v41nBy-SKPB3-8PJ6HNIW8fTQ,4808 +llvmlite-0.41.1.dist-info/RECORD,, +llvmlite-0.41.1.dist-info/WHEEL,sha256=eaDTbMedWofVq8IZjew9qeAkoA5Sw2MOU2ppdIRr1Jg,110 +llvmlite-0.41.1.dist-info/top_level.txt,sha256=WJi8Gq92jA2wv_aV1Oshp9iZ-zMa43Kcmw80kWeGYGA,9 +llvmlite/__init__.py,sha256=PiUSiFLCm0YX5rbHS4xOLGdqdPDC8j3etV3nmEaelzI,92 +llvmlite/__pycache__/__init__.cpython-311.pyc,, +llvmlite/__pycache__/_version.cpython-311.pyc,, +llvmlite/__pycache__/utils.cpython-311.pyc,, +llvmlite/_version.py,sha256=fsnaBKvglYPJywrUAvzZsHhvixqEwJIDh0JKz4rwPtw,418 +llvmlite/binding/__init__.py,sha256=zjhFN8Ucg5Y_14kwn1OEyiH_X-wEnzwS_WVmkPoSChk,382 +llvmlite/binding/__pycache__/__init__.cpython-311.pyc,, +llvmlite/binding/__pycache__/analysis.cpython-311.pyc,, +llvmlite/binding/__pycache__/common.cpython-311.pyc,, +llvmlite/binding/__pycache__/context.cpython-311.pyc,, +llvmlite/binding/__pycache__/dylib.cpython-311.pyc,, +llvmlite/binding/__pycache__/executionengine.cpython-311.pyc,, +llvmlite/binding/__pycache__/ffi.cpython-311.pyc,, +llvmlite/binding/__pycache__/initfini.cpython-311.pyc,, +llvmlite/binding/__pycache__/linker.cpython-311.pyc,, +llvmlite/binding/__pycache__/module.cpython-311.pyc,, +llvmlite/binding/__pycache__/object_file.cpython-311.pyc,, +llvmlite/binding/__pycache__/options.cpython-311.pyc,, +llvmlite/binding/__pycache__/orcjit.cpython-311.pyc,, +llvmlite/binding/__pycache__/passmanagers.cpython-311.pyc,, +llvmlite/binding/__pycache__/targets.cpython-311.pyc,, +llvmlite/binding/__pycache__/transforms.cpython-311.pyc,, +llvmlite/binding/__pycache__/value.cpython-311.pyc,, +llvmlite/binding/analysis.py,sha256=BbCcAAGY0GLAEUek6ZogHkBAmFA9kvpS7333XyIrbhc,2253 +llvmlite/binding/common.py,sha256=eCSnnY4sctgeqVwDv9PrH6jpMI45nJPmAz4rfjbPsf8,742 +llvmlite/binding/context.py,sha256=l2vdKsJ038PfSKzaU17FCSDYWtByzIFYREmx93JwKW8,657 +llvmlite/binding/dylib.py,sha256=ypfikOYKiWQZi8h00LhLBXwmPlJ5d86yLOUn01pDjmM,1300 +llvmlite/binding/executionengine.py,sha256=rJrBP9n0Hm-lo53KRoRssFBLS8XOuIoAp_XWetiesS4,10713 +llvmlite/binding/ffi.py,sha256=bQB6yudHJTlCGaCsnvrhNgWQzJYcvxwvULAo53j3oe4,11950 +llvmlite/binding/initfini.py,sha256=zF9tJXmCONabkP0d_IqmiU6M_Wn8N8ArkwfXBxf1TDo,1595 +llvmlite/binding/libllvmlite.dylib,sha256=M1fMZuZYLPJYUM6bH3EMvkFg-HGpDIu-ls_Yf-hX6jA,91363294 +llvmlite/binding/linker.py,sha256=M4bAkoxVAUgxqai5S0_iCHS5EcNRPBX_9zldVqFLV90,489 +llvmlite/binding/module.py,sha256=Zf9GcuCEFf1xtOmP-jXqKtJbj4dO8l9a2NEPKTwsimI,11174 +llvmlite/binding/object_file.py,sha256=qZMTAi6gcVQq2e3KghHNxVH3Ivzr7zxDPecfiZ1Riy8,2664 +llvmlite/binding/options.py,sha256=aDH4SFh6VZ11agtUJO9vAxhVhQkIGAByK9IHKeuRcAI,509 +llvmlite/binding/orcjit.py,sha256=HUWDKicxrYK5s2trdrM_KEmkfvwifrP4E9MxmCb8JSM,11856 +llvmlite/binding/passmanagers.py,sha256=zfn-iP-vi5j_1s8JPAnZjPpcahhz1IL98tSdZKCw40s,34412 +llvmlite/binding/targets.py,sha256=5nxDn73pK_ElQu86EU994Qcd-k5Ja2U127T_oLrW_kk,14802 +llvmlite/binding/transforms.py,sha256=C_Tp0XPV__aOHaVzLLL_QFa-yI9vkDx1gwZADk_KwG8,4947 +llvmlite/binding/value.py,sha256=21-PwkBgAl26g0sqP2mI_lckSIDvq_LkgoLmzJE_8K4,18845 +llvmlite/ir/__init__.py,sha256=rNPtrPLshsPJYO4GegWAU-rpbpiYo0xU-CQb3rt0JtE,258 +llvmlite/ir/__pycache__/__init__.cpython-311.pyc,, +llvmlite/ir/__pycache__/_utils.cpython-311.pyc,, +llvmlite/ir/__pycache__/builder.cpython-311.pyc,, +llvmlite/ir/__pycache__/context.cpython-311.pyc,, +llvmlite/ir/__pycache__/instructions.cpython-311.pyc,, +llvmlite/ir/__pycache__/module.cpython-311.pyc,, +llvmlite/ir/__pycache__/transforms.cpython-311.pyc,, +llvmlite/ir/__pycache__/types.cpython-311.pyc,, +llvmlite/ir/__pycache__/values.cpython-311.pyc,, +llvmlite/ir/_utils.py,sha256=mkpyEMlQ9nHMcWmBMBsJm4S16Y0BfvxBf5brsdMmKio,2001 +llvmlite/ir/builder.py,sha256=t6ZCvkwXd1jmb-CGoTW12kLOSTnwjfS_eY9JJs6ij3g,33479 +llvmlite/ir/context.py,sha256=npgEbox0MzChmH7nfHpTdSsN_G4zU-XrpGx5AIYwafk,518 +llvmlite/ir/instructions.py,sha256=UbiK1Ja7JqZuEj0l6sm7-p-zgfu-fXEbhWqrQB43hbw,31753 +llvmlite/ir/module.py,sha256=pfpAh-73WMLptKqwgARwZ7aLMHpm88AcJA2GPfGvyVM,9074 +llvmlite/ir/transforms.py,sha256=pV79pB20m4N_HLmBEksw5VVP8cxyf7AYGDCbS1E7fOQ,1552 +llvmlite/ir/types.py,sha256=2GX-PIx_jDvt4GIfHkqiEkrJI_gPQqSktOsku2UZTgQ,16149 +llvmlite/ir/values.py,sha256=5YlGc90Yc7QuzDMcptoXmvfCjcAvhSk4fSnAwF1vSas,33987 +llvmlite/tests/__init__.py,sha256=TBHEOsEq-9M9rF94nES2HxefA-7GYwNE00Y7gTkHrD8,1378 +llvmlite/tests/__main__.py,sha256=10_On1rLj4CX1xsBJ9TbjULvNSp_K0qk9U1N6azUTUw,40 +llvmlite/tests/__pycache__/__init__.cpython-311.pyc,, +llvmlite/tests/__pycache__/__main__.cpython-311.pyc,, +llvmlite/tests/__pycache__/customize.cpython-311.pyc,, +llvmlite/tests/__pycache__/refprune_proto.cpython-311.pyc,, +llvmlite/tests/__pycache__/test_binding.cpython-311.pyc,, +llvmlite/tests/__pycache__/test_ir.cpython-311.pyc,, +llvmlite/tests/__pycache__/test_refprune.cpython-311.pyc,, +llvmlite/tests/__pycache__/test_valuerepr.cpython-311.pyc,, +llvmlite/tests/customize.py,sha256=85Af1gyZ5rtXXI3qpeTc2DXMrgETjv7hrLN-73A7Fhg,13268 +llvmlite/tests/refprune_proto.py,sha256=I5g0jWHYlsLCOX3Ct9-fA5_udLfkipzuBAsEkrNsFIk,8677 +llvmlite/tests/test_binding.py,sha256=Pvz7WxlxK_awXEXDAV30O4zTJ4PWY1-4SWwrRIGKMmA,80827 +llvmlite/tests/test_ir.py,sha256=tAE8Yruj8r1q6c8dk5I-oIJjnSVTADIwWGDKHUVUEo0,105472 +llvmlite/tests/test_refprune.py,sha256=oyk3HBLCOMPyRG-bj-omO3Ec_1lI66S8iNgZwl81Zs0,14235 +llvmlite/tests/test_valuerepr.py,sha256=57MaGznJUnqCf0etajnOCoBRue5-nmFTx1bds_5atlE,1989 +llvmlite/utils.py,sha256=BwgrA2JaYaZiHRafshoZBHiYSBskJQMG_K2F2jbW2-w,695 diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/WHEEL b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/WHEEL new file mode 100644 index 0000000000000000000000000000000000000000..5feb1eeba52cffb96bc20980b20ca1eb17bea57f --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.41.2) +Root-Is-Purelib: false +Tag: cp311-cp311-macosx_11_0_arm64 + diff --git a/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/top_level.txt b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..454f54ec1099613577b38e16e4d840f482157738 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite-0.41.1.dist-info/top_level.txt @@ -0,0 +1 @@ +llvmlite diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/customize.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/customize.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58e44826b2800abe4b49a0dc243830a4f2c6b280 Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/customize.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/refprune_proto.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/refprune_proto.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19a45b083aaac792f9b6267568e33a4062d6952b Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/refprune_proto.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_binding.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_binding.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a70b5c3754dd9e3f4cc16b2b4e8b64d01c8b9f5 Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_binding.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_ir.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_ir.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..870b9aaeea0d0589c78933febabf1f9fceefd0ed Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_ir.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_refprune.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_refprune.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc2efb1cc73ed977b6900982aa1f4a7f7009239d Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_refprune.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_valuerepr.cpython-311.pyc b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_valuerepr.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7399ed690762a279c17278475aa113224f54c843 Binary files /dev/null and b/lib/python3.11/site-packages/llvmlite/tests/__pycache__/test_valuerepr.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/llvmlite/tests/customize.py b/lib/python3.11/site-packages/llvmlite/tests/customize.py new file mode 100644 index 0000000000000000000000000000000000000000..7d747a3ca4343a7cb94911fa1283dbfbc35e0577 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/customize.py @@ -0,0 +1,407 @@ +# XXX Ripped off from numba.tests; we should factor it out somewhere? + +import collections +import contextlib +import cProfile +from io import StringIO +import gc +import os +import multiprocessing +import sys +import time +import unittest +import warnings +from unittest import result, runner, signals + + +# "unittest.main" is really the TestProgram class! +# (defined in a module named itself "unittest.main"...) + +class NumbaTestProgram(unittest.main): + """ + A TestProgram subclass adding the following options: + * a -R option to enable reference leak detection + * a --profile option to enable profiling of the test run + + Currently the options are only added in 3.4+. + """ + + refleak = False + profile = False + multiprocess = False + + def __init__(self, *args, **kwargs): + self.discovered_suite = kwargs.pop('suite', None) + # HACK to force unittest not to change warning display options + # (so that NumbaWarnings don't appear all over the place) + sys.warnoptions.append(':x') + super(NumbaTestProgram, self).__init__(*args, **kwargs) + + def createTests(self): + if self.discovered_suite is not None: + self.test = self.discovered_suite + else: + super(NumbaTestProgram, self).createTests() + + def _getParentArgParser(self): + # NOTE: this hook only exists on Python 3.4+. The options won't be + # added in earlier versions (which use optparse - 3.3 - or getopt() + # - 2.x). + parser = super(NumbaTestProgram, self)._getParentArgParser() + if self.testRunner is None: + parser.add_argument('-R', '--refleak', dest='refleak', + action='store_true', + help='Detect reference / memory leaks') + parser.add_argument('-m', '--multiprocess', dest='multiprocess', + action='store_true', + help='Parallelize tests') + parser.add_argument('--profile', dest='profile', + action='store_true', + help='Profile the test run') + return parser + + def parseArgs(self, argv): + if sys.version_info < (3, 4): + # We want these options to work on all versions, emulate them. + if '-R' in argv: + argv.remove('-R') + self.refleak = True + if '-m' in argv: + argv.remove('-m') + self.multiprocess = True + super(NumbaTestProgram, self).parseArgs(argv) + if self.verbosity <= 0: + # We aren't interested in informational messages / warnings when + # running with '-q'. + self.buffer = True + + def runTests(self): + if self.refleak: + self.testRunner = RefleakTestRunner + + if not hasattr(sys, "gettotalrefcount"): + warnings.warn("detecting reference leaks requires a debug " + "build of Python, only memory leaks will be " + "detected") + + elif self.testRunner is None: + self.testRunner = unittest.TextTestRunner + + if self.multiprocess: + self.testRunner = ParallelTestRunner(self.testRunner, + verbosity=self.verbosity, + failfast=self.failfast, + buffer=self.buffer) + + def run_tests_real(): + super(NumbaTestProgram, self).runTests() + + if self.profile: + filename = os.path.splitext( + os.path.basename(sys.modules['__main__'].__file__) + )[0] + '.prof' + p = cProfile.Profile(timer=time.perf_counter) # 3.3+ + p.enable() + try: + p.runcall(run_tests_real) + finally: + p.disable() + print("Writing test profile data into %r" % (filename,)) + p.dump_stats(filename) + else: + run_tests_real() + + +# Monkey-patch unittest so that individual test modules get our custom +# options for free. +unittest.main = NumbaTestProgram + + +# The reference leak detection code is liberally taken and adapted from +# Python's own Lib/test/regrtest.py. + +def _refleak_cleanup(): + # Collect cyclic trash and read memory statistics immediately after. + try: + func1 = sys.getallocatedblocks + except AttributeError: + def func1(): + return 42 + try: + func2 = sys.gettotalrefcount + except AttributeError: + def func2(): + return 42 + + # Flush standard output, so that buffered data is sent to the OS and + # associated Python objects are reclaimed. + for stream in (sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__): + if stream is not None: + stream.flush() + + sys._clear_type_cache() + # This also clears the various internal CPython freelists. + gc.collect() + return func1(), func2() + + +class ReferenceLeakError(RuntimeError): + pass + + +class IntPool(collections.defaultdict): + + def __missing__(self, key): + return key + + +class RefleakTestResult(runner.TextTestResult): + + warmup = 3 + repetitions = 6 + + def _huntLeaks(self, test): + self.stream.flush() + + repcount = self.repetitions + nwarmup = self.warmup + rc_deltas = [0] * (repcount - nwarmup) + alloc_deltas = [0] * (repcount - nwarmup) + # Preallocate ints likely to be stored in rc_deltas and alloc_deltas, + # to make sys.getallocatedblocks() less flaky. + _int_pool = IntPool() + for i in range(-200, 200): + _int_pool[i] + + alloc_before = rc_before = 0 + for i in range(repcount): + # Use a pristine, silent result object to avoid recursion + res = result.TestResult() + test.run(res) + # Poorly-written tests may fail when run several times. + # In this case, abort the refleak run and report the failure. + if not res.wasSuccessful(): + self.failures.extend(res.failures) + self.errors.extend(res.errors) + raise AssertionError + del res + alloc_after, rc_after = _refleak_cleanup() + if i >= nwarmup: + rc_deltas[i - nwarmup] = _int_pool[rc_after - rc_before] + alloc_deltas[i - + nwarmup] = _int_pool[alloc_after - + alloc_before] + alloc_before, rc_before = alloc_after, rc_after + return rc_deltas, alloc_deltas + + def addSuccess(self, test): + try: + rc_deltas, alloc_deltas = self._huntLeaks(test) + except AssertionError: + # Test failed when repeated + assert not self.wasSuccessful() + return + + # These checkers return False on success, True on failure + def check_rc_deltas(deltas): + return any(deltas) + + def check_alloc_deltas(deltas): + # At least 1/3rd of 0s + if 3 * deltas.count(0) < len(deltas): + return True + # Nothing else than 1s, 0s and -1s + if not set(deltas) <= set((1, 0, -1)): + return True + return False + + failed = False + + for deltas, item_name, checker in [ + (rc_deltas, 'references', check_rc_deltas), + (alloc_deltas, 'memory blocks', check_alloc_deltas)]: + if checker(deltas): + msg = '%s leaked %s %s, sum=%s' % ( + test, deltas, item_name, sum(deltas)) + failed = True + try: + raise ReferenceLeakError(msg) + except Exception: + exc_info = sys.exc_info() + if self.showAll: + self.stream.write("%s = %r " % (item_name, deltas)) + self.addFailure(test, exc_info) + + if not failed: + super(RefleakTestResult, self).addSuccess(test) + + +class RefleakTestRunner(runner.TextTestRunner): + resultclass = RefleakTestResult + + +def _flatten_suite(test): + """Expand suite into list of tests + """ + if isinstance(test, unittest.TestSuite): + tests = [] + for x in test: + tests.extend(_flatten_suite(x)) + return tests + else: + return [test] + + +class ParallelTestResult(runner.TextTestResult): + """ + A TestResult able to inject results from other results. + """ + + def add_results(self, result): + """ + Add the results from the other *result* to this result. + """ + self.stream.write(result.stream.getvalue()) + self.stream.flush() + self.testsRun += result.testsRun + self.failures.extend(result.failures) + self.errors.extend(result.errors) + self.skipped.extend(result.skipped) + self.expectedFailures.extend(result.expectedFailures) + self.unexpectedSuccesses.extend(result.unexpectedSuccesses) + + +class _MinimalResult(object): + """ + A minimal, picklable TestResult-alike object. + """ + + __slots__ = ( + 'failures', 'errors', 'skipped', 'expectedFailures', + 'unexpectedSuccesses', 'stream', 'shouldStop', 'testsRun') + + def fixup_case(self, case): + """ + Remove any unpicklable attributes from TestCase instance *case*. + """ + # Python 3.3 doesn't reset this one. + case._outcomeForDoCleanups = None + + def __init__(self, original_result): + for attr in self.__slots__: + setattr(self, attr, getattr(original_result, attr)) + for case, _ in self.expectedFailures: + self.fixup_case(case) + for case, _ in self.errors: + self.fixup_case(case) + for case, _ in self.failures: + self.fixup_case(case) + + +class _FakeStringIO(object): + """ + A trivial picklable StringIO-alike for Python 2. + """ + + def __init__(self, value): + self._value = value + + def getvalue(self): + return self._value + + +class _MinimalRunner(object): + """ + A minimal picklable object able to instantiate a runner in a + child process and run a test case with it. + """ + + def __init__(self, runner_cls, runner_args): + self.runner_cls = runner_cls + self.runner_args = runner_args + + # Python 2 doesn't know how to pickle instance methods, so we use __call__ + # instead. + + def __call__(self, test): + # Executed in child process + kwargs = self.runner_args + # Force recording of output in a buffer (it will be printed out + # by the parent). + kwargs['stream'] = StringIO() + runner = self.runner_cls(**kwargs) + result = runner._makeResult() + # Avoid child tracebacks when Ctrl-C is pressed. + signals.installHandler() + signals.registerResult(result) + result.failfast = runner.failfast + result.buffer = runner.buffer + with self.cleanup_object(test): + test(result) + # HACK as cStringIO.StringIO isn't picklable in 2.x + result.stream = _FakeStringIO(result.stream.getvalue()) + return _MinimalResult(result) + + @contextlib.contextmanager + def cleanup_object(self, test): + """ + A context manager which cleans up unwanted attributes on a test case + (or any other object). + """ + vanilla_attrs = set(test.__dict__) + try: + yield test + finally: + spurious_attrs = set(test.__dict__) - vanilla_attrs + for name in spurious_attrs: + del test.__dict__[name] + + +class ParallelTestRunner(runner.TextTestRunner): + """ + A test runner which delegates the actual running to a pool of child + processes. + """ + + resultclass = ParallelTestResult + + def __init__(self, runner_cls, **kwargs): + runner.TextTestRunner.__init__(self, **kwargs) + self.runner_cls = runner_cls + self.runner_args = kwargs + + def _run_inner(self, result): + # We hijack TextTestRunner.run()'s inner logic by passing this + # method as if it were a test case. + child_runner = _MinimalRunner(self.runner_cls, self.runner_args) + pool = multiprocessing.Pool() + imap = pool.imap_unordered + try: + for child_result in imap(child_runner, self._test_list): + result.add_results(child_result) + if child_result.shouldStop: + break + return result + finally: + # Kill the still active workers + pool.terminate() + pool.join() + + def run(self, test): + self._test_list = _flatten_suite(test) + # This will call self._run_inner() on the created result object, + # and print out the detailed test results at the end. + return super(ParallelTestRunner, self).run(self._run_inner) + + +try: + import faulthandler +except ImportError: + pass +else: + try: + # May fail in IPython Notebook with UnsupportedOperation + faulthandler.enable() + except BaseException as e: + msg = "Failed to enable faulthandler due to:\n{err}" + warnings.warn(msg.format(err=e)) diff --git a/lib/python3.11/site-packages/llvmlite/tests/refprune_proto.py b/lib/python3.11/site-packages/llvmlite/tests/refprune_proto.py new file mode 100644 index 0000000000000000000000000000000000000000..3edc58f4b42b18e4280873491bb65a0e0635b1d0 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/refprune_proto.py @@ -0,0 +1,329 @@ +""" +Contains tests and a prototype implementation for the fanout algorithm in +the LLVM refprune pass. +""" + +try: + from graphviz import Digraph +except ImportError: + pass +from collections import defaultdict + +# The entry block. It's always the same. +ENTRY = "A" + + +# The following caseNN() functions returns a 3-tuple of +# (nodes, edges, expected). +# `nodes` maps BB nodes to incref/decref inside the block. +# `edges` maps BB nodes to their successor BB. +# `expected` maps BB-node with incref to a set of BB-nodes with the decrefs, or +# the value can be None, indicating invalid prune. + +def case1(): + edges = { + "A": ["B"], + "B": ["C", "D"], + "C": [], + "D": ["E", "F"], + "E": ["G"], + "F": [], + "G": ["H", "I"], + "I": ["G", "F"], + "H": ["J", "K"], + "J": ["L", "M"], + "K": [], + "L": ["Z"], + "M": ["Z", "O", "P"], + "O": ["Z"], + "P": ["Z"], + "Z": [], + } + nodes = defaultdict(list) + nodes["D"] = ["incref"] + nodes["H"] = ["decref"] + nodes["F"] = ["decref", "decref"] + expected = {"D": {"H", "F"}} + return nodes, edges, expected + + +def case2(): + edges = { + "A": ["B", "C"], + "B": ["C"], + "C": [], + } + nodes = defaultdict(list) + nodes["A"] = ["incref"] + nodes["B"] = ["decref"] + nodes["C"] = ["decref"] + expected = {"A": None} + return nodes, edges, expected + + +def case3(): + nodes, edges, _ = case1() + # adds an invalid edge + edges["H"].append("F") + expected = {"D": None} + return nodes, edges, expected + + +def case4(): + nodes, edges, _ = case1() + # adds an invalid edge + edges["H"].append("E") + expected = {"D": None} + return nodes, edges, expected + + +def case5(): + nodes, edges, _ = case1() + # adds backedge to go before incref + edges["B"].append("I") + expected = {"D": None} + return nodes, edges, expected + + +def case6(): + nodes, edges, _ = case1() + # adds backedge to go before incref + edges["I"].append("B") + expected = {"D": None} + return nodes, edges, expected + + +def case7(): + nodes, edges, _ = case1() + # adds forward jump outside + edges["I"].append("M") + expected = {"D": None} + return nodes, edges, expected + + +def case8(): + edges = { + "A": ["B", "C"], + "B": ["C"], + "C": [], + } + nodes = defaultdict(list) + nodes["A"] = ["incref"] + nodes["C"] = ["decref"] + expected = {"A": {"C"}} + return nodes, edges, expected + + +def case9(): + nodes, edges, _ = case8() + # adds back edge + edges["C"].append("B") + expected = {"A": None} + return nodes, edges, expected + + +def case10(): + nodes, edges, _ = case8() + # adds back edge to A + edges["C"].append("A") + expected = {"A": {"C"}} + return nodes, edges, expected + + +def case11(): + nodes, edges, _ = case8() + edges["C"].append("D") + edges["D"] = [] + expected = {"A": {"C"}} + return nodes, edges, expected + + +def case12(): + nodes, edges, _ = case8() + edges["C"].append("D") + edges["D"] = ["A"] + expected = {"A": {"C"}} + return nodes, edges, expected + + +def case13(): + nodes, edges, _ = case8() + edges["C"].append("D") + edges["D"] = ["B"] + expected = {"A": None} + return nodes, edges, expected + + +def make_predecessor_map(edges): + d = defaultdict(set) + for src, outgoings in edges.items(): + for dst in outgoings: + d[dst].add(src) + return d + + +class FanoutAlgorithm: + def __init__(self, nodes, edges, verbose=False): + self.nodes = nodes + self.edges = edges + self.rev_edges = make_predecessor_map(edges) + self.print = print if verbose else self._null_print + + def run(self): + return self.find_fanout_in_function() + + def _null_print(self, *args, **kwargs): + pass + + def find_fanout_in_function(self): + got = {} + for cur_node in self.edges: + for incref in (x for x in self.nodes[cur_node] if x == "incref"): + decref_blocks = self.find_fanout(cur_node) + self.print(">>", cur_node, "===", decref_blocks) + got[cur_node] = decref_blocks + return got + + def find_fanout(self, head_node): + decref_blocks = self.find_decref_candidates(head_node) + self.print("candidates", decref_blocks) + if not decref_blocks: + return None + if not self.verify_non_overlapping( + head_node, decref_blocks, entry=ENTRY + ): + return None + return set(decref_blocks) + + def verify_non_overlapping(self, head_node, decref_blocks, entry): + self.print("verify_non_overlapping".center(80, "-")) + # reverse walk for each decref_blocks + # they should end at head_node + todo = list(decref_blocks) + while todo: + cur_node = todo.pop() + visited = set() + + workstack = [cur_node] + del cur_node + while workstack: + cur_node = workstack.pop() + self.print("cur_node", cur_node, "|", workstack) + if cur_node in visited: + continue # skip + if cur_node == entry: + # Entry node + self.print( + "!! failed because we arrived at entry", cur_node + ) + return False + visited.add(cur_node) + # check all predecessors + self.print( + f" {cur_node} preds {self.get_predecessors(cur_node)}" + ) + for pred in self.get_predecessors(cur_node): + if pred in decref_blocks: + # reject because there's a predecessor in decref_blocks + self.print( + "!! reject because predecessor in decref_blocks" + ) + return False + if pred != head_node: + + workstack.append(pred) + + return True + + def get_successors(self, node): + return tuple(self.edges[node]) + + def get_predecessors(self, node): + return tuple(self.rev_edges[node]) + + def has_decref(self, node): + return "decref" in self.nodes[node] + + def walk_child_for_decref( + self, cur_node, path_stack, decref_blocks, depth=10 + ): + indent = " " * len(path_stack) + self.print(indent, "walk", path_stack, cur_node) + if depth <= 0: + return False # missing + if cur_node in path_stack: + if cur_node == path_stack[0]: + return False # reject interior node backedge + return True # skip + if self.has_decref(cur_node): + decref_blocks.add(cur_node) + self.print(indent, "found decref") + return True + + depth -= 1 + path_stack += (cur_node,) + found = False + for child in self.get_successors(cur_node): + if not self.walk_child_for_decref( + child, path_stack, decref_blocks + ): + found = False + break + else: + found = True + + self.print(indent, f"ret {found}") + return found + + def find_decref_candidates(self, cur_node): + # Forward pass + self.print("find_decref_candidates".center(80, "-")) + path_stack = (cur_node,) + found = False + decref_blocks = set() + for child in self.get_successors(cur_node): + if not self.walk_child_for_decref( + child, path_stack, decref_blocks + ): + found = False + break + else: + found = True + if not found: + return set() + else: + return decref_blocks + + +def check_once(): + nodes, edges, expected = case13() + + # Render graph + G = Digraph() + for node in edges: + G.node(node, shape="rect", label=f"{node}\n" + r"\l".join(nodes[node])) + for node, children in edges.items(): + for child in children: + G.edge(node, child) + + G.view() + + algo = FanoutAlgorithm(nodes, edges, verbose=True) + got = algo.run() + assert expected == got + + +def check_all(): + for k, fn in list(globals().items()): + if k.startswith("case"): + print(f"{fn}".center(80, "-")) + nodes, edges, expected = fn() + algo = FanoutAlgorithm(nodes, edges) + got = algo.run() + assert expected == got + print("ALL PASSED") + + +if __name__ == "__main__": + # check_once() + check_all() diff --git a/lib/python3.11/site-packages/llvmlite/tests/test_binding.py b/lib/python3.11/site-packages/llvmlite/tests/test_binding.py new file mode 100644 index 0000000000000000000000000000000000000000..3a62c4564a8bfbc691cb725a359fa7c301807af8 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/test_binding.py @@ -0,0 +1,2431 @@ +import ctypes +import threading +from ctypes import CFUNCTYPE, c_int, c_int32 +from ctypes.util import find_library +import gc +import locale +import os +import platform +import re +import subprocess +import sys +import unittest +from contextlib import contextmanager +from tempfile import mkstemp + +from llvmlite import ir +from llvmlite import binding as llvm +from llvmlite.binding import ffi +from llvmlite.tests import TestCase + + +# arvm7l needs extra ABI symbols to link successfully +if platform.machine() == 'armv7l': + llvm.load_library_permanently('libgcc_s.so.1') + + +def no_de_locale(): + cur = locale.setlocale(locale.LC_ALL) + try: + locale.setlocale(locale.LC_ALL, 'de_DE') + except locale.Error: + return True + else: + return False + finally: + locale.setlocale(locale.LC_ALL, cur) + + +asm_sum = r""" + ; ModuleID = '' + source_filename = "asm_sum.c" + target triple = "{triple}" + %struct.glob_type = type {{ i64, [2 x i64]}} + + @glob = global i32 0 + @glob_b = global i8 0 + @glob_f = global float 1.5 + @glob_struct = global %struct.glob_type {{i64 0, [2 x i64] [i64 0, i64 0]}} + + define i32 @sum(i32 %.1, i32 %.2) {{ + %.3 = add i32 %.1, %.2 + %.4 = add i32 0, %.3 + ret i32 %.4 + }} + """ + +asm_sum2 = r""" + ; ModuleID = '' + target triple = "{triple}" + + define i32 @sum(i32 %.1, i32 %.2) {{ + %.3 = add i32 %.1, %.2 + ret i32 %.3 + }} + """ + +asm_sum3 = r""" + ; ModuleID = '' + target triple = "{triple}" + + define i64 @sum(i64 %.1, i64 %.2) {{ + %.3 = add i64 %.1, %.2 + %.4 = add i64 5, %.3 + %.5 = add i64 -5, %.4 + ret i64 %.5 + }} + """ + +asm_mul = r""" + ; ModuleID = '' + target triple = "{triple}" + @mul_glob = global i32 0 + + define i32 @mul(i32 %.1, i32 %.2) {{ + %.3 = mul i32 %.1, %.2 + ret i32 %.3 + }} + """ + +asm_square_sum = r""" + ; ModuleID = '' + target triple = "{triple}" + @mul_glob = global i32 0 + + declare i32 @sum(i32, i32) + define i32 @square_sum(i32 %.1, i32 %.2) {{ + %.3 = call i32 @sum(i32 %.1, i32 %.2) + %.4 = mul i32 %.3, %.3 + ret i32 %.4 + }} + """ + +asm_getversion = r""" + ; ModuleID = '' + target triple = "{triple}" + + declare i8* @Py_GetVersion() + + define void @getversion(i32 %.1, i32 %.2) {{ + %1 = call i8* @Py_GetVersion() + ret void + }} + """ + +if platform.python_implementation() == 'PyPy': + asm_getversion = asm_getversion.replace('Py_GetVersion', 'PyPy_GetVersion') + +# `fadd` used on integer inputs +asm_parse_error = r""" + ; ModuleID = '' + target triple = "{triple}" + + define i32 @sum(i32 %.1, i32 %.2) {{ + %.3 = fadd i32 %.1, %.2 + ret i32 %.3 + }} + """ + +# "%.bug" definition references itself +asm_verification_fail = r""" + ; ModuleID = '' + target triple = "{triple}" + + define void @sum() {{ + %.bug = add i32 1, %.bug + ret void + }} + """ + +asm_sum_declare = r""" + ; ModuleID = '' + target triple = "{triple}" + + declare i32 @sum(i32 %.1, i32 %.2) + """ + +asm_double_inaccurate = r""" + ; ModuleID = '' + target triple = "{triple}" + + define void @foo() {{ + %const = fadd fp128 0xLF3CB1CCF26FBC178452FB4EC7F91DEAD, 0xL00000000000000000000000000000001 + ret void + }} + """ # noqa E501 + +asm_double_locale = r""" + ; ModuleID = '' + target triple = "{triple}" + + define void @foo() {{ + %const = fadd double 0.0, 3.14 + ret void + }} + """ + + +asm_inlineasm = r""" + ; ModuleID = '' + target triple = "{triple}" + + define void @foo() {{ + call void asm sideeffect "nop", ""() + ret void + }} + """ + +asm_inlineasm2 = """ + ; ModuleID = '' + target triple = "{triple}" + + define void @inlineme() {{ + ret void + }} + + define i32 @caller(i32 %.1, i32 %.2) {{ + entry: + %stack = alloca i32 + store i32 %.1, i32* %stack + br label %main + main: + %loaded = load i32, i32* %stack + %.3 = add i32 %loaded, %.2 + %.4 = add i32 0, %.3 + call void @inlineme() + ret i32 %.4 + }} +""" + +asm_inlineasm3 = """ +; ModuleID = 'test.c' +source_filename = "test.c" +target triple = "{triple}" + +; Function Attrs: noinline nounwind optnone ssp uwtable +define void @inlineme() noinline !dbg !15 {{ + ret void, !dbg !18 +}} + +; Function Attrs: noinline nounwind optnone ssp uwtable +define i32 @foo(i32 %0, i32 %1) !dbg !19 {{ + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 %0, i32* %3, align 4 + call void @llvm.dbg.declare(metadata i32* %3, metadata !23, metadata !DIExpression()), !dbg !24 + store i32 %1, i32* %4, align 4 + call void @llvm.dbg.declare(metadata i32* %4, metadata !25, metadata !DIExpression()), !dbg !26 + call void @inlineme(), !dbg !27 + %5 = load i32, i32* %3, align 4, !dbg !28 + %6 = load i32, i32* %4, align 4, !dbg !29 + %7 = add nsw i32 %5, %6, !dbg !30 + ret i32 %7, !dbg !31 +}} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #1 = {{ nofree nosync nounwind readnone speculatable willreturn }} + +!llvm.module.flags = !{{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10}} +!llvm.dbg.cu = !{{!11}} +!llvm.ident = !{{!14}} + +!0 = !{{i32 2, !"SDK Version", [2 x i32] [i32 12, i32 3]}} +!1 = !{{i32 7, !"Dwarf Version", i32 4}} +!2 = !{{i32 2, !"Debug Info Version", i32 3}} +!3 = !{{i32 1, !"wchar_size", i32 4}} +!4 = !{{i32 1, !"branch-target-enforcement", i32 0}} +!5 = !{{i32 1, !"sign-return-address", i32 0}} +!6 = !{{i32 1, !"sign-return-address-all", i32 0}} +!7 = !{{i32 1, !"sign-return-address-with-bkey", i32 0}} +!8 = !{{i32 7, !"PIC Level", i32 2}} +!9 = !{{i32 7, !"uwtable", i32 1}} +!10 = !{{i32 7, !"frame-pointer", i32 1}} +!11 = distinct !DICompileUnit(language: DW_LANG_C99, file: !12, producer: "Apple clang version 13.1.6 (clang-1316.0.21.2.3)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !13, splitDebugInlining: false, nameTableKind: None, sysroot: "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk", sdk: "MacOSX.sdk") +!12 = !DIFile(filename: "test.c", directory: "/") +!13 = !{{}} +!14 = !{{!"Apple clang version 13.1.6 (clang-1316.0.21.2.3)"}} +!15 = distinct !DISubprogram(name: "inlineme", scope: !12, file: !12, line: 1, type: !16, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !13) +!16 = !DISubroutineType(types: !17) +!17 = !{{null}} +!18 = !DILocation(line: 1, column: 22, scope: !15) +!19 = distinct !DISubprogram(name: "foo", scope: !12, file: !12, line: 3, type: !20, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11, retainedNodes: !13) +!20 = !DISubroutineType(types: !21) +!21 = !{{!22, !22, !22}} +!22 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!23 = !DILocalVariable(name: "a", arg: 1, scope: !19, file: !12, line: 3, type: !22) +!24 = !DILocation(line: 3, column: 13, scope: !19) +!25 = !DILocalVariable(name: "b", arg: 2, scope: !19, file: !12, line: 3, type: !22) +!26 = !DILocation(line: 3, column: 20, scope: !19) +!27 = !DILocation(line: 4, column: 5, scope: !19) +!28 = !DILocation(line: 5, column: 12, scope: !19) +!29 = !DILocation(line: 5, column: 16, scope: !19) +!30 = !DILocation(line: 5, column: 14, scope: !19) +!31 = !DILocation(line: 5, column: 5, scope: !19) +""" # noqa E501 + +licm_asm = r""" +; ModuleID = "" +target triple = "{triple}" + +define double @licm(i32 %0) {{ + %2 = alloca i32, align 4 + %3 = alloca double, align 8 + %4 = alloca i32, align 4 + %5 = alloca double, align 8 + store i32 %0, i32* %2, align 4 + store double 0.000000e+00, double* %3, align 8 + store i32 0, i32* %4, align 4 + br label %6 + +6: ; preds = %14, %1 + %7 = load i32, i32* %4, align 4 + %8 = load i32, i32* %2, align 4 + %9 = icmp slt i32 %7, %8 + br i1 %9, label %10, label %17 + +10: ; preds = %6 + store double 7.000000e+00, double* %5, align 8 + %11 = load double, double* %5, align 8 + %12 = load double, double* %3, align 8 + %13 = fadd double %12, %11 + store double %13, double* %3, align 8 + br label %14 + +14: ; preds = %10 + %15 = load i32, i32* %4, align 4 + %16 = add nsw i32 %15, 1 + store i32 %16, i32* %4, align 4 + br label %6 + +17: ; preds = %6 + %18 = load double, double* %3, align 8 + ret double %18 +}} +""" # noqa E501 + +asm_global_ctors = r""" + ; ModuleID = "" + target triple = "{triple}" + + @A = global i32 undef + + define void @ctor_A() + {{ + store i32 10, i32* @A + ret void + }} + + define void @dtor_A() + {{ + store i32 20, i32* @A + ret void + }} + + define i32 @foo() + {{ + %.2 = load i32, i32* @A + %.3 = add i32 %.2, 2 + ret i32 %.3 + }} + + @llvm.global_ctors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @ctor_A, i8* null}}] + @llvm.global_dtors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @dtor_A, i8* null}}] + """ # noqa E501 + +asm_ext_ctors = r""" + ; ModuleID = "" + target triple = "{triple}" + + @A = external global i32 + + define void @ctor_A() + {{ + store i32 10, i32* @A + ret void + }} + + define void @dtor_A() + {{ + store i32 20, i32* @A + ret void + }} + + define i32 @foo() + {{ + %.2 = load i32, i32* @A + %.3 = add i32 %.2, 2 + ret i32 %.3 + }} + + @llvm.global_ctors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @ctor_A, i8* null}}] + @llvm.global_dtors = appending global [1 x {{i32, void ()*, i8*}}] [{{i32, void ()*, i8*}} {{i32 0, void ()* @dtor_A, i8* null}}] + """ # noqa E501 + + +asm_nonalphanum_blocklabel = """; ModuleID = "" +target triple = "unknown-unknown-unknown" +target datalayout = "" + +define i32 @"foo"() +{ +"<>!*''#": + ret i32 12345 +} +""" # noqa W291 # trailing space needed for match later + + +asm_null_constant = r""" + ; ModuleID = '' + target triple = "{triple}" + + define void @foo(i64* %.1) {{ + ret void + }} + + define void @bar() {{ + call void @foo(i64* null) + ret void + }} +""" + + +riscv_asm_ilp32 = [ + 'addi\tsp, sp, -16', + 'sw\ta1, 8(sp)', + 'sw\ta2, 12(sp)', + 'fld\tft0, 8(sp)', + 'fmv.w.x\tft1, a0', + 'fcvt.d.s\tft1, ft1', + 'fadd.d\tft0, ft1, ft0', + 'fsd\tft0, 8(sp)', + 'lw\ta0, 8(sp)', + 'lw\ta1, 12(sp)', + 'addi\tsp, sp, 16', + 'ret' +] + + +riscv_asm_ilp32f = [ + 'addi\tsp, sp, -16', + 'sw\ta0, 8(sp)', + 'sw\ta1, 12(sp)', + 'fld\tft0, 8(sp)', + 'fcvt.d.s\tft1, fa0', + 'fadd.d\tft0, ft1, ft0', + 'fsd\tft0, 8(sp)', + 'lw\ta0, 8(sp)', + 'lw\ta1, 12(sp)', + 'addi\tsp, sp, 16', + 'ret' +] + + +riscv_asm_ilp32d = [ + 'fcvt.d.s\tft0, fa0', + 'fadd.d\tfa0, ft0, fa1', + 'ret' +] + + +asm_attributes = r""" +declare void @a_readonly_func(i8 *) readonly + +declare i8* @a_arg0_return_func(i8* returned, i32*) +""" + + +# This produces the following output from objdump: +# +# $ objdump -D 632.elf +# +# 632.elf: file format elf64-x86-64 +# +# +# Disassembly of section .text: +# +# 0000000000000000 <__arybo>: +# 0: 48 c1 e2 20 shl $0x20,%rdx +# 4: 48 09 c2 or %rax,%rdx +# 7: 48 89 d0 mov %rdx,%rax +# a: 48 c1 c0 3d rol $0x3d,%rax +# e: 48 31 d0 xor %rdx,%rax +# 11: 48 b9 01 20 00 04 80 movabs $0x7010008004002001,%rcx +# 18: 00 10 70 +# 1b: 48 0f af c8 imul %rax,%rcx + +issue_632_elf = \ + "7f454c4602010100000000000000000001003e00010000000000000000000000000000" \ + "0000000000e0000000000000000000000040000000000040000500010048c1e2204809" \ + "c24889d048c1c03d4831d048b90120000480001070480fafc800000000000000000000" \ + "0000000000000000000000000000002f0000000400f1ff000000000000000000000000" \ + "00000000070000001200020000000000000000001f00000000000000002e7465787400" \ + "5f5f617279626f002e6e6f74652e474e552d737461636b002e737472746162002e7379" \ + "6d746162003c737472696e673e00000000000000000000000000000000000000000000" \ + "0000000000000000000000000000000000000000000000000000000000000000000000" \ + "00000000000000001f0000000300000000000000000000000000000000000000a80000" \ + "0000000000380000000000000000000000000000000100000000000000000000000000" \ + "000001000000010000000600000000000000000000000000000040000000000000001f" \ + "000000000000000000000000000000100000000000000000000000000000000f000000" \ + "01000000000000000000000000000000000000005f0000000000000000000000000000" \ + "0000000000000000000100000000000000000000000000000027000000020000000000" \ + "0000000000000000000000000000600000000000000048000000000000000100000002" \ + "00000008000000000000001800000000000000" + + +issue_632_text = \ + "48c1e2204809c24889d048c1c03d4831d048b90120000480001070480fafc8" + + +asm_tli_exp2 = r""" +; ModuleID = '' +source_filename = "" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +declare float @llvm.exp2.f32(float %casted) + +define float @foo(i16 %arg) { +entry: + %casted = sitofp i16 %arg to float + %ret = call float @llvm.exp2.f32(float %casted) + ret float %ret +} +""" # noqa E501 + + +class BaseTest(TestCase): + + def setUp(self): + llvm.initialize() + llvm.initialize_native_target() + llvm.initialize_native_asmprinter() + gc.collect() + self.old_garbage = gc.garbage[:] + gc.garbage[:] = [] + + def tearDown(self): + # Test that no uncollectable objects were created + # (llvmlite objects have a __del__ so a reference cycle could + # create some). + gc.collect() + self.assertEqual(gc.garbage, []) + # This will probably put any existing garbage in gc.garbage again + del self.old_garbage + + def module(self, asm=asm_sum, context=None): + asm = asm.format(triple=llvm.get_default_triple()) + mod = llvm.parse_assembly(asm, context) + return mod + + def glob(self, name='glob', mod=None): + if mod is None: + mod = self.module() + return mod.get_global_variable(name) + + def target_machine(self, *, jit): + target = llvm.Target.from_default_triple() + return target.create_target_machine(jit=jit) + + +class TestDependencies(BaseTest): + """ + Test DLL dependencies are within a certain expected set. + """ + + @unittest.skipUnless(sys.platform.startswith('linux'), + "Linux-specific test") + @unittest.skipUnless(os.environ.get('LLVMLITE_DIST_TEST'), + "Distribution-specific test") + def test_linux(self): + lib_path = ffi.lib._name + env = os.environ.copy() + env['LANG'] = 'C' + p = subprocess.Popen(["objdump", "-p", lib_path], + stdout=subprocess.PIPE, env=env) + out, _ = p.communicate() + self.assertEqual(0, p.returncode) + # Parse library dependencies + lib_pat = re.compile(r'^([-_a-zA-Z0-9]+)\.so(?:\.\d+){0,3}$') + deps = set() + for line in out.decode().splitlines(): + parts = line.split() + if parts and parts[0] == 'NEEDED': + dep = parts[1] + m = lib_pat.match(dep) + if len(parts) != 2 or not m: + self.fail("invalid NEEDED line: %r" % (line,)) + deps.add(m.group(1)) + # Sanity check that our dependencies were parsed ok + if 'libc' not in deps or 'libpthread' not in deps: + self.fail("failed parsing dependencies? got %r" % (deps,)) + # Ensure all dependencies are expected + allowed = set(['librt', 'libdl', 'libpthread', 'libz', 'libm', + 'libgcc_s', 'libc', 'ld-linux', 'ld64']) + if platform.python_implementation() == 'PyPy': + allowed.add('libtinfo') + + for dep in deps: + if not dep.startswith('ld-linux-') and dep not in allowed: + self.fail("unexpected dependency %r in %r" % (dep, deps)) + + +class TestRISCVABI(BaseTest): + """ + Test calling convention of floating point arguments of RISC-V + using different ABI. + """ + triple = "riscv32-unknown-linux" + + def setUp(self): + super().setUp() + llvm.initialize_all_targets() + llvm.initialize_all_asmprinters() + + def check_riscv_target(self): + try: + llvm.Target.from_triple(self.triple) + except RuntimeError as e: + if "No available targets are compatible with triple" in str(e): + self.skipTest("RISCV target unsupported by linked LLVM.") + else: + raise e + + def riscv_target_machine(self, **kwarg): + lltarget = llvm.Target.from_triple(self.triple) + return lltarget.create_target_machine(**kwarg) + + def fpadd_ll_module(self): + f64 = ir.DoubleType() + f32 = ir.FloatType() + fnty = ir.FunctionType(f64, (f32, f64)) + module = ir.Module() + func = ir.Function(module, fnty, name="fpadd") + block = func.append_basic_block() + builder = ir.IRBuilder(block) + a, b = func.args + arg0 = builder.fpext(a, f64) + result = builder.fadd(arg0, b) + builder.ret(result) + + llmod = llvm.parse_assembly(str(module)) + llmod.verify() + return llmod + + def break_up_asm(self, asm): + asm_list = [] + for line in asm.splitlines(): + s_line = line.strip() + if not (s_line.startswith(".") or s_line.startswith("fpadd") + or s_line == ""): + asm_list.append(s_line) + return asm_list + + def test_rv32d_ilp32(self): + self.check_riscv_target() + llmod = self.fpadd_ll_module() + target = self.riscv_target_machine(features="+f,+d") + self.assertEqual(self.break_up_asm(target.emit_assembly(llmod)), + riscv_asm_ilp32) + + def test_rv32d_ilp32f(self): + self.check_riscv_target() + llmod = self.fpadd_ll_module() + target = self.riscv_target_machine(features="+f,+d", abiname="ilp32f") + self.assertEqual(self.break_up_asm(target.emit_assembly(llmod)), + riscv_asm_ilp32f) + + def test_rv32d_ilp32d(self): + self.check_riscv_target() + llmod = self.fpadd_ll_module() + target = self.riscv_target_machine(features="+f,+d", abiname="ilp32d") + self.assertEqual(self.break_up_asm(target.emit_assembly(llmod)), + riscv_asm_ilp32d) + + +class TestMisc(BaseTest): + """ + Test miscellaneous functions in llvm.binding. + """ + + def test_parse_assembly(self): + self.module(asm_sum) + + def test_parse_assembly_error(self): + with self.assertRaises(RuntimeError) as cm: + self.module(asm_parse_error) + s = str(cm.exception) + self.assertIn("parsing error", s) + self.assertIn("invalid operand type", s) + + def test_nonalphanum_block_name(self): + mod = ir.Module() + ft = ir.FunctionType(ir.IntType(32), []) + fn = ir.Function(mod, ft, "foo") + bd = ir.IRBuilder(fn.append_basic_block(name="<>!*''#")) + bd.ret(ir.Constant(ir.IntType(32), 12345)) + asm = str(mod) + self.assertEqual(asm, asm_nonalphanum_blocklabel) + + def test_global_context(self): + gcontext1 = llvm.context.get_global_context() + gcontext2 = llvm.context.get_global_context() + assert gcontext1 == gcontext2 + + def test_dylib_symbols(self): + llvm.add_symbol("__xyzzy", 1234) + llvm.add_symbol("__xyzzy", 5678) + addr = llvm.address_of_symbol("__xyzzy") + self.assertEqual(addr, 5678) + addr = llvm.address_of_symbol("__foobar") + self.assertIs(addr, None) + + def test_get_default_triple(self): + triple = llvm.get_default_triple() + self.assertIsInstance(triple, str) + self.assertTrue(triple) + + def test_get_process_triple(self): + # Sometimes we get synonyms for PPC + def normalize_ppc(arch): + if arch == 'powerpc64le': + return 'ppc64le' + else: + return arch + + triple = llvm.get_process_triple() + default = llvm.get_default_triple() + self.assertIsInstance(triple, str) + self.assertTrue(triple) + + default_arch = normalize_ppc(default.split('-')[0]) + triple_arch = normalize_ppc(triple.split('-')[0]) + # Arch must be equal + self.assertEqual(default_arch, triple_arch) + + def test_get_host_cpu_features(self): + features = llvm.get_host_cpu_features() + # Check the content of `features` + self.assertIsInstance(features, dict) + self.assertIsInstance(features, llvm.FeatureMap) + for k, v in features.items(): + self.assertIsInstance(k, str) + self.assertTrue(k) # single feature string cannot be empty + self.assertIsInstance(v, bool) + self.assertIsInstance(features.flatten(), str) + + re_term = r"[+\-][a-zA-Z0-9\._-]+" + regex = r"^({0}|{0}(,{0})*)?$".format(re_term) + # quick check for our regex + self.assertIsNotNone(re.match(regex, "")) + self.assertIsNotNone(re.match(regex, "+aa")) + self.assertIsNotNone(re.match(regex, "+a,-bb")) + # check CpuFeature.flatten() + if len(features) == 0: + self.assertEqual(features.flatten(), "") + else: + self.assertIsNotNone(re.match(regex, features.flatten())) + + def test_get_host_cpu_name(self): + cpu = llvm.get_host_cpu_name() + self.assertIsInstance(cpu, str) + self.assertTrue(cpu) + + def test_initfini(self): + code = """if 1: + from llvmlite import binding as llvm + + llvm.initialize() + llvm.initialize_native_target() + llvm.initialize_native_asmprinter() + llvm.initialize_all_targets() + llvm.initialize_all_asmprinters() + llvm.shutdown() + """ + subprocess.check_call([sys.executable, "-c", code]) + + def test_set_option(self): + # We cannot set an option multiple times (LLVM would exit() the + # process), so run the code in a subprocess. + code = """if 1: + from llvmlite import binding as llvm + + llvm.set_option("progname", "-debug-pass=Disabled") + """ + subprocess.check_call([sys.executable, "-c", code]) + + def test_version(self): + major, minor, patch = llvm.llvm_version_info + # one of these can be valid + valid = [(14, )] + self.assertIn((major,), valid) + self.assertIn(patch, range(10)) + + def test_check_jit_execution(self): + llvm.check_jit_execution() + + @unittest.skipIf(no_de_locale(), "Locale not available") + def test_print_double_locale(self): + m = self.module(asm_double_locale) + expect = str(m) + # Change the locale so that comma is used as decimal-point + # to trigger the LLVM bug (llvmlite issue #80) + locale.setlocale(locale.LC_ALL, 'de_DE') + # The LLVM bug is trigged by print the module with double constant + got = str(m) + # Changing the locale should not affect the LLVM IR + self.assertEqual(expect, got) + + def test_no_accidental_warnings(self): + code = "from llvmlite import binding" + flags = "-Werror" + cmdargs = [sys.executable, flags, "-c", code] + subprocess.check_call(cmdargs) + + +class TestModuleRef(BaseTest): + + def test_str(self): + mod = self.module() + s = str(mod).strip() + self.assertTrue(s.startswith('; ModuleID ='), s) + + def test_close(self): + mod = self.module() + str(mod) + mod.close() + with self.assertRaises(ctypes.ArgumentError): + str(mod) + mod.close() + + def test_with(self): + mod = self.module() + str(mod) + with mod: + str(mod) + with self.assertRaises(ctypes.ArgumentError): + str(mod) + with self.assertRaises(RuntimeError): + with mod: + pass + + def test_name(self): + mod = self.module() + mod.name = "foo" + self.assertEqual(mod.name, "foo") + mod.name = "bar" + self.assertEqual(mod.name, "bar") + + def test_source_file(self): + mod = self.module() + self.assertEqual(mod.source_file, "asm_sum.c") + + def test_data_layout(self): + mod = self.module() + s = mod.data_layout + self.assertIsInstance(s, str) + mod.data_layout = s + self.assertEqual(s, mod.data_layout) + + def test_triple(self): + mod = self.module() + s = mod.triple + self.assertEqual(s, llvm.get_default_triple()) + mod.triple = '' + self.assertEqual(mod.triple, '') + + def test_verify(self): + # Verify successful + mod = self.module() + self.assertIs(mod.verify(), None) + # Verify failed + mod = self.module(asm_verification_fail) + with self.assertRaises(RuntimeError) as cm: + mod.verify() + s = str(cm.exception) + self.assertIn("%.bug = add i32 1, %.bug", s) + + def test_get_function(self): + mod = self.module() + fn = mod.get_function("sum") + self.assertIsInstance(fn, llvm.ValueRef) + self.assertEqual(fn.name, "sum") + + with self.assertRaises(NameError): + mod.get_function("foo") + + # Check that fn keeps the module instance alive + del mod + str(fn.module) + + def test_get_struct_type(self): + mod = self.module() + st_ty = mod.get_struct_type("struct.glob_type") + self.assertEqual(st_ty.name, "struct.glob_type") + # also match struct names of form "%struct.glob_type.{some_index}" + self.assertIsNotNone(re.match( + r'%struct\.glob_type(\.[\d]+)? = type { i64, \[2 x i64\] }', + str(st_ty))) + + with self.assertRaises(NameError): + mod.get_struct_type("struct.doesnt_exist") + + def test_get_global_variable(self): + mod = self.module() + gv = mod.get_global_variable("glob") + self.assertIsInstance(gv, llvm.ValueRef) + self.assertEqual(gv.name, "glob") + + with self.assertRaises(NameError): + mod.get_global_variable("bar") + + # Check that gv keeps the module instance alive + del mod + str(gv.module) + + def test_global_variables(self): + mod = self.module() + it = mod.global_variables + del mod + globs = sorted(it, key=lambda value: value.name) + self.assertEqual(len(globs), 4) + self.assertEqual([g.name for g in globs], + ["glob", "glob_b", "glob_f", "glob_struct"]) + + def test_functions(self): + mod = self.module() + it = mod.functions + del mod + funcs = list(it) + self.assertEqual(len(funcs), 1) + self.assertEqual(funcs[0].name, "sum") + + def test_structs(self): + mod = self.module() + it = mod.struct_types + del mod + structs = list(it) + self.assertEqual(len(structs), 1) + self.assertIsNotNone(re.match(r'struct\.glob_type(\.[\d]+)?', + structs[0].name)) + self.assertIsNotNone(re.match( + r'%struct\.glob_type(\.[\d]+)? = type { i64, \[2 x i64\] }', + str(structs[0]))) + + def test_link_in(self): + dest = self.module() + src = self.module(asm_mul) + dest.link_in(src) + self.assertEqual( + sorted(f.name for f in dest.functions), ["mul", "sum"]) + dest.get_function("mul") + dest.close() + with self.assertRaises(ctypes.ArgumentError): + src.get_function("mul") + + def test_link_in_preserve(self): + dest = self.module() + src2 = self.module(asm_mul) + dest.link_in(src2, preserve=True) + self.assertEqual( + sorted(f.name for f in dest.functions), ["mul", "sum"]) + dest.close() + self.assertEqual(sorted(f.name for f in src2.functions), ["mul"]) + src2.get_function("mul") + + def test_link_in_error(self): + # Raise an error by trying to link two modules with the same global + # definition "sum". + dest = self.module() + src = self.module(asm_sum2) + with self.assertRaises(RuntimeError) as cm: + dest.link_in(src) + self.assertIn("symbol multiply defined", str(cm.exception)) + + def test_as_bitcode(self): + mod = self.module() + bc = mod.as_bitcode() + # Refer to http://llvm.org/docs/doxygen/html/ReaderWriter_8h_source.html#l00064 # noqa E501 + # and http://llvm.org/docs/doxygen/html/ReaderWriter_8h_source.html#l00092 # noqa E501 + bitcode_wrapper_magic = b'\xde\xc0\x17\x0b' + bitcode_magic = b'BC' + self.assertTrue(bc.startswith(bitcode_magic) or + bc.startswith(bitcode_wrapper_magic)) + + def test_parse_bitcode_error(self): + with self.assertRaises(RuntimeError) as cm: + llvm.parse_bitcode(b"") + self.assertIn("LLVM bitcode parsing error", str(cm.exception)) + # for llvm < 9 + if llvm.llvm_version_info[0] < 9: + self.assertIn("Invalid bitcode signature", str(cm.exception)) + else: + self.assertIn( + "file too small to contain bitcode header", str(cm.exception), + ) + + def test_bitcode_roundtrip(self): + # create a new context to avoid struct renaming + context1 = llvm.create_context() + bc = self.module(context=context1).as_bitcode() + context2 = llvm.create_context() + mod = llvm.parse_bitcode(bc, context2) + self.assertEqual(mod.as_bitcode(), bc) + + mod.get_function("sum") + mod.get_global_variable("glob") + + def test_cloning(self): + m = self.module() + cloned = m.clone() + self.assertIsNot(cloned, m) + self.assertEqual(cloned.as_bitcode(), m.as_bitcode()) + + +class JITTestMixin(object): + """ + Mixin for ExecutionEngine tests. + """ + + def get_sum(self, ee, func_name="sum"): + ee.finalize_object() + cfptr = ee.get_function_address(func_name) + self.assertTrue(cfptr) + return CFUNCTYPE(c_int, c_int, c_int)(cfptr) + + def test_run_code(self): + mod = self.module() + with self.jit(mod) as ee: + cfunc = self.get_sum(ee) + res = cfunc(2, -5) + self.assertEqual(-3, res) + + def test_close(self): + ee = self.jit(self.module()) + ee.close() + ee.close() + with self.assertRaises(ctypes.ArgumentError): + ee.finalize_object() + + def test_with(self): + ee = self.jit(self.module()) + with ee: + pass + with self.assertRaises(RuntimeError): + with ee: + pass + with self.assertRaises(ctypes.ArgumentError): + ee.finalize_object() + + def test_module_lifetime(self): + mod = self.module() + ee = self.jit(mod) + ee.close() + mod.close() + + def test_module_lifetime2(self): + mod = self.module() + ee = self.jit(mod) + mod.close() + ee.close() + + def test_add_module(self): + ee = self.jit(self.module()) + mod = self.module(asm_mul) + ee.add_module(mod) + with self.assertRaises(KeyError): + ee.add_module(mod) + self.assertFalse(mod.closed) + ee.close() + self.assertTrue(mod.closed) + + def test_add_module_lifetime(self): + ee = self.jit(self.module()) + mod = self.module(asm_mul) + ee.add_module(mod) + mod.close() + ee.close() + + def test_add_module_lifetime2(self): + ee = self.jit(self.module()) + mod = self.module(asm_mul) + ee.add_module(mod) + ee.close() + mod.close() + + def test_remove_module(self): + ee = self.jit(self.module()) + mod = self.module(asm_mul) + ee.add_module(mod) + ee.remove_module(mod) + with self.assertRaises(KeyError): + ee.remove_module(mod) + self.assertFalse(mod.closed) + ee.close() + self.assertFalse(mod.closed) + + def test_target_data(self): + mod = self.module() + ee = self.jit(mod) + td = ee.target_data + # A singleton is returned + self.assertIs(ee.target_data, td) + str(td) + del mod, ee + str(td) + + def test_target_data_abi_enquiries(self): + mod = self.module() + ee = self.jit(mod) + td = ee.target_data + gv_i32 = mod.get_global_variable("glob") + gv_i8 = mod.get_global_variable("glob_b") + gv_struct = mod.get_global_variable("glob_struct") + # A global is a pointer, it has the ABI size of a pointer + pointer_size = 4 if sys.maxsize < 2 ** 32 else 8 + for g in (gv_i32, gv_i8, gv_struct): + self.assertEqual(td.get_abi_size(g.type), pointer_size) + + self.assertEqual(td.get_pointee_abi_size(gv_i32.type), 4) + self.assertEqual(td.get_pointee_abi_alignment(gv_i32.type), 4) + + self.assertEqual(td.get_pointee_abi_size(gv_i8.type), 1) + self.assertIn(td.get_pointee_abi_alignment(gv_i8.type), (1, 2, 4)) + + self.assertEqual(td.get_pointee_abi_size(gv_struct.type), 24) + self.assertIn(td.get_pointee_abi_alignment(gv_struct.type), (4, 8)) + + def test_object_cache_notify(self): + notifies = [] + + def notify(mod, buf): + notifies.append((mod, buf)) + + mod = self.module() + ee = self.jit(mod) + ee.set_object_cache(notify) + + self.assertEqual(len(notifies), 0) + cfunc = self.get_sum(ee) + cfunc(2, -5) + self.assertEqual(len(notifies), 1) + # The right module object was found + self.assertIs(notifies[0][0], mod) + self.assertIsInstance(notifies[0][1], bytes) + + notifies[:] = [] + mod2 = self.module(asm_mul) + ee.add_module(mod2) + cfunc = self.get_sum(ee, "mul") + self.assertEqual(len(notifies), 1) + # The right module object was found + self.assertIs(notifies[0][0], mod2) + self.assertIsInstance(notifies[0][1], bytes) + + def test_object_cache_getbuffer(self): + notifies = [] + getbuffers = [] + + def notify(mod, buf): + notifies.append((mod, buf)) + + def getbuffer(mod): + getbuffers.append(mod) + + mod = self.module() + ee = self.jit(mod) + ee.set_object_cache(notify, getbuffer) + + # First return None from getbuffer(): the object is compiled normally + self.assertEqual(len(notifies), 0) + self.assertEqual(len(getbuffers), 0) + cfunc = self.get_sum(ee) + self.assertEqual(len(notifies), 1) + self.assertEqual(len(getbuffers), 1) + self.assertIs(getbuffers[0], mod) + sum_buffer = notifies[0][1] + + # Recreate a new EE, and use getbuffer() to return the previously + # compiled object. + + def getbuffer_successful(mod): + getbuffers.append(mod) + return sum_buffer + + notifies[:] = [] + getbuffers[:] = [] + # Use another source module to make sure it is ignored + mod = self.module(asm_mul) + ee = self.jit(mod) + ee.set_object_cache(notify, getbuffer_successful) + + self.assertEqual(len(notifies), 0) + self.assertEqual(len(getbuffers), 0) + cfunc = self.get_sum(ee) + self.assertEqual(cfunc(2, -5), -3) + self.assertEqual(len(notifies), 0) + self.assertEqual(len(getbuffers), 1) + + +class JITWithTMTestMixin(JITTestMixin): + + def test_emit_assembly(self): + """Test TargetMachineRef.emit_assembly()""" + target_machine = self.target_machine(jit=True) + mod = self.module() + ee = self.jit(mod, target_machine) # noqa F841 # Keeps pointers alive + raw_asm = target_machine.emit_assembly(mod) + self.assertIn("sum", raw_asm) + target_machine.set_asm_verbosity(True) + raw_asm_verbose = target_machine.emit_assembly(mod) + self.assertIn("sum", raw_asm) + self.assertNotEqual(raw_asm, raw_asm_verbose) + + def test_emit_object(self): + """Test TargetMachineRef.emit_object()""" + target_machine = self.target_machine(jit=True) + mod = self.module() + ee = self.jit(mod, target_machine) # noqa F841 # Keeps pointers alive + code_object = target_machine.emit_object(mod) + self.assertIsInstance(code_object, bytes) + if sys.platform.startswith('linux'): + # Sanity check + self.assertIn(b"ELF", code_object[:10]) + + +class TestMCJit(BaseTest, JITWithTMTestMixin): + """ + Test JIT engines created with create_mcjit_compiler(). + """ + + def jit(self, mod, target_machine=None): + if target_machine is None: + target_machine = self.target_machine(jit=True) + return llvm.create_mcjit_compiler(mod, target_machine) + + +# There are some memory corruption issues with OrcJIT on AArch64 - see Issue +# #1000. Since OrcJIT is experimental, and we don't test regularly during +# llvmlite development on non-x86 platforms, it seems safest to skip these +# tests on non-x86 platforms. +@unittest.skipUnless(platform.machine().startswith("x86"), "x86 only") +class TestOrcLLJIT(BaseTest): + + def jit(self, asm=asm_sum, func_name="sum", target_machine=None, + add_process=False, func_type=CFUNCTYPE(c_int, c_int, c_int), + suppress_errors=False): + lljit = llvm.create_lljit_compiler(target_machine, + use_jit_link=False, + suppress_errors=suppress_errors) + builder = llvm.JITLibraryBuilder() + if add_process: + builder.add_current_process() + rt = builder\ + .add_ir(asm.format(triple=llvm.get_default_triple()))\ + .export_symbol(func_name)\ + .link(lljit, func_name) + cfptr = rt[func_name] + self.assertTrue(cfptr) + self.assertEqual(func_name, rt.name) + return lljit, rt, func_type(cfptr) + + # From test_dylib_symbols + def test_define_symbol(self): + lljit = llvm.create_lljit_compiler() + rt = llvm.JITLibraryBuilder().import_symbol("__xyzzy", 1234)\ + .export_symbol("__xyzzy").link(lljit, "foo") + self.assertEqual(rt["__xyzzy"], 1234) + + def test_lookup_undefined_symbol_fails(self): + lljit = llvm.create_lljit_compiler() + with self.assertRaisesRegex(RuntimeError, 'No such library'): + lljit.lookup("foo", "__foobar") + rt = llvm.JITLibraryBuilder().import_symbol("__xyzzy", 1234)\ + .export_symbol("__xyzzy").link(lljit, "foo") + self.assertNotEqual(rt["__xyzzy"], 0) + with self.assertRaisesRegex(RuntimeError, + 'Symbols not found.*__foobar'): + lljit.lookup("foo", "__foobar") + + def test_jit_link(self): + if sys.platform == "win32": + with self.assertRaisesRegex(RuntimeError, + 'JITLink .* Windows'): + llvm.create_lljit_compiler(use_jit_link=True) + else: + self.assertIsNotNone(llvm.create_lljit_compiler(use_jit_link=True)) + + def test_run_code(self): + (lljit, rt, cfunc) = self.jit() + with lljit: + res = cfunc(2, -5) + self.assertEqual(-3, res) + + def test_close(self): + (lljit, rt, cfunc) = self.jit() + lljit.close() + lljit.close() + with self.assertRaises(AssertionError): + lljit.lookup("foo", "fn") + + def test_with(self): + (lljit, rt, cfunc) = self.jit() + with lljit: + pass + with self.assertRaises(RuntimeError): + with lljit: + pass + with self.assertRaises(AssertionError): + lljit.lookup("foo", "fn") + + def test_add_ir_module(self): + (lljit, rt_sum, cfunc_sum) = self.jit() + rt_mul = llvm.JITLibraryBuilder() \ + .add_ir(asm_mul.format(triple=llvm.get_default_triple())) \ + .export_symbol("mul") \ + .link(lljit, "mul") + res = CFUNCTYPE(c_int, c_int, c_int)(rt_mul["mul"])(2, -5) + self.assertEqual(-10, res) + self.assertNotEqual(lljit.lookup("sum", "sum")["sum"], 0) + self.assertNotEqual(lljit.lookup("mul", "mul")["mul"], 0) + with self.assertRaises(RuntimeError): + lljit.lookup("sum", "mul") + with self.assertRaises(RuntimeError): + lljit.lookup("mul", "sum") + + def test_remove_module(self): + (lljit, rt_sum, _) = self.jit() + del rt_sum + gc.collect() + with self.assertRaises(RuntimeError): + lljit.lookup("sum", "sum") + lljit.close() + + def test_lib_depends(self): + (lljit, rt_sum, cfunc_sum) = self.jit() + rt_mul = llvm.JITLibraryBuilder() \ + .add_ir(asm_square_sum.format(triple=llvm.get_default_triple())) \ + .export_symbol("square_sum") \ + .add_jit_library("sum") \ + .link(lljit, "square_sum") + res = CFUNCTYPE(c_int, c_int, c_int)(rt_mul["square_sum"])(2, -5) + self.assertEqual(9, res) + + def test_target_data(self): + (lljit, rt, _) = self.jit() + td = lljit.target_data + # A singleton is returned + self.assertIs(lljit.target_data, td) + str(td) + del lljit + str(td) + + def test_global_ctors_dtors(self): + # test issue #303 + # (https://github.com/numba/llvmlite/issues/303) + shared_value = c_int32(0) + lljit = llvm.create_lljit_compiler() + builder = llvm.JITLibraryBuilder() + rt = builder \ + .add_ir(asm_ext_ctors.format(triple=llvm.get_default_triple())) \ + .import_symbol("A", ctypes.addressof(shared_value)) \ + .export_symbol("foo") \ + .link(lljit, "foo") + foo = rt["foo"] + self.assertTrue(foo) + self.assertEqual(CFUNCTYPE(c_int)(foo)(), 12) + del rt + self.assertNotEqual(shared_value.value, 20) + + def test_lookup_current_process_symbol_fails(self): + # An attempt to lookup a symbol in the current process (Py_GetVersion, + # in this case) should fail with an appropriate error if we have not + # enabled searching the current process for symbols. + msg = 'Failed to materialize symbols:.*getversion' + with self.assertRaisesRegex(RuntimeError, msg): + self.jit(asm_getversion, "getversion", suppress_errors=True) + + def test_lookup_current_process_symbol(self): + self.jit(asm_getversion, "getversion", None, True) + + def test_thread_safe(self): + lljit = llvm.create_lljit_compiler() + llvm_ir = asm_sum.format(triple=llvm.get_default_triple()) + + def compile_many(i): + def do_work(): + tracking = [] + for c in range(50): + tracking.append(llvm.JITLibraryBuilder() + .add_ir(llvm_ir) + .export_symbol("sum") + .link(lljit, f"sum_{i}_{c}")) + + return do_work + + ths = [threading.Thread(target=compile_many(i)) + for i in range(os.cpu_count())] + for th in ths: + th.start() + for th in ths: + th.join() + + def test_add_object_file(self): + target_machine = self.target_machine(jit=False) + mod = self.module() + lljit = llvm.create_lljit_compiler(target_machine) + rt = llvm.JITLibraryBuilder()\ + .add_object_img(target_machine.emit_object(mod))\ + .export_symbol("sum")\ + .link(lljit, "sum") + sum = CFUNCTYPE(c_int, c_int, c_int)(rt["sum"]) + self.assertEqual(sum(2, 3), 5) + + def test_add_object_file_from_filesystem(self): + target_machine = self.target_machine(jit=False) + mod = self.module() + obj_bin = target_machine.emit_object(mod) + temp_desc, temp_path = mkstemp() + + try: + with os.fdopen(temp_desc, "wb") as f: + f.write(obj_bin) + lljit = llvm.create_lljit_compiler(target_machine) + rt = llvm.JITLibraryBuilder() \ + .add_object_file(temp_path) \ + .export_symbol("sum") \ + .link(lljit, "sum") + sum = CFUNCTYPE(c_int, c_int, c_int)(rt["sum"]) + self.assertEqual(sum(2, 3), 5) + finally: + os.unlink(temp_path) + + +class TestValueRef(BaseTest): + + def test_str(self): + mod = self.module() + glob = mod.get_global_variable("glob") + self.assertEqual(str(glob), "@glob = global i32 0") + + def test_name(self): + mod = self.module() + glob = mod.get_global_variable("glob") + self.assertEqual(glob.name, "glob") + glob.name = "foobar" + self.assertEqual(glob.name, "foobar") + + def test_linkage(self): + mod = self.module() + glob = mod.get_global_variable("glob") + linkage = glob.linkage + self.assertIsInstance(glob.linkage, llvm.Linkage) + glob.linkage = linkage + self.assertEqual(glob.linkage, linkage) + for linkage in ("internal", "external"): + glob.linkage = linkage + self.assertIsInstance(glob.linkage, llvm.Linkage) + self.assertEqual(glob.linkage.name, linkage) + + def test_visibility(self): + mod = self.module() + glob = mod.get_global_variable("glob") + visibility = glob.visibility + self.assertIsInstance(glob.visibility, llvm.Visibility) + glob.visibility = visibility + self.assertEqual(glob.visibility, visibility) + for visibility in ("hidden", "protected", "default"): + glob.visibility = visibility + self.assertIsInstance(glob.visibility, llvm.Visibility) + self.assertEqual(glob.visibility.name, visibility) + + def test_storage_class(self): + mod = self.module() + glob = mod.get_global_variable("glob") + storage_class = glob.storage_class + self.assertIsInstance(glob.storage_class, llvm.StorageClass) + glob.storage_class = storage_class + self.assertEqual(glob.storage_class, storage_class) + for storage_class in ("dllimport", "dllexport", "default"): + glob.storage_class = storage_class + self.assertIsInstance(glob.storage_class, llvm.StorageClass) + self.assertEqual(glob.storage_class.name, storage_class) + + def test_add_function_attribute(self): + mod = self.module() + fn = mod.get_function("sum") + fn.add_function_attribute("nocapture") + with self.assertRaises(ValueError) as raises: + fn.add_function_attribute("zext") + self.assertEqual(str(raises.exception), "no such attribute 'zext'") + + def test_module(self): + mod = self.module() + glob = mod.get_global_variable("glob") + self.assertIs(glob.module, mod) + + def test_type(self): + mod = self.module() + glob = mod.get_global_variable("glob") + tp = glob.type + self.assertIsInstance(tp, llvm.TypeRef) + + def test_type_name(self): + mod = self.module() + glob = mod.get_global_variable("glob") + tp = glob.type + self.assertEqual(tp.name, "") + st = mod.get_global_variable("glob_struct") + self.assertIsNotNone(re.match(r"struct\.glob_type(\.[\d]+)?", + st.type.element_type.name)) + + def test_type_printing_variable(self): + mod = self.module() + glob = mod.get_global_variable("glob") + tp = glob.type + self.assertEqual(str(tp), 'i32*') + + def test_type_printing_function(self): + mod = self.module() + fn = mod.get_function("sum") + self.assertEqual(str(fn.type), "i32 (i32, i32)*") + + def test_type_printing_struct(self): + mod = self.module() + st = mod.get_global_variable("glob_struct") + self.assertTrue(st.type.is_pointer) + self.assertIsNotNone(re.match(r'%struct\.glob_type(\.[\d]+)?\*', + str(st.type))) + self.assertIsNotNone(re.match( + r"%struct\.glob_type(\.[\d]+)? = type { i64, \[2 x i64\] }", + str(st.type.element_type))) + + def test_close(self): + glob = self.glob() + glob.close() + glob.close() + + def test_is_declaration(self): + defined = self.module().get_function('sum') + declared = self.module(asm_sum_declare).get_function('sum') + self.assertFalse(defined.is_declaration) + self.assertTrue(declared.is_declaration) + + def test_module_global_variables(self): + mod = self.module(asm_sum) + gvars = list(mod.global_variables) + self.assertEqual(len(gvars), 4) + for v in gvars: + self.assertTrue(v.is_global) + + def test_module_functions(self): + mod = self.module() + funcs = list(mod.functions) + self.assertEqual(len(funcs), 1) + func = funcs[0] + self.assertTrue(func.is_function) + self.assertEqual(func.name, 'sum') + + with self.assertRaises(ValueError): + func.instructions + with self.assertRaises(ValueError): + func.operands + with self.assertRaises(ValueError): + func.opcode + + def test_function_arguments(self): + mod = self.module() + func = mod.get_function('sum') + self.assertTrue(func.is_function) + args = list(func.arguments) + self.assertEqual(len(args), 2) + self.assertTrue(args[0].is_argument) + self.assertTrue(args[1].is_argument) + self.assertEqual(args[0].name, '.1') + self.assertEqual(str(args[0].type), 'i32') + self.assertEqual(args[1].name, '.2') + self.assertEqual(str(args[1].type), 'i32') + + with self.assertRaises(ValueError): + args[0].blocks + with self.assertRaises(ValueError): + args[0].arguments + + def test_function_blocks(self): + func = self.module().get_function('sum') + blocks = list(func.blocks) + self.assertEqual(len(blocks), 1) + block = blocks[0] + self.assertTrue(block.is_block) + + def test_block_instructions(self): + func = self.module().get_function('sum') + insts = list(list(func.blocks)[0].instructions) + self.assertEqual(len(insts), 3) + self.assertTrue(insts[0].is_instruction) + self.assertTrue(insts[1].is_instruction) + self.assertTrue(insts[2].is_instruction) + self.assertEqual(insts[0].opcode, 'add') + self.assertEqual(insts[1].opcode, 'add') + self.assertEqual(insts[2].opcode, 'ret') + + def test_instruction_operands(self): + func = self.module().get_function('sum') + add = list(list(func.blocks)[0].instructions)[0] + self.assertEqual(add.opcode, 'add') + operands = list(add.operands) + self.assertEqual(len(operands), 2) + self.assertTrue(operands[0].is_operand) + self.assertTrue(operands[1].is_operand) + self.assertEqual(operands[0].name, '.1') + self.assertEqual(str(operands[0].type), 'i32') + self.assertEqual(operands[1].name, '.2') + self.assertEqual(str(operands[1].type), 'i32') + + def test_function_attributes(self): + mod = self.module(asm_attributes) + for func in mod.functions: + attrs = list(func.attributes) + if func.name == 'a_readonly_func': + self.assertEqual(attrs, [b'readonly']) + elif func.name == 'a_arg0_return_func': + self.assertEqual(attrs, []) + args = list(func.arguments) + self.assertEqual(list(args[0].attributes), [b'returned']) + self.assertEqual(list(args[1].attributes), []) + + def test_value_kind(self): + mod = self.module() + self.assertEqual(mod.get_global_variable('glob').value_kind, + llvm.ValueKind.global_variable) + func = mod.get_function('sum') + self.assertEqual(func.value_kind, llvm.ValueKind.function) + block = list(func.blocks)[0] + self.assertEqual(block.value_kind, llvm.ValueKind.basic_block) + inst = list(block.instructions)[1] + self.assertEqual(inst.value_kind, llvm.ValueKind.instruction) + self.assertEqual(list(inst.operands)[0].value_kind, + llvm.ValueKind.constant_int) + self.assertEqual(list(inst.operands)[1].value_kind, + llvm.ValueKind.instruction) + + iasm_func = self.module(asm_inlineasm).get_function('foo') + iasm_inst = list(list(iasm_func.blocks)[0].instructions)[0] + self.assertEqual(list(iasm_inst.operands)[0].value_kind, + llvm.ValueKind.inline_asm) + + def test_is_constant(self): + mod = self.module() + self.assertTrue(mod.get_global_variable('glob').is_constant) + constant_operands = 0 + for func in mod.functions: + self.assertTrue(func.is_constant) + for block in func.blocks: + self.assertFalse(block.is_constant) + for inst in block.instructions: + self.assertFalse(inst.is_constant) + for op in inst.operands: + if op.is_constant: + constant_operands += 1 + + self.assertEqual(constant_operands, 1) + + def test_constant_int(self): + mod = self.module() + func = mod.get_function('sum') + insts = list(list(func.blocks)[0].instructions) + self.assertEqual(insts[1].opcode, 'add') + operands = list(insts[1].operands) + self.assertTrue(operands[0].is_constant) + self.assertFalse(operands[1].is_constant) + self.assertEqual(operands[0].get_constant_value(), 0) + with self.assertRaises(ValueError): + operands[1].get_constant_value() + + mod = self.module(asm_sum3) + func = mod.get_function('sum') + insts = list(list(func.blocks)[0].instructions) + posint64 = list(insts[1].operands)[0] + negint64 = list(insts[2].operands)[0] + self.assertEqual(posint64.get_constant_value(), 5) + self.assertEqual(negint64.get_constant_value(signed_int=True), -5) + + # Convert from unsigned arbitrary-precision integer to signed i64 + as_u64 = negint64.get_constant_value(signed_int=False) + as_i64 = int.from_bytes(as_u64.to_bytes(8, 'little'), 'little', + signed=True) + self.assertEqual(as_i64, -5) + + def test_constant_fp(self): + mod = self.module(asm_double_locale) + func = mod.get_function('foo') + insts = list(list(func.blocks)[0].instructions) + self.assertEqual(len(insts), 2) + self.assertEqual(insts[0].opcode, 'fadd') + operands = list(insts[0].operands) + self.assertTrue(operands[0].is_constant) + self.assertAlmostEqual(operands[0].get_constant_value(), 0.0) + self.assertTrue(operands[1].is_constant) + self.assertAlmostEqual(operands[1].get_constant_value(), 3.14) + + mod = self.module(asm_double_inaccurate) + func = mod.get_function('foo') + inst = list(list(func.blocks)[0].instructions)[0] + operands = list(inst.operands) + with self.assertRaises(ValueError): + operands[0].get_constant_value() + self.assertAlmostEqual(operands[1].get_constant_value(round_fp=True), 0) + + def test_constant_as_string(self): + mod = self.module(asm_null_constant) + func = mod.get_function('bar') + inst = list(list(func.blocks)[0].instructions)[0] + arg = list(inst.operands)[0] + self.assertTrue(arg.is_constant) + self.assertEqual(arg.get_constant_value(), 'i64* null') + + +class TestTarget(BaseTest): + + def test_from_triple(self): + f = llvm.Target.from_triple + with self.assertRaises(RuntimeError) as cm: + f("foobar") + self.assertIn("No available targets are compatible with", + str(cm.exception)) + triple = llvm.get_default_triple() + target = f(triple) + self.assertEqual(target.triple, triple) + target.close() + + def test_create_target_machine(self): + target = llvm.Target.from_triple(llvm.get_default_triple()) + # With the default settings + target.create_target_machine('', '', 1, 'default', 'default') + # With the host's CPU + cpu = llvm.get_host_cpu_name() + target.create_target_machine(cpu, '', 1, 'default', 'default') + + def test_name(self): + t = llvm.Target.from_triple(llvm.get_default_triple()) + u = llvm.Target.from_default_triple() + self.assertIsInstance(t.name, str) + self.assertEqual(t.name, u.name) + + def test_description(self): + t = llvm.Target.from_triple(llvm.get_default_triple()) + u = llvm.Target.from_default_triple() + self.assertIsInstance(t.description, str) + self.assertEqual(t.description, u.description) + + def test_str(self): + target = llvm.Target.from_triple(llvm.get_default_triple()) + s = str(target) + self.assertIn(target.name, s) + self.assertIn(target.description, s) + + +class TestTargetData(BaseTest): + + def target_data(self): + return llvm.create_target_data("e-m:e-i64:64-f80:128-n8:16:32:64-S128") + + def test_get_abi_size(self): + td = self.target_data() + glob = self.glob() + self.assertEqual(td.get_abi_size(glob.type), 8) + + def test_get_pointee_abi_size(self): + td = self.target_data() + + glob = self.glob() + self.assertEqual(td.get_pointee_abi_size(glob.type), 4) + + glob = self.glob("glob_struct") + self.assertEqual(td.get_pointee_abi_size(glob.type), 24) + + def test_get_struct_element_offset(self): + td = self.target_data() + glob = self.glob("glob_struct") + + with self.assertRaises(ValueError): + td.get_element_offset(glob.type, 0) + + struct_type = glob.type.element_type + self.assertEqual(td.get_element_offset(struct_type, 0), 0) + self.assertEqual(td.get_element_offset(struct_type, 1), 8) + + +class TestTargetMachine(BaseTest): + + def test_add_analysis_passes(self): + tm = self.target_machine(jit=False) + pm = llvm.create_module_pass_manager() + tm.add_analysis_passes(pm) + + def test_target_data_from_tm(self): + tm = self.target_machine(jit=False) + td = tm.target_data + mod = self.module() + gv_i32 = mod.get_global_variable("glob") + # A global is a pointer, it has the ABI size of a pointer + pointer_size = 4 if sys.maxsize < 2 ** 32 else 8 + self.assertEqual(td.get_abi_size(gv_i32.type), pointer_size) + + +class TestPassManagerBuilder(BaseTest): + + def pmb(self): + return llvm.PassManagerBuilder() + + def test_old_api(self): + # Test the create_pass_manager_builder() factory function + pmb = llvm.create_pass_manager_builder() + pmb.inlining_threshold = 2 + pmb.opt_level = 3 + + def test_close(self): + pmb = self.pmb() + pmb.close() + pmb.close() + + def test_opt_level(self): + pmb = self.pmb() + self.assertIsInstance(pmb.opt_level, int) + for i in range(4): + pmb.opt_level = i + self.assertEqual(pmb.opt_level, i) + + def test_size_level(self): + pmb = self.pmb() + self.assertIsInstance(pmb.size_level, int) + for i in range(4): + pmb.size_level = i + self.assertEqual(pmb.size_level, i) + + def test_inlining_threshold(self): + pmb = self.pmb() + with self.assertRaises(NotImplementedError): + pmb.inlining_threshold + for i in (25, 80, 350): + pmb.inlining_threshold = i + + def test_disable_unroll_loops(self): + pmb = self.pmb() + self.assertIsInstance(pmb.disable_unroll_loops, bool) + for b in (True, False): + pmb.disable_unroll_loops = b + self.assertEqual(pmb.disable_unroll_loops, b) + + def test_loop_vectorize(self): + pmb = self.pmb() + self.assertIsInstance(pmb.loop_vectorize, bool) + for b in (True, False): + pmb.loop_vectorize = b + self.assertEqual(pmb.loop_vectorize, b) + + def test_slp_vectorize(self): + pmb = self.pmb() + self.assertIsInstance(pmb.slp_vectorize, bool) + for b in (True, False): + pmb.slp_vectorize = b + self.assertEqual(pmb.slp_vectorize, b) + + def test_populate_module_pass_manager(self): + pmb = self.pmb() + pm = llvm.create_module_pass_manager() + pmb.populate(pm) + pmb.close() + pm.close() + + def test_populate_function_pass_manager(self): + mod = self.module() + pmb = self.pmb() + pm = llvm.create_function_pass_manager(mod) + pmb.populate(pm) + pmb.close() + pm.close() + + +class PassManagerTestMixin(object): + + def pmb(self): + pmb = llvm.create_pass_manager_builder() + pmb.opt_level = 2 + pmb.inlining_threshold = 300 + return pmb + + def test_close(self): + pm = self.pm() + pm.close() + pm.close() + + +class TestModulePassManager(BaseTest, PassManagerTestMixin): + + def pm(self): + return llvm.create_module_pass_manager() + + def test_run(self): + pm = self.pm() + self.pmb().populate(pm) + mod = self.module() + orig_asm = str(mod) + pm.run(mod) + opt_asm = str(mod) + # Quick check that optimizations were run, should get: + # define i32 @sum(i32 %.1, i32 %.2) local_unnamed_addr #0 { + # %.X = add i32 %.2, %.1 + # ret i32 %.X + # } + # where X in %.X is 3 or 4 + opt_asm_split = opt_asm.splitlines() + for idx, l in enumerate(opt_asm_split): + if l.strip().startswith('ret i32'): + toks = {'%.3', '%.4'} + for t in toks: + if t in l: + break + else: + raise RuntimeError("expected tokens not found") + othertoken = (toks ^ {t}).pop() + + self.assertIn("%.3", orig_asm) + self.assertNotIn(othertoken, opt_asm) + break + else: + raise RuntimeError("expected IR not found") + + def test_run_with_remarks_successful_inline(self): + pm = self.pm() + pm.add_function_inlining_pass(70) + self.pmb().populate(pm) + mod = self.module(asm_inlineasm2) + (status, remarks) = pm.run_with_remarks(mod) + self.assertTrue(status) + # Inlining has happened? The remark will tell us. + self.assertIn("Passed", remarks) + self.assertIn("inlineme", remarks) + + def test_run_with_remarks_failed_inline(self): + pm = self.pm() + pm.add_function_inlining_pass(0) + self.pmb().populate(pm) + mod = self.module(asm_inlineasm3) + (status, remarks) = pm.run_with_remarks(mod) + self.assertTrue(status) + + # Inlining has not happened? The remark will tell us. + self.assertIn("Missed", remarks) + self.assertIn("inlineme", remarks) + self.assertIn("noinline function attribute", remarks) + + def test_run_with_remarks_inline_filter_out(self): + pm = self.pm() + pm.add_function_inlining_pass(70) + self.pmb().populate(pm) + mod = self.module(asm_inlineasm2) + (status, remarks) = pm.run_with_remarks(mod, remarks_filter="nothing") + self.assertTrue(status) + self.assertEqual("", remarks) + + def test_run_with_remarks_inline_filter_in(self): + pm = self.pm() + pm.add_function_inlining_pass(70) + self.pmb().populate(pm) + mod = self.module(asm_inlineasm2) + (status, remarks) = pm.run_with_remarks(mod, remarks_filter="inlin.*") + self.assertTrue(status) + self.assertIn("Passed", remarks) + self.assertIn("inlineme", remarks) + + +class TestFunctionPassManager(BaseTest, PassManagerTestMixin): + + def pm(self, mod=None): + mod = mod or self.module() + return llvm.create_function_pass_manager(mod) + + def test_initfini(self): + pm = self.pm() + pm.initialize() + pm.finalize() + + def test_run(self): + mod = self.module() + fn = mod.get_function("sum") + pm = self.pm(mod) + self.pmb().populate(pm) + mod.close() + orig_asm = str(fn) + pm.initialize() + pm.run(fn) + pm.finalize() + opt_asm = str(fn) + # Quick check that optimizations were run + self.assertIn("%.4", orig_asm) + self.assertNotIn("%.4", opt_asm) + + def test_run_with_remarks(self): + mod = self.module(licm_asm) + fn = mod.get_function("licm") + pm = self.pm(mod) + pm.add_licm_pass() + self.pmb().populate(pm) + mod.close() + + pm.initialize() + (ok, remarks) = pm.run_with_remarks(fn) + pm.finalize() + self.assertTrue(ok) + self.assertIn("Passed", remarks) + self.assertIn("licm", remarks) + + def test_run_with_remarks_filter_out(self): + mod = self.module(licm_asm) + fn = mod.get_function("licm") + pm = self.pm(mod) + pm.add_licm_pass() + self.pmb().populate(pm) + mod.close() + + pm.initialize() + (ok, remarks) = pm.run_with_remarks(fn, remarks_filter="nothing") + pm.finalize() + self.assertTrue(ok) + self.assertEqual("", remarks) + + def test_run_with_remarks_filter_in(self): + mod = self.module(licm_asm) + fn = mod.get_function("licm") + pm = self.pm(mod) + pm.add_licm_pass() + self.pmb().populate(pm) + mod.close() + + pm.initialize() + (ok, remarks) = pm.run_with_remarks(fn, remarks_filter="licm") + pm.finalize() + self.assertTrue(ok) + self.assertIn("Passed", remarks) + self.assertIn("licm", remarks) + + +class TestPasses(BaseTest, PassManagerTestMixin): + + def pm(self): + return llvm.create_module_pass_manager() + + def test_populate(self): + pm = self.pm() + pm.add_target_library_info("") # unspecified target triple + pm.add_constant_merge_pass() + pm.add_dead_arg_elimination_pass() + pm.add_function_attrs_pass() + pm.add_function_inlining_pass(225) + pm.add_global_dce_pass() + pm.add_global_optimizer_pass() + pm.add_ipsccp_pass() + pm.add_dead_code_elimination_pass() + pm.add_cfg_simplification_pass() + pm.add_gvn_pass() + pm.add_instruction_combining_pass() + pm.add_licm_pass() + pm.add_sccp_pass() + pm.add_sroa_pass() + pm.add_type_based_alias_analysis_pass() + pm.add_basic_alias_analysis_pass() + pm.add_loop_rotate_pass() + pm.add_region_info_pass() + pm.add_scalar_evolution_aa_pass() + pm.add_aggressive_dead_code_elimination_pass() + pm.add_aa_eval_pass() + pm.add_always_inliner_pass() + pm.add_arg_promotion_pass(42) + pm.add_break_critical_edges_pass() + pm.add_dead_store_elimination_pass() + pm.add_reverse_post_order_function_attrs_pass() + pm.add_aggressive_instruction_combining_pass() + pm.add_internalize_pass() + pm.add_jump_threading_pass(7) + pm.add_lcssa_pass() + pm.add_loop_deletion_pass() + pm.add_loop_extractor_pass() + pm.add_single_loop_extractor_pass() + pm.add_loop_strength_reduce_pass() + pm.add_loop_simplification_pass() + pm.add_loop_unroll_pass() + pm.add_loop_unroll_and_jam_pass() + pm.add_loop_unswitch_pass() + pm.add_lower_atomic_pass() + pm.add_lower_invoke_pass() + pm.add_lower_switch_pass() + pm.add_memcpy_optimization_pass() + pm.add_merge_functions_pass() + pm.add_merge_returns_pass() + pm.add_partial_inlining_pass() + pm.add_prune_exception_handling_pass() + pm.add_reassociate_expressions_pass() + pm.add_demote_register_to_memory_pass() + pm.add_sink_pass() + pm.add_strip_symbols_pass() + pm.add_strip_dead_debug_info_pass() + pm.add_strip_dead_prototypes_pass() + pm.add_strip_debug_declare_pass() + pm.add_strip_nondebug_symbols_pass() + pm.add_tail_call_elimination_pass() + pm.add_basic_aa_pass() + pm.add_dependence_analysis_pass() + pm.add_dot_call_graph_pass() + pm.add_dot_cfg_printer_pass() + pm.add_dot_dom_printer_pass() + pm.add_dot_postdom_printer_pass() + pm.add_globals_mod_ref_aa_pass() + pm.add_iv_users_pass() + pm.add_lazy_value_info_pass() + pm.add_lint_pass() + pm.add_module_debug_info_pass() + pm.add_refprune_pass() + + @unittest.skipUnless(platform.machine().startswith("x86"), "x86 only") + def test_target_library_info_behavior(self): + """Test a specific situation that demonstrate TLI is affecting + optimization. See https://github.com/numba/numba/issues/8898. + """ + def run(use_tli): + mod = llvm.parse_assembly(asm_tli_exp2) + target = llvm.Target.from_triple(mod.triple) + tm = target.create_target_machine() + pm = llvm.ModulePassManager() + tm.add_analysis_passes(pm) + if use_tli: + pm.add_target_library_info(mod.triple) + pm.add_instruction_combining_pass() + pm.run(mod) + return mod + + # Run with TLI should suppress transformation of exp2 -> ldexpf + mod = run(use_tli=True) + self.assertIn("call float @llvm.exp2.f32", str(mod)) + + # Run without TLI will enable the transformation + mod = run(use_tli=False) + self.assertNotIn("call float @llvm.exp2.f32", str(mod)) + self.assertIn("call float @ldexpf", str(mod)) + + +class TestDylib(BaseTest): + + def test_bad_library(self): + with self.assertRaises(RuntimeError): + llvm.load_library_permanently("zzzasdkf;jasd;l") + + @unittest.skipUnless(platform.system() in ["Linux"], + "test only works on Linux") + def test_libm(self): + libm = find_library("m") + llvm.load_library_permanently(libm) + + +class TestAnalysis(BaseTest): + def build_ir_module(self): + m = ir.Module() + ft = ir.FunctionType(ir.IntType(32), [ir.IntType(32), ir.IntType(32)]) + fn = ir.Function(m, ft, "foo") + bd = ir.IRBuilder(fn.append_basic_block()) + x, y = fn.args + z = bd.add(x, y) + bd.ret(z) + return m + + def test_get_function_cfg_on_ir(self): + mod = self.build_ir_module() + foo = mod.get_global('foo') + dot_showing_inst = llvm.get_function_cfg(foo) + dot_without_inst = llvm.get_function_cfg(foo, show_inst=False) + inst = "%.5 = add i32 %.1, %.2" + self.assertIn(inst, dot_showing_inst) + self.assertNotIn(inst, dot_without_inst) + + def test_function_cfg_on_llvm_value(self): + defined = self.module().get_function('sum') + dot_showing_inst = llvm.get_function_cfg(defined, show_inst=True) + dot_without_inst = llvm.get_function_cfg(defined, show_inst=False) + # Check "digraph" + prefix = 'digraph' + self.assertIn(prefix, dot_showing_inst) + self.assertIn(prefix, dot_without_inst) + # Check function name + fname = "CFG for 'sum' function" + self.assertIn(fname, dot_showing_inst) + self.assertIn(fname, dot_without_inst) + # Check instruction + inst = "%.3 = add i32 %.1, %.2" + self.assertIn(inst, dot_showing_inst) + self.assertNotIn(inst, dot_without_inst) + + +class TestTypeParsing(BaseTest): + @contextmanager + def check_parsing(self): + mod = ir.Module() + # Yield to caller and provide the module for adding + # new GV. + yield mod + # Caller yield back and continue with testing + asm = str(mod) + llvm.parse_assembly(asm) + + def test_literal_struct(self): + # Natural layout + with self.check_parsing() as mod: + typ = ir.LiteralStructType([ir.IntType(32)]) + gv = ir.GlobalVariable(mod, typ, "foo") + # Also test constant text repr + gv.initializer = ir.Constant(typ, [1]) + + # Packed layout + with self.check_parsing() as mod: + typ = ir.LiteralStructType([ir.IntType(32)], + packed=True) + gv = ir.GlobalVariable(mod, typ, "foo") + # Also test constant text repr + gv.initializer = ir.Constant(typ, [1]) + + +class TestGlobalConstructors(TestMCJit): + def test_global_ctors_dtors(self): + # test issue #303 + # (https://github.com/numba/llvmlite/issues/303) + mod = self.module(asm_global_ctors) + ee = self.jit(mod) + ee.finalize_object() + + ee.run_static_constructors() + + # global variable should have been initialized + ptr_addr = ee.get_global_value_address("A") + ptr_t = ctypes.POINTER(ctypes.c_int32) + ptr = ctypes.cast(ptr_addr, ptr_t) + self.assertEqual(ptr.contents.value, 10) + + foo_addr = ee.get_function_address("foo") + foo = ctypes.CFUNCTYPE(ctypes.c_int32)(foo_addr) + self.assertEqual(foo(), 12) + + ee.run_static_destructors() + + # destructor should have run + self.assertEqual(ptr.contents.value, 20) + + +class TestGlobalVariables(BaseTest): + def check_global_variable_linkage(self, linkage, has_undef=True): + # This test default initializer on global variables with different + # linkages. Some linkages requires an initializer be present, while + # it is optional for others. This test uses ``parse_assembly()`` + # to verify that we are adding an `undef` automatically if user didn't + # specific one for certain linkages. It is a IR syntax error if the + # initializer is not present for certain linkages e.g. "external". + mod = ir.Module() + typ = ir.IntType(32) + gv = ir.GlobalVariable(mod, typ, "foo") + gv.linkage = linkage + asm = str(mod) + # check if 'undef' is present + if has_undef: + self.assertIn('undef', asm) + else: + self.assertNotIn('undef', asm) + # parse assembly to ensure correctness + self.module(asm) + + def test_internal_linkage(self): + self.check_global_variable_linkage('internal') + + def test_common_linkage(self): + self.check_global_variable_linkage('common') + + def test_external_linkage(self): + self.check_global_variable_linkage('external', has_undef=False) + + def test_available_externally_linkage(self): + self.check_global_variable_linkage('available_externally') + + def test_private_linkage(self): + self.check_global_variable_linkage('private') + + def test_linkonce_linkage(self): + self.check_global_variable_linkage('linkonce') + + def test_weak_linkage(self): + self.check_global_variable_linkage('weak') + + def test_appending_linkage(self): + self.check_global_variable_linkage('appending') + + def test_extern_weak_linkage(self): + self.check_global_variable_linkage('extern_weak', has_undef=False) + + def test_linkonce_odr_linkage(self): + self.check_global_variable_linkage('linkonce_odr') + + def test_weak_odr_linkage(self): + self.check_global_variable_linkage('weak_odr') + + +@unittest.skipUnless(platform.machine().startswith('x86'), "only on x86") +class TestInlineAsm(BaseTest): + def test_inlineasm(self): + llvm.initialize_native_asmparser() + m = self.module(asm=asm_inlineasm) + tm = self.target_machine(jit=False) + asm = tm.emit_assembly(m) + self.assertIn('nop', asm) + + +class TestObjectFile(BaseTest): + + mod_asm = """ + ;ModuleID = + target triple = "{triple}" + + declare i32 @sum(i32 %.1, i32 %.2) + + define i32 @sum_twice(i32 %.1, i32 %.2) {{ + %.3 = call i32 @sum(i32 %.1, i32 %.2) + %.4 = call i32 @sum(i32 %.3, i32 %.3) + ret i32 %.4 + }} + """ + + def test_object_file(self): + target_machine = self.target_machine(jit=False) + mod = self.module() + obj_bin = target_machine.emit_object(mod) + obj = llvm.ObjectFileRef.from_data(obj_bin) + # Check that we have a text section, and that she has a name and data + has_text = False + last_address = -1 + for s in obj.sections(): + if s.is_text(): + has_text = True + self.assertIsNotNone(s.name()) + self.assertTrue(s.size() > 0) + self.assertTrue(len(s.data()) > 0) + self.assertIsNotNone(s.address()) + self.assertTrue(last_address < s.address()) + last_address = s.address() + break + self.assertTrue(has_text) + + def test_add_object_file(self): + target_machine = self.target_machine(jit=False) + mod = self.module() + obj_bin = target_machine.emit_object(mod) + obj = llvm.ObjectFileRef.from_data(obj_bin) + + jit = llvm.create_mcjit_compiler(self.module(self.mod_asm), + target_machine) + + jit.add_object_file(obj) + + sum_twice = CFUNCTYPE(c_int, c_int, c_int)( + jit.get_function_address("sum_twice")) + + self.assertEqual(sum_twice(2, 3), 10) + + def test_add_object_file_from_filesystem(self): + target_machine = self.target_machine(jit=False) + mod = self.module() + obj_bin = target_machine.emit_object(mod) + temp_desc, temp_path = mkstemp() + + try: + try: + f = os.fdopen(temp_desc, "wb") + f.write(obj_bin) + f.flush() + finally: + f.close() + + jit = llvm.create_mcjit_compiler(self.module(self.mod_asm), + target_machine) + + jit.add_object_file(temp_path) + finally: + os.unlink(temp_path) + + sum_twice = CFUNCTYPE(c_int, c_int, c_int)( + jit.get_function_address("sum_twice")) + + self.assertEqual(sum_twice(2, 3), 10) + + def test_get_section_content(self): + # See Issue #632 - section contents were getting truncated at null + # bytes. + elf = bytes.fromhex(issue_632_elf) + obj = llvm.ObjectFileRef.from_data(elf) + for s in obj.sections(): + if s.is_text(): + self.assertEqual(len(s.data()), 31) + self.assertEqual(s.data().hex(), issue_632_text) + + +class TestTimePasses(BaseTest): + def test_reporting(self): + mp = llvm.create_module_pass_manager() + + pmb = llvm.create_pass_manager_builder() + pmb.opt_level = 3 + pmb.populate(mp) + + try: + llvm.set_time_passes(True) + mp.run(self.module()) + mp.run(self.module()) + mp.run(self.module()) + finally: + report = llvm.report_and_reset_timings() + llvm.set_time_passes(False) + + self.assertIsInstance(report, str) + self.assertEqual(report.count("Pass execution timing report"), 1) + + def test_empty_report(self): + # Returns empty str if no data is collected + self.assertFalse(llvm.report_and_reset_timings()) + + +class TestLLVMLockCallbacks(BaseTest): + def test_lock_callbacks(self): + events = [] + + def acq(): + events.append('acq') + + def rel(): + events.append('rel') + + # register callback + llvm.ffi.register_lock_callback(acq, rel) + + # Check: events are initially empty + self.assertFalse(events) + # Call LLVM functions + llvm.create_module_pass_manager() + # Check: there must be at least one acq and one rel + self.assertIn("acq", events) + self.assertIn("rel", events) + + # unregister callback + llvm.ffi.unregister_lock_callback(acq, rel) + + # Check: removing non-existent callbacks will trigger a ValueError + with self.assertRaises(ValueError): + llvm.ffi.unregister_lock_callback(acq, rel) + + +if __name__ == "__main__": + unittest.main() diff --git a/lib/python3.11/site-packages/llvmlite/tests/test_ir.py b/lib/python3.11/site-packages/llvmlite/tests/test_ir.py new file mode 100644 index 0000000000000000000000000000000000000000..63a7c5f309c84057915f2b99f0c838caca21a522 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/test_ir.py @@ -0,0 +1,2725 @@ +""" +IR Construction Tests +""" + +import copy +import itertools +import pickle +import re +import textwrap +import unittest + +from . import TestCase +from llvmlite import ir +from llvmlite import binding as llvm + + +int1 = ir.IntType(1) +int8 = ir.IntType(8) +int16 = ir.IntType(16) +int32 = ir.IntType(32) +int64 = ir.IntType(64) +hlf = ir.HalfType() +flt = ir.FloatType() +dbl = ir.DoubleType() + + +class TestBase(TestCase): + """ + Utilities for IR tests. + """ + + def assertInText(self, pattern, text): + """ + Assert *pattern* is in *text*, ignoring any whitespace differences + (including newlines). + """ + + def escape(c): + if not c.isalnum() and not c.isspace(): + return '\\' + c + return c + + pattern = ''.join(map(escape, pattern)) + regex = re.sub(r'\s+', r'\\s*', pattern) + self.assertRegex(text, regex) + + def assert_ir_line(self, line, mod): + lines = [line.strip() for line in str(mod).splitlines()] + self.assertIn(line, lines) + + def assert_valid_ir(self, mod): + llvm.parse_assembly(str(mod)) + + def assert_pickle_correctly(self, irobject): + """Assert that the IR object pickles and unpickles correctly. + The IR string is equal and that their type is equal + """ + newobject = pickle.loads(pickle.dumps(irobject, protocol=-1)) + self.assertIs(irobject.__class__, newobject.__class__) + self.assertEqual(str(irobject), str(newobject)) + return newobject + + def module(self): + return ir.Module() + + def function(self, module=None, name='my_func'): + module = module or self.module() + fnty = ir.FunctionType(int32, (int32, int32, dbl, + ir.PointerType(int32))) + return ir.Function(module, fnty, name) + + def block(self, func=None, name=''): + func = func or self.function() + return func.append_basic_block(name) + + def descr(self, thing): + buf = [] + thing.descr(buf) + return "".join(buf) + + def _normalize_asm(self, asm): + asm = textwrap.dedent(asm) + # Normalize indent + asm = asm.replace("\n ", "\n ") + return asm + + def check_descr_regex(self, descr, asm): + expected = self._normalize_asm(asm) + self.assertRegex(descr, expected) + + def check_descr(self, descr, asm): + expected = self._normalize_asm(asm) + self.assertEqual(descr, expected) + + def check_block(self, block, asm): + self.check_descr(self.descr(block), asm) + + def check_block_regex(self, block, asm): + self.check_descr_regex(self.descr(block), asm) + + def check_module_body(self, module, asm): + expected = self._normalize_asm(asm) + actual = module._stringify_body() + self.assertEqual(actual.strip(), expected.strip()) + + def check_metadata(self, module, asm): + """ + Check module metadata against *asm*. + """ + expected = self._normalize_asm(asm) + actual = module._stringify_metadata() + self.assertEqual(actual.strip(), expected.strip()) + + def check_func_body(self, func, asm): + expected = self._normalize_asm(asm) + actual = self.descr(func) + actual = actual.partition('{')[2].rpartition('}')[0] + self.assertEqual(actual.strip(), expected.strip()) + + +class TestFunction(TestBase): + + proto = """i32 @"my_func"(i32 %".1", i32 %".2", double %".3", i32* %".4")""" + + def test_declare(self): + # A simple declaration + func = self.function() + asm = self.descr(func).strip() + self.assertEqual(asm.strip(), "declare %s" % self.proto) + + def test_declare_attributes(self): + # Now with function attributes + func = self.function() + func.attributes.add("optsize") + func.attributes.add("alwaysinline") + func.attributes.alignstack = 16 + tp_pers = ir.FunctionType(int8, (), var_arg=True) + pers = ir.Function(self.module(), tp_pers, '__gxx_personality_v0') + func.attributes.personality = pers + asm = self.descr(func).strip() + self.assertEqual(asm, + ("declare %s alwaysinline optsize alignstack(16) " + "personality i8 (...)* @\"__gxx_personality_v0\"") % + self.proto) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_attributes(self): + # Now with parameter attributes + func = self.function() + func.args[0].add_attribute("zeroext") + func.args[1].attributes.dereferenceable = 5 + func.args[1].attributes.dereferenceable_or_null = 10 + func.args[3].attributes.align = 4 + func.args[3].add_attribute("nonnull") + func.return_value.add_attribute("noalias") + asm = self.descr(func).strip() + self.assertEqual(asm, + """declare noalias i32 @"my_func"(i32 zeroext %".1", i32 dereferenceable(5) dereferenceable_or_null(10) %".2", double %".3", i32* nonnull align 4 %".4")""" # noqa E501 + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_metadata(self): + # Now with function metadata + module = self.module() + func = self.function(module) + func.set_metadata('dbg', module.add_metadata([])) + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} !dbg !0' + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_section(self): + # Test function with section + func = self.function() + func.section = "a_section" + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} section "a_section"' + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_section_meta(self): + # Test function with section and metadata + module = self.module() + func = self.function(module) + func.section = "a_section" + func.set_metadata('dbg', module.add_metadata([])) + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} section "a_section" !dbg !0' + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_attr_meta(self): + # Test function with attributes and metadata + module = self.module() + func = self.function(module) + func.attributes.add("alwaysinline") + func.set_metadata('dbg', module.add_metadata([])) + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} alwaysinline !dbg !0' + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_attr_section(self): + # Test function with attributes and section + func = self.function() + func.attributes.add("optsize") + func.section = "a_section" + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} optsize section "a_section"') + # Check pickling + self.assert_pickle_correctly(func) + + def test_function_attr_section_meta(self): + # Test function with attributes, section and metadata + module = self.module() + func = self.function(module) + func.attributes.add("alwaysinline") + func.section = "a_section" + func.set_metadata('dbg', module.add_metadata([])) + asm = self.descr(func).strip() + self.assertEqual(asm, + f'declare {self.proto} alwaysinline section "a_section" !dbg !0' # noqa E501 + ) + # Check pickling + self.assert_pickle_correctly(func) + + def test_define(self): + # A simple definition + func = self.function() + func.attributes.add("alwaysinline") + block = func.append_basic_block('my_block') + builder = ir.IRBuilder(block) + builder.ret_void() + asm = self.descr(func) + self.check_descr(asm, """\ + define {proto} alwaysinline + {{ + my_block: + ret void + }} + """.format(proto=self.proto)) + + def test_declare_intrinsics(self): + module = self.module() + pint8 = int8.as_pointer() + + powi = module.declare_intrinsic('llvm.powi', [dbl]) + memset = module.declare_intrinsic('llvm.memset', [pint8, int32]) + memcpy = module.declare_intrinsic('llvm.memcpy', [pint8, pint8, int32]) + assume = module.declare_intrinsic('llvm.assume') + self.check_descr(self.descr(powi).strip(), """\ + declare double @"llvm.powi.f64"(double %".1", i32 %".2")""") + self.check_descr(self.descr(memset).strip(), """\ + declare void @"llvm.memset.p0i8.i32"(i8* %".1", i8 %".2", i32 %".3", i1 %".4")""") # noqa E501 + self.check_descr(self.descr(memcpy).strip(), """\ + declare void @"llvm.memcpy.p0i8.p0i8.i32"(i8* %".1", i8* %".2", i32 %".3", i1 %".4")""") # noqa E501 + self.check_descr(self.descr(assume).strip(), """\ + declare void @"llvm.assume"(i1 %".1")""") + + def test_redeclare_intrinsic(self): + module = self.module() + powi = module.declare_intrinsic('llvm.powi', [dbl]) + powi2 = module.declare_intrinsic('llvm.powi', [dbl]) + self.assertIs(powi, powi2) + + def test_pickling(self): + fn = self.function() + self.assert_pickle_correctly(fn) + + def test_alwaysinline_noinline_disallowed(self): + module = self.module() + func = self.function(module) + func.attributes.add('alwaysinline') + + msg = "Can't have alwaysinline and noinline" + with self.assertRaisesRegex(ValueError, msg): + func.attributes.add('noinline') + + def test_noinline_alwaysinline_disallowed(self): + module = self.module() + func = self.function(module) + func.attributes.add('noinline') + + msg = "Can't have alwaysinline and noinline" + with self.assertRaisesRegex(ValueError, msg): + func.attributes.add('alwaysinline') + + +class TestIR(TestBase): + + def test_unnamed_metadata(self): + # An unnamed metadata node + mod = self.module() + mod.add_metadata([int32(123), int8(42)]) + self.assert_ir_line("!0 = !{ i32 123, i8 42 }", mod) + self.assert_valid_ir(mod) + + def test_unnamed_metadata_2(self): + # Several unnamed metadata nodes + mod = self.module() + # First node has a literal metadata string + m0 = mod.add_metadata([int32(123), "kernel"]) + # Second node refers to the first one + m1 = mod.add_metadata([int64(456), m0]) + # Third node is the same as the second one + m2 = mod.add_metadata([int64(456), m0]) + self.assertIs(m2, m1) + # Fourth node refers to the first three + mod.add_metadata([m0, m1, m2]) + self.assert_ir_line('!0 = !{ i32 123, !"kernel" }', mod) + self.assert_ir_line('!1 = !{ i64 456, !0 }', mod) + self.assert_ir_line('!2 = !{ !0, !1, !1 }', mod) + + def test_unnamed_metadata_3(self): + # Passing nested metadata as a sequence + mod = self.module() + mod.add_metadata([int32(123), [int32(456)], [int32(789)], [int32(456)]]) + self.assert_ir_line('!0 = !{ i32 456 }', mod) + self.assert_ir_line('!1 = !{ i32 789 }', mod) + self.assert_ir_line('!2 = !{ i32 123, !0, !1, !0 }', mod) + + def test_metadata_string(self): + # Escaping contents of a metadata string + mod = self.module() + mod.add_metadata(["\"\\$"]) + self.assert_ir_line('!0 = !{ !"\\22\\5c$" }', mod) + + def test_named_metadata(self): + # Add a named metadata node and add metadata values to it + mod = self.module() + m0 = mod.add_metadata([int32(123)]) + m1 = mod.add_metadata([int64(456)]) + nmd = mod.add_named_metadata("foo") + nmd.add(m0) + nmd.add(m1) + nmd.add(m0) + self.assert_ir_line("!foo = !{ !0, !1, !0 }", mod) + self.assert_valid_ir(mod) + # Check get_named_metadata() + self.assertIs(nmd, mod.get_named_metadata("foo")) + with self.assertRaises(KeyError): + mod.get_named_metadata("bar") + + def test_named_metadata_2(self): + # Add and set named metadata through a single add_named_metadata() call + mod = self.module() + m0 = mod.add_metadata([int32(123)]) + mod.add_named_metadata("foo", m0) + mod.add_named_metadata("foo", [int64(456)]) + mod.add_named_metadata("foo", ["kernel"]) + mod.add_named_metadata("bar", []) + self.assert_ir_line("!foo = !{ !0, !1, !2 }", mod) + self.assert_ir_line("!0 = !{ i32 123 }", mod) + self.assert_ir_line("!1 = !{ i64 456 }", mod) + self.assert_ir_line('!2 = !{ !"kernel" }', mod) + self.assert_ir_line("!bar = !{ !3 }", mod) + self.assert_ir_line('!3 = !{ }', mod) + self.assert_valid_ir(mod) + + def test_metadata_null(self): + # A null metadata (typed) value + mod = self.module() + mod.add_metadata([int32.as_pointer()(None)]) + self.assert_ir_line("!0 = !{ i32* null }", mod) + self.assert_valid_ir(mod) + # A null metadata (untyped) value + mod = self.module() + mod.add_metadata([None, int32(123)]) + self.assert_ir_line("!0 = !{ null, i32 123 }", mod) + self.assert_valid_ir(mod) + + def test_debug_info(self): + # Add real world-looking debug information to a module + # (with various value types) + mod = self.module() + di_file = mod.add_debug_info("DIFile", { + "filename": "foo", + "directory": "bar", + }) + di_func_type = mod.add_debug_info("DISubroutineType", { + # None as `null` + "types": mod.add_metadata([None]), + }) + di_compileunit = mod.add_debug_info("DICompileUnit", { + "language": ir.DIToken("DW_LANG_Python"), + "file": di_file, + "producer": "ARTIQ", + "runtimeVersion": 0, + "isOptimized": True, + }, is_distinct=True) + mod.add_debug_info("DISubprogram", { + "name": "my_func", + "file": di_file, + "line": 11, + "type": di_func_type, + "isLocal": False, + "unit": di_compileunit, + }, is_distinct=True) + + # Check output + strmod = str(mod) + self.assert_ir_line('!0 = !DIFile(directory: "bar", filename: "foo")', + strmod) + self.assert_ir_line('!1 = !{ null }', strmod) + self.assert_ir_line('!2 = !DISubroutineType(types: !1)', strmod) + # self.assert_ir_line('!4 = !{ !3 }', strmod) + self.assert_ir_line('!3 = distinct !DICompileUnit(file: !0, ' + 'isOptimized: true, language: DW_LANG_Python, ' + 'producer: "ARTIQ", runtimeVersion: 0)', + strmod) + self.assert_ir_line('!4 = distinct !DISubprogram(file: !0, isLocal: ' + 'false, line: 11, name: "my_func", type: !2, unit: ' + '!3)', + strmod) + self.assert_valid_ir(mod) + + def test_debug_info_2(self): + # Identical debug info nodes should be merged + mod = self.module() + di1 = mod.add_debug_info("DIFile", + {"filename": "foo", + "directory": "bar", + }) + di2 = mod.add_debug_info("DIFile", + {"filename": "foo", + "directory": "bar", + }) + di3 = mod.add_debug_info("DIFile", + {"filename": "bar", + "directory": "foo", + }) + di4 = mod.add_debug_info("DIFile", + {"filename": "foo", + "directory": "bar", + }, is_distinct=True) + self.assertIs(di1, di2) + self.assertEqual(len({di1, di2, di3, di4}), 3) + # Check output + strmod = str(mod) + self.assert_ir_line('!0 = !DIFile(directory: "bar", filename: "foo")', + strmod) + self.assert_ir_line('!1 = !DIFile(directory: "foo", filename: "bar")', + strmod) + self.assert_ir_line('!2 = distinct !DIFile(directory: "bar", filename: ' + '"foo")', strmod) + self.assert_valid_ir(mod) + + def test_debug_info_gvar(self): + # This test defines a module with a global variable named 'gvar'. + # When the module is compiled and linked with a main function, gdb can + # be used to interpret and print the the value of 'gvar'. + mod = self.module() + + gvar = ir.GlobalVariable(mod, ir.FloatType(), 'gvar') + gvar.initializer = ir.Constant(ir.FloatType(), 42) + + di_float = mod.add_debug_info("DIBasicType", { + "name": "float", + "size": 32, + "encoding": ir.DIToken("DW_ATE_float") + }) + di_gvar = mod.add_debug_info("DIGlobalVariableExpression", { + "expr": mod.add_debug_info("DIExpression", {}), + "var": mod.add_debug_info("DIGlobalVariable", { + "name": gvar.name, + "type": di_float, + "isDefinition": True + }, is_distinct=True) + }) + gvar.set_metadata('dbg', di_gvar) + + # Check output + strmod = str(mod) + self.assert_ir_line('!0 = !DIBasicType(encoding: DW_ATE_float, ' + 'name: "float", size: 32)', strmod) + self.assert_ir_line('!1 = !DIExpression()', strmod) + self.assert_ir_line('!2 = distinct !DIGlobalVariable(isDefinition: ' + 'true, name: "gvar", type: !0)', strmod) + self.assert_ir_line('!3 = !DIGlobalVariableExpression(expr: !1, ' + 'var: !2)', strmod) + self.assert_ir_line('@"gvar" = global float 0x4045000000000000, ' + '!dbg !3', strmod) + + # The remaining debug info is not part of the automated test, but + # can be used to produce an object file that can be loaded into a + # debugger to print the value of gvar. This can be done by printing the + # module then compiling it with clang and inspecting with gdb: + # + # clang test_debug_info_gvar.ll -c + # printf "file test_debug_info_gvar.o \n p gvar" | gdb + # + # Which should result in the output: + # + # (gdb) $1 = 42 + + dver = [ir.IntType(32)(2), 'Dwarf Version', ir.IntType(32)(4)] + diver = [ir.IntType(32)(2), 'Debug Info Version', ir.IntType(32)(3)] + dver = mod.add_metadata(dver) + diver = mod.add_metadata(diver) + flags = mod.add_named_metadata('llvm.module.flags') + flags.add(dver) + flags.add(diver) + + di_file = mod.add_debug_info("DIFile", { + "filename": "foo", + "directory": "bar", + }) + di_cu = mod.add_debug_info("DICompileUnit", { + "language": ir.DIToken("DW_LANG_Python"), + "file": di_file, + 'emissionKind': ir.DIToken('FullDebug'), + "globals": mod.add_metadata([di_gvar]) + }, is_distinct=True) + mod.add_named_metadata('llvm.dbg.cu', di_cu) + + def test_debug_info_unicode_string(self): + mod = self.module() + mod.add_debug_info("DILocalVariable", {"name": "a∆"}) + # Check output + strmod = str(mod) + # The unicode character is utf8 encoded with \XX format, where XX is hex + name = ''.join(map(lambda x: f"\\{x:02x}", "∆".encode())) + self.assert_ir_line(f'!0 = !DILocalVariable(name: "a{name}")', strmod) + + def test_inline_assembly(self): + mod = self.module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'foo') + builder = ir.IRBuilder(foo.append_basic_block('')) + asmty = ir.FunctionType(int32, [int32]) + asm = ir.InlineAsm(asmty, "mov $1, $2", "=r,r", side_effect=True) + builder.call(asm, [int32(123)]) + builder.ret_void() + pat = 'call i32 asm sideeffect "mov $1, $2", "=r,r" ( i32 123 )' + self.assertInText(pat, str(mod)) + self.assert_valid_ir(mod) + + def test_builder_asm(self): + mod = self.module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'foo') + builder = ir.IRBuilder(foo.append_basic_block('')) + asmty = ir.FunctionType(int32, [int32]) + builder.asm(asmty, "mov $1, $2", "=r,r", [int32(123)], side_effect=True) + builder.ret_void() + pat = 'call i32 asm sideeffect "mov $1, $2", "=r,r" ( i32 123 )' + self.assertInText(pat, str(mod)) + self.assert_valid_ir(mod) + + def test_builder_load_reg(self): + mod = self.module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'foo') + builder = ir.IRBuilder(foo.append_basic_block('')) + builder.load_reg(ir.IntType(64), "rax") + builder.ret_void() + pat = 'call i64 asm "", "={rax}"' + self.assertInText(pat, str(mod)) + self.assert_valid_ir(mod) + + def test_builder_store_reg(self): + mod = self.module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'foo') + builder = ir.IRBuilder(foo.append_basic_block('')) + builder.store_reg(int64(123), ir.IntType(64), "rax") + builder.ret_void() + pat = 'call void asm sideeffect "", "{rax}" ( i64 123 )' + self.assertInText(pat, str(mod)) + self.assert_valid_ir(mod) + + +class TestGlobalValues(TestBase): + + def test_globals_access(self): + mod = self.module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'foo') + ir.Function(mod, ir.FunctionType(ir.VoidType(), []), 'bar') + globdouble = ir.GlobalVariable(mod, ir.DoubleType(), 'globdouble') + self.assertEqual(mod.get_global('foo'), foo) + self.assertEqual(mod.get_global('globdouble'), globdouble) + with self.assertRaises(KeyError): + mod.get_global('kkk') + # Globals should have a useful repr() + self.assertEqual(repr(globdouble), + "") + + def test_functions_global_values_access(self): + """ + Accessing functions and global values through Module.functions + and Module.global_values. + """ + mod = self.module() + fty = ir.FunctionType(ir.VoidType(), []) + foo = ir.Function(mod, fty, 'foo') + bar = ir.Function(mod, fty, 'bar') + globdouble = ir.GlobalVariable(mod, ir.DoubleType(), 'globdouble') + self.assertEqual(set(mod.functions), set((foo, bar))) + self.assertEqual(set(mod.global_values), set((foo, bar, globdouble))) + + def test_global_variables_ir(self): + """ + IR serialization of global variables. + """ + mod = self.module() + # the following have side effects and write to self.module() + a = ir.GlobalVariable(mod, int8, 'a') # noqa F841 + b = ir.GlobalVariable(mod, int8, 'b', addrspace=42) # noqa F841 + # Initialized global variable doesn't default to "external" + c = ir.GlobalVariable(mod, int32, 'c') + c.initializer = int32(123) + d = ir.GlobalVariable(mod, int32, 'd') + d.global_constant = True + # Non-external linkage implies default "undef" initializer + e = ir.GlobalVariable(mod, int32, 'e') + e.linkage = "internal" + f = ir.GlobalVariable(mod, int32, 'f', addrspace=456) + f.unnamed_addr = True + g = ir.GlobalVariable(mod, int32, 'g') + g.linkage = "internal" + g.initializer = int32(123) + g.align = 16 + h = ir.GlobalVariable(mod, int32, 'h') + h.linkage = "internal" + h.initializer = int32(123) + h.section = "h_section" + i = ir.GlobalVariable(mod, int32, 'i') + i.linkage = "internal" + i.initializer = int32(456) + i.align = 8 + i.section = "i_section" + self.check_module_body(mod, """\ + @"a" = external global i8 + @"b" = external addrspace(42) global i8 + @"c" = global i32 123 + @"d" = external constant i32 + @"e" = internal global i32 undef + @"f" = external unnamed_addr addrspace(456) global i32 + @"g" = internal global i32 123, align 16 + @"h" = internal global i32 123, section "h_section" + @"i" = internal global i32 456, section "i_section", align 8 + """) + + def test_pickle(self): + mod = self.module() + self.assert_pickle_correctly(mod) + + +class TestBlock(TestBase): + + def test_attributes(self): + func = self.function() + block = ir.Block(parent=func, name='start') + self.assertIs(block.parent, func) + self.assertFalse(block.is_terminated) + + def test_descr(self): + block = self.block(name='my_block') + self.assertEqual(self.descr(block), "my_block:\n") + block.instructions.extend(['a', 'b']) + self.assertEqual(self.descr(block), "my_block:\n a\n b\n") + + def test_replace(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + c = builder.add(a, b, 'c') + d = builder.sub(a, b, 'd') + builder.mul(d, b, 'e') + f = ir.Instruction(block, a.type, 'sdiv', (c, b), 'f') + self.check_block(block, """\ + my_block: + %"c" = add i32 %".1", %".2" + %"d" = sub i32 %".1", %".2" + %"e" = mul i32 %"d", %".2" + """) + block.replace(d, f) + self.check_block(block, """\ + my_block: + %"c" = add i32 %".1", %".2" + %"f" = sdiv i32 %"c", %".2" + %"e" = mul i32 %"f", %".2" + """) + + def test_repr(self): + """ + Blocks should have a useful repr() + """ + func = self.function() + block = ir.Block(parent=func, name='start') + self.assertEqual(repr(block), "") + + +class TestBuildInstructions(TestBase): + """ + Test IR generation of LLVM instructions through the IRBuilder class. + """ + + maxDiff = 4000 + + def test_simple(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + inst = builder.add(a, b, 'res') + self.check_block(block, """\ + my_block: + %"res" = add i32 %".1", %".2" + """) + # Instructions should have a useful repr() + self.assertEqual(repr(inst), + ", " + ")>") + + def test_binops(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b, ff = builder.function.args[:3] + builder.add(a, b, 'c') + builder.fadd(a, b, 'd') + builder.sub(a, b, 'e') + builder.fsub(a, b, 'f') + builder.mul(a, b, 'g') + builder.fmul(a, b, 'h') + builder.udiv(a, b, 'i') + builder.sdiv(a, b, 'j') + builder.fdiv(a, b, 'k') + builder.urem(a, b, 'l') + builder.srem(a, b, 'm') + builder.frem(a, b, 'n') + builder.or_(a, b, 'o') + builder.and_(a, b, 'p') + builder.xor(a, b, 'q') + builder.shl(a, b, 'r') + builder.ashr(a, b, 's') + builder.lshr(a, b, 't') + with self.assertRaises(ValueError) as cm: + builder.add(a, ff) + self.assertEqual(str(cm.exception), + "Operands must be the same type, got (i32, double)") + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"c" = add i32 %".1", %".2" + %"d" = fadd i32 %".1", %".2" + %"e" = sub i32 %".1", %".2" + %"f" = fsub i32 %".1", %".2" + %"g" = mul i32 %".1", %".2" + %"h" = fmul i32 %".1", %".2" + %"i" = udiv i32 %".1", %".2" + %"j" = sdiv i32 %".1", %".2" + %"k" = fdiv i32 %".1", %".2" + %"l" = urem i32 %".1", %".2" + %"m" = srem i32 %".1", %".2" + %"n" = frem i32 %".1", %".2" + %"o" = or i32 %".1", %".2" + %"p" = and i32 %".1", %".2" + %"q" = xor i32 %".1", %".2" + %"r" = shl i32 %".1", %".2" + %"s" = ashr i32 %".1", %".2" + %"t" = lshr i32 %".1", %".2" + """) + + def test_binop_flags(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + # As tuple + builder.add(a, b, 'c', flags=('nuw',)) + # and as list + builder.sub(a, b, 'd', flags=['nuw', 'nsw']) + self.check_block(block, """\ + my_block: + %"c" = add nuw i32 %".1", %".2" + %"d" = sub nuw nsw i32 %".1", %".2" + """) + + def test_binop_fastmath_flags(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + # As tuple + builder.fadd(a, b, 'c', flags=('fast',)) + # and as list + builder.fsub(a, b, 'd', flags=['ninf', 'nsz']) + self.check_block(block, """\ + my_block: + %"c" = fadd fast i32 %".1", %".2" + %"d" = fsub ninf nsz i32 %".1", %".2" + """) + + def test_binops_with_overflow(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + builder.sadd_with_overflow(a, b, 'c') + builder.smul_with_overflow(a, b, 'd') + builder.ssub_with_overflow(a, b, 'e') + builder.uadd_with_overflow(a, b, 'f') + builder.umul_with_overflow(a, b, 'g') + builder.usub_with_overflow(a, b, 'h') + self.check_block(block, """\ +my_block: + %"c" = call {i32, i1} @"llvm.sadd.with.overflow.i32"(i32 %".1", i32 %".2") + %"d" = call {i32, i1} @"llvm.smul.with.overflow.i32"(i32 %".1", i32 %".2") + %"e" = call {i32, i1} @"llvm.ssub.with.overflow.i32"(i32 %".1", i32 %".2") + %"f" = call {i32, i1} @"llvm.uadd.with.overflow.i32"(i32 %".1", i32 %".2") + %"g" = call {i32, i1} @"llvm.umul.with.overflow.i32"(i32 %".1", i32 %".2") + %"h" = call {i32, i1} @"llvm.usub.with.overflow.i32"(i32 %".1", i32 %".2") + """) + + def test_unary_ops(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b, c = builder.function.args[:3] + builder.neg(a, 'd') + builder.not_(b, 'e') + builder.fneg(c, 'f') + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"d" = sub i32 0, %".1" + %"e" = xor i32 %".2", -1 + %"f" = fneg double %".3" + """) + + def test_replace_operand(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + undef1 = ir.Constant(ir.IntType(32), ir.Undefined) + undef2 = ir.Constant(ir.IntType(32), ir.Undefined) + c = builder.add(undef1, undef2, 'c') + self.check_block(block, """\ + my_block: + %"c" = add i32 undef, undef + """) + c.replace_usage(undef1, a) + c.replace_usage(undef2, b) + self.check_block(block, """\ + my_block: + %"c" = add i32 %".1", %".2" + """) + + def test_integer_comparisons(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + builder.icmp_unsigned('==', a, b, 'c') + builder.icmp_unsigned('!=', a, b, 'd') + builder.icmp_unsigned('<', a, b, 'e') + builder.icmp_unsigned('<=', a, b, 'f') + builder.icmp_unsigned('>', a, b, 'g') + builder.icmp_unsigned('>=', a, b, 'h') + builder.icmp_signed('==', a, b, 'i') + builder.icmp_signed('!=', a, b, 'j') + builder.icmp_signed('<', a, b, 'k') + builder.icmp_signed('<=', a, b, 'l') + builder.icmp_signed('>', a, b, 'm') + builder.icmp_signed('>=', a, b, 'n') + with self.assertRaises(ValueError): + builder.icmp_signed('uno', a, b, 'zz') + with self.assertRaises(ValueError): + builder.icmp_signed('foo', a, b, 'zz') + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"c" = icmp eq i32 %".1", %".2" + %"d" = icmp ne i32 %".1", %".2" + %"e" = icmp ult i32 %".1", %".2" + %"f" = icmp ule i32 %".1", %".2" + %"g" = icmp ugt i32 %".1", %".2" + %"h" = icmp uge i32 %".1", %".2" + %"i" = icmp eq i32 %".1", %".2" + %"j" = icmp ne i32 %".1", %".2" + %"k" = icmp slt i32 %".1", %".2" + %"l" = icmp sle i32 %".1", %".2" + %"m" = icmp sgt i32 %".1", %".2" + %"n" = icmp sge i32 %".1", %".2" + """) + + def test_float_comparisons(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + builder.fcmp_ordered('==', a, b, 'c') + builder.fcmp_ordered('!=', a, b, 'd') + builder.fcmp_ordered('<', a, b, 'e') + builder.fcmp_ordered('<=', a, b, 'f') + builder.fcmp_ordered('>', a, b, 'g') + builder.fcmp_ordered('>=', a, b, 'h') + builder.fcmp_unordered('==', a, b, 'i') + builder.fcmp_unordered('!=', a, b, 'j') + builder.fcmp_unordered('<', a, b, 'k') + builder.fcmp_unordered('<=', a, b, 'l') + builder.fcmp_unordered('>', a, b, 'm') + builder.fcmp_unordered('>=', a, b, 'n') + # fcmp_ordered and fcmp_unordered are the same for these cases + builder.fcmp_ordered('ord', a, b, 'u') + builder.fcmp_ordered('uno', a, b, 'v') + builder.fcmp_unordered('ord', a, b, 'w') + builder.fcmp_unordered('uno', a, b, 'x') + builder.fcmp_unordered('olt', a, b, 'y', + flags=['nnan', 'ninf', 'nsz', 'arcp', 'fast']) + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"c" = fcmp oeq i32 %".1", %".2" + %"d" = fcmp one i32 %".1", %".2" + %"e" = fcmp olt i32 %".1", %".2" + %"f" = fcmp ole i32 %".1", %".2" + %"g" = fcmp ogt i32 %".1", %".2" + %"h" = fcmp oge i32 %".1", %".2" + %"i" = fcmp ueq i32 %".1", %".2" + %"j" = fcmp une i32 %".1", %".2" + %"k" = fcmp ult i32 %".1", %".2" + %"l" = fcmp ule i32 %".1", %".2" + %"m" = fcmp ugt i32 %".1", %".2" + %"n" = fcmp uge i32 %".1", %".2" + %"u" = fcmp ord i32 %".1", %".2" + %"v" = fcmp uno i32 %".1", %".2" + %"w" = fcmp ord i32 %".1", %".2" + %"x" = fcmp uno i32 %".1", %".2" + %"y" = fcmp nnan ninf nsz arcp fast olt i32 %".1", %".2" + """) + + def test_misc_ops(self): + block = self.block(name='my_block') + t = ir.Constant(int1, True) + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + builder.select(t, a, b, 'c', flags=('arcp', 'nnan')) + self.assertFalse(block.is_terminated) + builder.unreachable() + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + %"c" = select arcp nnan i1 true, i32 %".1", i32 %".2" + unreachable + """) + + def test_phi(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + bb2 = builder.function.append_basic_block('b2') + bb3 = builder.function.append_basic_block('b3') + phi = builder.phi(int32, 'my_phi', flags=('fast',)) + phi.add_incoming(a, bb2) + phi.add_incoming(b, bb3) + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"my_phi" = phi fast i32 [%".1", %"b2"], [%".2", %"b3"] + """) + + def test_mem_ops(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b, z = builder.function.args[:3] + c = builder.alloca(int32, name='c') + d = builder.alloca(int32, size=42, name='d') # noqa F841 + e = builder.alloca(dbl, size=a, name='e') + e.align = 8 + self.assertEqual(e.type, ir.PointerType(dbl)) + ee = builder.store(z, e) + self.assertEqual(ee.type, ir.VoidType()) + f = builder.store(b, c) + self.assertEqual(f.type, ir.VoidType()) + g = builder.load(c, 'g') + self.assertEqual(g.type, int32) + # With alignment + h = builder.store(b, c, align=1) + self.assertEqual(h.type, ir.VoidType()) + i = builder.load(c, 'i', align=1) + self.assertEqual(i.type, int32) + # Atomics + j = builder.store_atomic(b, c, ordering="seq_cst", align=4) + self.assertEqual(j.type, ir.VoidType()) + k = builder.load_atomic(c, ordering="seq_cst", align=4, name='k') + self.assertEqual(k.type, int32) + # Not pointer types + with self.assertRaises(TypeError): + builder.store(b, a) + with self.assertRaises(TypeError): + builder.load(b) + # Mismatching pointer type + with self.assertRaises(TypeError) as cm: + builder.store(b, e) + self.assertEqual(str(cm.exception), + "cannot store i32 to double*: mismatching types") + self.check_block(block, """\ + my_block: + %"c" = alloca i32 + %"d" = alloca i32, i32 42 + %"e" = alloca double, i32 %".1", align 8 + store double %".3", double* %"e" + store i32 %".2", i32* %"c" + %"g" = load i32, i32* %"c" + store i32 %".2", i32* %"c", align 1 + %"i" = load i32, i32* %"c", align 1 + store atomic i32 %".2", i32* %"c" seq_cst, align 4 + %"k" = load atomic i32, i32* %"c" seq_cst, align 4 + """) + + def test_gep(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + c = builder.alloca(ir.PointerType(int32), name='c') + d = builder.gep(c, [ir.Constant(int32, 5), a], name='d') + self.assertEqual(d.type, ir.PointerType(int32)) + self.check_block(block, """\ + my_block: + %"c" = alloca i32* + %"d" = getelementptr i32*, i32** %"c", i32 5, i32 %".1" + """) + # XXX test with more complex types + + def test_gep_castinstr(self): + # similar to: + # numba::runtime::nrtdynmod.py_define_nrt_meminfo_data() + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + int8ptr = int8.as_pointer() + ls = ir.LiteralStructType([int64, int8ptr, int8ptr, int8ptr, int64]) + d = builder.bitcast(a, ls.as_pointer(), name='d') + e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') + self.assertEqual(e.type, ir.PointerType(int8ptr)) + self.check_block(block, """\ + my_block: + %"d" = bitcast i32 %".1" to {i64, i8*, i8*, i8*, i64}* + %"e" = getelementptr {i64, i8*, i8*, i8*, i64}, {i64, i8*, i8*, i8*, i64}* %"d", i32 0, i32 3 + """) # noqa E501 + + def test_gep_castinstr_addrspace(self): + # similar to: + # numba::runtime::nrtdynmod.py_define_nrt_meminfo_data() + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + addrspace = 4 + int8ptr = int8.as_pointer() + ls = ir.LiteralStructType([int64, int8ptr, int8ptr, int8ptr, int64]) + d = builder.bitcast(a, ls.as_pointer(addrspace=addrspace), name='d') + e = builder.gep(d, [ir.Constant(int32, x) for x in [0, 3]], name='e') + self.assertEqual(e.type.addrspace, addrspace) + self.assertEqual(e.type, ir.PointerType(int8ptr, addrspace=addrspace)) + self.check_block(block, """\ + my_block: + %"d" = bitcast i32 %".1" to {i64, i8*, i8*, i8*, i64} addrspace(4)* + %"e" = getelementptr {i64, i8*, i8*, i8*, i64}, {i64, i8*, i8*, i8*, i64} addrspace(4)* %"d", i32 0, i32 3 + """) # noqa E501 + + def test_gep_addrspace(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + addrspace = 4 + c = builder.alloca(ir.PointerType(int32, addrspace=addrspace), name='c') + self.assertEqual(str(c.type), 'i32 addrspace(4)**') + self.assertEqual(c.type.pointee.addrspace, addrspace) + d = builder.gep(c, [ir.Constant(int32, 5), a], name='d') + self.assertEqual(d.type.addrspace, addrspace) + e = builder.gep(d, [ir.Constant(int32, 10)], name='e') + self.assertEqual(e.type.addrspace, addrspace) + self.check_block(block, """\ + my_block: + %"c" = alloca i32 addrspace(4)* + %"d" = getelementptr i32 addrspace(4)*, i32 addrspace(4)** %"c", i32 5, i32 %".1" + %"e" = getelementptr i32, i32 addrspace(4)* %"d", i32 10 + """) # noqa E501 + + def test_extract_insert_value(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + tp_inner = ir.LiteralStructType([int32, int1]) + tp_outer = ir.LiteralStructType([int8, tp_inner]) + c_inner = ir.Constant(tp_inner, (ir.Constant(int32, 4), + ir.Constant(int1, True))) + # Flat structure + c = builder.extract_value(c_inner, 0, name='c') # noqa F841 + d = builder.insert_value(c_inner, a, 0, name='d') # noqa F841 + e = builder.insert_value(d, ir.Constant(int1, False), 1, name='e') # noqa F841 E501 + self.assertEqual(d.type, tp_inner) + self.assertEqual(e.type, tp_inner) + # Nested structure + p_outer = builder.alloca(tp_outer, name='ptr') + j = builder.load(p_outer, name='j') + k = builder.extract_value(j, 0, name='k') + l = builder.extract_value(j, 1, name='l') + m = builder.extract_value(j, (1, 0), name='m') + n = builder.extract_value(j, (1, 1), name='n') + o = builder.insert_value(j, l, 1, name='o') + p = builder.insert_value(j, a, (1, 0), name='p') + self.assertEqual(k.type, int8) + self.assertEqual(l.type, tp_inner) + self.assertEqual(m.type, int32) + self.assertEqual(n.type, int1) + self.assertEqual(o.type, tp_outer) + self.assertEqual(p.type, tp_outer) + + with self.assertRaises(TypeError): + # Not an aggregate + builder.extract_value(p_outer, 0) + with self.assertRaises(TypeError): + # Indexing too deep + builder.extract_value(c_inner, (0, 0)) + with self.assertRaises(TypeError): + # Index out of structure bounds + builder.extract_value(c_inner, 5) + with self.assertRaises(TypeError): + # Not an aggregate + builder.insert_value(a, b, 0) + with self.assertRaises(TypeError): + # Replacement value has the wrong type + builder.insert_value(c_inner, a, 1) + + self.check_block(block, """\ + my_block: + %"c" = extractvalue {i32, i1} {i32 4, i1 true}, 0 + %"d" = insertvalue {i32, i1} {i32 4, i1 true}, i32 %".1", 0 + %"e" = insertvalue {i32, i1} %"d", i1 false, 1 + %"ptr" = alloca {i8, {i32, i1}} + %"j" = load {i8, {i32, i1}}, {i8, {i32, i1}}* %"ptr" + %"k" = extractvalue {i8, {i32, i1}} %"j", 0 + %"l" = extractvalue {i8, {i32, i1}} %"j", 1 + %"m" = extractvalue {i8, {i32, i1}} %"j", 1, 0 + %"n" = extractvalue {i8, {i32, i1}} %"j", 1, 1 + %"o" = insertvalue {i8, {i32, i1}} %"j", {i32, i1} %"l", 1 + %"p" = insertvalue {i8, {i32, i1}} %"j", i32 %".1", 1, 0 + """) + + def test_cast_ops(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b, fa, ptr = builder.function.args[:4] + c = builder.trunc(a, int8, name='c') + d = builder.zext(c, int32, name='d') # noqa F841 + e = builder.sext(c, int32, name='e') # noqa F841 + fb = builder.fptrunc(fa, flt, 'fb') + fc = builder.fpext(fb, dbl, 'fc') # noqa F841 + g = builder.fptoui(fa, int32, 'g') + h = builder.fptosi(fa, int8, 'h') + fd = builder.uitofp(g, flt, 'fd') # noqa F841 + fe = builder.sitofp(h, dbl, 'fe') # noqa F841 + i = builder.ptrtoint(ptr, int32, 'i') + j = builder.inttoptr(i, ir.PointerType(int8), 'j') # noqa F841 + k = builder.bitcast(a, flt, "k") # noqa F841 + self.assertFalse(block.is_terminated) + self.check_block(block, """\ + my_block: + %"c" = trunc i32 %".1" to i8 + %"d" = zext i8 %"c" to i32 + %"e" = sext i8 %"c" to i32 + %"fb" = fptrunc double %".3" to float + %"fc" = fpext float %"fb" to double + %"g" = fptoui double %".3" to i32 + %"h" = fptosi double %".3" to i8 + %"fd" = uitofp i32 %"g" to float + %"fe" = sitofp i8 %"h" to double + %"i" = ptrtoint i32* %".4" to i32 + %"j" = inttoptr i32 %"i" to i8* + %"k" = bitcast i32 %".1" to float + """) + + def test_atomicrmw(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + c = builder.alloca(int32, name='c') + d = builder.atomic_rmw('add', c, a, 'monotonic', 'd') + self.assertEqual(d.type, int32) + self.check_block(block, """\ + my_block: + %"c" = alloca i32 + %"d" = atomicrmw add i32* %"c", i32 %".1" monotonic + """) + + def test_branch(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + bb_target = builder.function.append_basic_block(name='target') + builder.branch(bb_target) + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + br label %"target" + """) + + def test_cbranch(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + bb_true = builder.function.append_basic_block(name='b_true') + bb_false = builder.function.append_basic_block(name='b_false') + builder.cbranch(ir.Constant(int1, False), bb_true, bb_false) + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + br i1 false, label %"b_true", label %"b_false" + """) + + def test_cbranch_weights(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + bb_true = builder.function.append_basic_block(name='b_true') + bb_false = builder.function.append_basic_block(name='b_false') + br = builder.cbranch(ir.Constant(int1, False), bb_true, bb_false) + br.set_weights([5, 42]) + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + br i1 false, label %"b_true", label %"b_false", !prof !0 + """) + self.check_metadata(builder.module, """\ + !0 = !{ !"branch_weights", i32 5, i32 42 } + """) + + def test_branch_indirect(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + bb_1 = builder.function.append_basic_block(name='b_1') + bb_2 = builder.function.append_basic_block(name='b_2') + indirectbr = builder.branch_indirect( + ir.BlockAddress(builder.function, bb_1)) + indirectbr.add_destination(bb_1) + indirectbr.add_destination(bb_2) + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + indirectbr i8* blockaddress(@"my_func", %"b_1"), [label %"b_1", label %"b_2"] + """) # noqa E501 + + def test_returns(self): + def check(block, expected_ir): + self.assertTrue(block.is_terminated) + self.check_block(block, expected_ir) + + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + builder.ret_void() + check(block, """\ + my_block: + ret void + """) + + block = self.block(name='other_block') + builder = ir.IRBuilder(block) + builder.ret(int32(5)) + check(block, """\ + other_block: + ret i32 5 + """) + + # With metadata + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + inst = builder.ret_void() + inst.set_metadata("dbg", block.module.add_metadata(())) + check(block, """\ + my_block: + ret void, !dbg !0 + """) + + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + inst = builder.ret(int32(6)) + inst.set_metadata("dbg", block.module.add_metadata(())) + check(block, """\ + my_block: + ret i32 6, !dbg !0 + """) + + def test_switch(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + bb_onzero = builder.function.append_basic_block(name='onzero') + bb_onone = builder.function.append_basic_block(name='onone') + bb_ontwo = builder.function.append_basic_block(name='ontwo') + bb_else = builder.function.append_basic_block(name='otherwise') + sw = builder.switch(a, bb_else) + sw.add_case(ir.Constant(int32, 0), bb_onzero) + sw.add_case(ir.Constant(int32, 1), bb_onone) + # A plain Python value gets converted into the right IR constant + sw.add_case(2, bb_ontwo) + self.assertTrue(block.is_terminated) + self.check_block(block, """\ + my_block: + switch i32 %".1", label %"otherwise" [i32 0, label %"onzero" i32 1, label %"onone" i32 2, label %"ontwo"] + """) # noqa E501 + + def test_call(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + tp_f = ir.FunctionType(flt, (int32, int32)) + tp_g = ir.FunctionType(dbl, (int32,), var_arg=True) + tp_h = ir.FunctionType(hlf, (int32, int32)) + f = ir.Function(builder.function.module, tp_f, 'f') + g = ir.Function(builder.function.module, tp_g, 'g') + h = ir.Function(builder.function.module, tp_h, 'h') + builder.call(f, (a, b), 'res_f') + builder.call(g, (b, a), 'res_g') + builder.call(h, (a, b), 'res_h') + builder.call(f, (a, b), 'res_f_fast', cconv='fastcc') + res_f_readonly = builder.call(f, (a, b), 'res_f_readonly') + res_f_readonly.attributes.add('readonly') + builder.call(f, (a, b), 'res_fast', fastmath='fast') + builder.call(f, (a, b), 'res_nnan_ninf', fastmath=('nnan', 'ninf')) + builder.call(f, (a, b), 'res_noinline', attrs='noinline') + builder.call(f, (a, b), 'res_alwaysinline', attrs='alwaysinline') + builder.call(f, (a, b), 'res_noinline_ro', attrs=('noinline', + 'readonly')) + self.check_block(block, """\ + my_block: + %"res_f" = call float @"f"(i32 %".1", i32 %".2") + %"res_g" = call double (i32, ...) @"g"(i32 %".2", i32 %".1") + %"res_h" = call half @"h"(i32 %".1", i32 %".2") + %"res_f_fast" = call fastcc float @"f"(i32 %".1", i32 %".2") + %"res_f_readonly" = call float @"f"(i32 %".1", i32 %".2") readonly + %"res_fast" = call fast float @"f"(i32 %".1", i32 %".2") + %"res_nnan_ninf" = call ninf nnan float @"f"(i32 %".1", i32 %".2") + %"res_noinline" = call float @"f"(i32 %".1", i32 %".2") noinline + %"res_alwaysinline" = call float @"f"(i32 %".1", i32 %".2") alwaysinline + %"res_noinline_ro" = call float @"f"(i32 %".1", i32 %".2") noinline readonly + """) # noqa E501 + + def test_call_metadata(self): + """ + Function calls with metadata arguments. + """ + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + dbg_declare_ty = ir.FunctionType(ir.VoidType(), [ir.MetaDataType()] * 3) + dbg_declare = ir.Function( + builder.module, + dbg_declare_ty, + 'llvm.dbg.declare') + a = builder.alloca(int32, name="a") + b = builder.module.add_metadata(()) + builder.call(dbg_declare, (a, b, b)) + self.check_block(block, """\ + my_block: + %"a" = alloca i32 + call void @"llvm.dbg.declare"(metadata i32* %"a", metadata !0, metadata !0) + """) # noqa E501 + + def test_call_attributes(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + fun_ty = ir.FunctionType( + ir.VoidType(), (int32.as_pointer(), int32, int32.as_pointer())) + fun = ir.Function(builder.function.module, fun_ty, 'fun') + fun.args[0].add_attribute('sret') + retval = builder.alloca(int32, name='retval') + other = builder.alloca(int32, name='other') + builder.call( + fun, + (retval, ir.Constant(int32, 42), other), + arg_attrs={ + 0: ('sret', 'noalias'), + 2: 'noalias' + } + ) + self.check_block_regex(block, """\ + my_block: + %"retval" = alloca i32 + %"other" = alloca i32 + call void @"fun"\\(i32\\* noalias sret(\\(i32\\))? %"retval", i32 42, i32\\* noalias %"other"\\) + """) # noqa E501 + + def test_call_tail(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + fun_ty = ir.FunctionType(ir.VoidType(), ()) + fun = ir.Function(builder.function.module, fun_ty, 'my_fun') + + builder.call(fun, ()) + builder.call(fun, (), tail=False) + builder.call(fun, (), tail=True) + builder.call(fun, (), tail='tail') + builder.call(fun, (), tail='notail') + builder.call(fun, (), tail='musttail') + builder.call(fun, (), tail=[]) # This is a falsy value + builder.call(fun, (), tail='not a marker') # This is a truthy value + + self.check_block(block, """\ + my_block: + call void @"my_fun"() + call void @"my_fun"() + tail call void @"my_fun"() + tail call void @"my_fun"() + notail call void @"my_fun"() + musttail call void @"my_fun"() + call void @"my_fun"() + tail call void @"my_fun"() + """) # noqa E501 + + def test_invalid_call_attributes(self): + block = self.block() + builder = ir.IRBuilder(block) + fun_ty = ir.FunctionType(ir.VoidType(), ()) + fun = ir.Function(builder.function.module, fun_ty, 'fun') + with self.assertRaises(ValueError): + # The function has no arguments, so this should fail. + builder.call(fun, (), arg_attrs={0: 'sret'}) + + def test_invoke(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + tp_f = ir.FunctionType(flt, (int32, int32)) + f = ir.Function(builder.function.module, tp_f, 'f') + bb_normal = builder.function.append_basic_block(name='normal') + bb_unwind = builder.function.append_basic_block(name='unwind') + builder.invoke(f, (a, b), bb_normal, bb_unwind, 'res_f') + self.check_block(block, """\ + my_block: + %"res_f" = invoke float @"f"(i32 %".1", i32 %".2") + to label %"normal" unwind label %"unwind" + """) + + def test_invoke_attributes(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + fun_ty = ir.FunctionType( + ir.VoidType(), (int32.as_pointer(), int32, int32.as_pointer())) + fun = ir.Function(builder.function.module, fun_ty, 'fun') + fun.calling_convention = "fastcc" + fun.args[0].add_attribute('sret') + retval = builder.alloca(int32, name='retval') + other = builder.alloca(int32, name='other') + bb_normal = builder.function.append_basic_block(name='normal') + bb_unwind = builder.function.append_basic_block(name='unwind') + builder.invoke( + fun, + (retval, ir.Constant(int32, 42), other), + bb_normal, + bb_unwind, + cconv='fastcc', + fastmath='fast', + attrs='noinline', + arg_attrs={ + 0: ('sret', 'noalias'), + 2: 'noalias' + } + ) + self.check_block_regex(block, """\ + my_block: + %"retval" = alloca i32 + %"other" = alloca i32 + invoke fast fastcc void @"fun"\\(i32\\* noalias sret(\\(i32\\))? %"retval", i32 42, i32\\* noalias %"other"\\) noinline + to label %"normal" unwind label %"unwind" + """) # noqa E501 + + def test_landingpad(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + lp = builder.landingpad(ir.LiteralStructType([int32, + int8.as_pointer()]), 'lp') + int_typeinfo = ir.GlobalVariable(builder.function.module, + int8.as_pointer(), "_ZTIi") + int_typeinfo.global_constant = True + lp.add_clause(ir.CatchClause(int_typeinfo)) + lp.add_clause(ir.FilterClause(ir.Constant(ir.ArrayType( + int_typeinfo.type, 1), [int_typeinfo]))) + builder.resume(lp) + self.check_block(block, """\ + my_block: + %"lp" = landingpad {i32, i8*} + catch i8** @"_ZTIi" + filter [1 x i8**] [i8** @"_ZTIi"] + resume {i32, i8*} %"lp" + """) + + def test_assume(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + c = builder.icmp_signed('>', a, b, name='c') + builder.assume(c) + self.check_block(block, """\ + my_block: + %"c" = icmp sgt i32 %".1", %".2" + call void @"llvm.assume"(i1 %"c") + """) + + def test_vector_ops(self): + block = self.block(name='insert_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + a.name = 'a' + b.name = 'b' + + vecty = ir.VectorType(a.type, 2) + vec = ir.Constant(vecty, ir.Undefined) + idxty = ir.IntType(32) + vec = builder.insert_element(vec, a, idxty(0), name='vec1') + vec = builder.insert_element(vec, b, idxty(1), name='vec2') + + self.check_block(block, """\ +insert_block: + %"vec1" = insertelement <2 x i32> , i32 %"a", i32 0 + %"vec2" = insertelement <2 x i32> %"vec1", i32 %"b", i32 1 + """) + + block = builder.append_basic_block("shuffle_block") + builder.branch(block) + builder.position_at_end(block) + + mask = ir.Constant(vecty, [1, 0]) + builder.shuffle_vector(vec, vec, mask, name='shuf') + + self.check_block(block, """\ + shuffle_block: + %"shuf" = shufflevector <2 x i32> %"vec2", <2 x i32> %"vec2", <2 x i32> + """) # noqa E501 + + block = builder.append_basic_block("add_block") + builder.branch(block) + builder.position_at_end(block) + + builder.add(vec, vec, name='sum') + + self.check_block(block, """\ + add_block: + %"sum" = add <2 x i32> %"vec2", %"vec2" + """) + + block = builder.append_basic_block("extract_block") + builder.branch(block) + builder.position_at_end(block) + + c = builder.extract_element(vec, idxty(0), name='ex1') + d = builder.extract_element(vec, idxty(1), name='ex2') + + self.check_block(block, """\ + extract_block: + %"ex1" = extractelement <2 x i32> %"vec2", i32 0 + %"ex2" = extractelement <2 x i32> %"vec2", i32 1 + """) + + builder.ret(builder.add(c, d)) + self.assert_valid_ir(builder.module) + + def test_bitreverse(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int64, 5) + c = builder.bitreverse(a, name='c') + builder.ret(c) + self.check_block(block, """\ + my_block: + %"c" = call i64 @"llvm.bitreverse.i64"(i64 5) + ret i64 %"c" + """) + + def test_bitreverse_wrongtype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5) + + with self.assertRaises(TypeError) as raises: + builder.bitreverse(a, name='c') + self.assertIn( + "expected an integer type, got float", + str(raises.exception)) + + def test_fence(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + with self.assertRaises(ValueError) as raises: + builder.fence("monotonic", None) + self.assertIn( + "Invalid fence ordering \"monotonic\"!", + str(raises.exception)) + with self.assertRaises(ValueError) as raises: + builder.fence(None, "monotonic") + self.assertIn( + "Invalid fence ordering \"None\"!", + str(raises.exception)) + builder.fence("acquire", None) + builder.fence("release", "singlethread") + builder.fence("acq_rel", "singlethread") + builder.fence("seq_cst") + builder.ret_void() + self.check_block(block, """\ + my_block: + fence acquire + fence syncscope("singlethread") release + fence syncscope("singlethread") acq_rel + fence seq_cst + ret void + """) + + def test_comment(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + with self.assertRaises(AssertionError): + builder.comment("so\nmany lines") + builder.comment("my comment") + builder.ret_void() + self.check_block(block, """\ + my_block: + ; my comment + ret void + """) + + def test_bswap(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int32, 5) + c = builder.bswap(a, name='c') + builder.ret(c) + self.check_block(block, """\ + my_block: + %"c" = call i32 @"llvm.bswap.i32"(i32 5) + ret i32 %"c" + """) + + def test_ctpop(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int16, 5) + c = builder.ctpop(a, name='c') + builder.ret(c) + self.check_block(block, """\ + my_block: + %"c" = call i16 @"llvm.ctpop.i16"(i16 5) + ret i16 %"c" + """) + + def test_ctlz(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int16, 5) + b = ir.Constant(int1, 1) + c = builder.ctlz(a, b, name='c') + builder.ret(c) + self.check_block(block, """\ + my_block: + %"c" = call i16 @"llvm.ctlz.i16"(i16 5, i1 1) + ret i16 %"c" + """) + + def test_convert_to_fp16_f32(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5.0) + b = builder.convert_to_fp16(a, name='b') + builder.ret(b) + self.check_block(block, """\ + my_block: + %"b" = call i16 @"llvm.convert.to.fp16.f32"(float 0x4014000000000000) + ret i16 %"b" + """) # noqa E501 + + def test_convert_to_fp16_f32_wrongtype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int16, 5) + + with self.assertRaises(TypeError) as raises: + builder.convert_to_fp16(a, name='b') + self.assertIn( + "expected a float type, got i16", + str(raises.exception)) + + def test_convert_from_fp16_f32(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int16, 5) + b = builder.convert_from_fp16(a, name='b', to=flt) + builder.ret(b) + self.check_block(block, """\ + my_block: + %"b" = call float @"llvm.convert.from.fp16.f32"(i16 5) + ret float %"b" + """) + + def test_convert_from_fp16_f32_notype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5.5) + + with self.assertRaises(TypeError) as raises: + builder.convert_from_fp16(a, name='b') + self.assertIn( + "expected a float return type", + str(raises.exception)) + + def test_convert_from_fp16_f32_wrongtype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5.5) + + with self.assertRaises(TypeError) as raises: + builder.convert_from_fp16(a, name='b', to=flt) + self.assertIn( + "expected an i16 type, got float", + str(raises.exception)) + + def test_convert_from_fp16_f32_wrongtype2(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5.5) + + with self.assertRaises(TypeError) as raises: + builder.convert_from_fp16(a, name='b', to=int16) + self.assertIn( + "expected a float type, got i16", + str(raises.exception)) + + def test_cttz(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int64, 5) + b = ir.Constant(int1, 1) + c = builder.cttz(a, b, name='c') + builder.ret(c) + self.check_block(block, """\ + my_block: + %"c" = call i64 @"llvm.cttz.i64"(i64 5, i1 1) + ret i64 %"c" + """) + + def test_cttz_wrongflag(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int64, 5) + b = ir.Constant(int32, 3) + + with self.assertRaises(TypeError) as raises: + builder.cttz(a, b, name='c') + self.assertIn( + "expected an i1 type, got i32", + str(raises.exception)) + + def test_cttz_wrongtype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5) + b = ir.Constant(int1, 1) + + with self.assertRaises(TypeError) as raises: + builder.cttz(a, b, name='c') + self.assertIn( + "expected an integer type, got float", + str(raises.exception)) + + def test_fma(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5) + b = ir.Constant(flt, 1) + c = ir.Constant(flt, 2) + fma = builder.fma(a, b, c, name='fma') + builder.ret(fma) + self.check_block(block, """\ + my_block: + %"fma" = call float @"llvm.fma.f32"(float 0x4014000000000000, float 0x3ff0000000000000, float 0x4000000000000000) + ret float %"fma" + """) # noqa E501 + + def test_fma_wrongtype(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(int32, 5) + b = ir.Constant(int32, 1) + c = ir.Constant(int32, 2) + + with self.assertRaises(TypeError) as raises: + builder.fma(a, b, c, name='fma') + self.assertIn( + "expected an floating point type, got i32", + str(raises.exception)) + + def test_fma_mixedtypes(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a = ir.Constant(flt, 5) + b = ir.Constant(dbl, 1) + c = ir.Constant(flt, 2) + + with self.assertRaises(TypeError) as raises: + builder.fma(a, b, c, name='fma') + self.assertIn( + "expected types to be the same, got float, double, float", + str(raises.exception)) + + def test_arg_attributes(self): + def gen_code(attr_name): + fnty = ir.FunctionType(ir.IntType(32), [ir.IntType(32).as_pointer(), + ir.IntType(32)]) + module = ir.Module() + + func = ir.Function(module, fnty, name="sum") + + bb_entry = func.append_basic_block() + bb_loop = func.append_basic_block() + bb_exit = func.append_basic_block() + + builder = ir.IRBuilder() + builder.position_at_end(bb_entry) + + builder.branch(bb_loop) + builder.position_at_end(bb_loop) + + index = builder.phi(ir.IntType(32)) + index.add_incoming(ir.Constant(index.type, 0), bb_entry) + accum = builder.phi(ir.IntType(32)) + accum.add_incoming(ir.Constant(accum.type, 0), bb_entry) + + func.args[0].add_attribute(attr_name) + ptr = builder.gep(func.args[0], [index]) + value = builder.load(ptr) + + added = builder.add(accum, value) + accum.add_incoming(added, bb_loop) + + indexp1 = builder.add(index, ir.Constant(index.type, 1)) + index.add_incoming(indexp1, bb_loop) + + cond = builder.icmp_unsigned('<', indexp1, func.args[1]) + builder.cbranch(cond, bb_loop, bb_exit) + + builder.position_at_end(bb_exit) + builder.ret(added) + + return str(module) + + for attr_name in ( + 'byref', + 'byval', + 'elementtype', + 'immarg', + 'inalloca', + 'inreg', + 'nest', + 'noalias', + 'nocapture', + 'nofree', + 'nonnull', + 'noundef', + 'preallocated', + 'returned', + 'signext', + 'swiftasync', + 'swifterror', + 'swiftself', + 'zeroext', + ): + # If this parses, we emitted the right byval attribute format + llvm.parse_assembly(gen_code(attr_name)) + # sret doesn't fit this pattern and is tested in test_call_attributes + + +class TestBuilderMisc(TestBase): + """ + Test various other features of the IRBuilder class. + """ + + def test_attributes(self): + block = self.block(name='start') + builder = ir.IRBuilder(block) + self.assertIs(builder.function, block.parent) + self.assertIsInstance(builder.function, ir.Function) + self.assertIs(builder.module, block.parent.module) + self.assertIsInstance(builder.module, ir.Module) + + def test_goto_block(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + a, b = builder.function.args[:2] + builder.add(a, b, 'c') + bb_new = builder.append_basic_block(name='foo') + with builder.goto_block(bb_new): + builder.fadd(a, b, 'd') + with builder.goto_entry_block(): + builder.sub(a, b, 'e') + builder.fsub(a, b, 'f') + builder.branch(bb_new) + builder.mul(a, b, 'g') + with builder.goto_block(bb_new): + builder.fmul(a, b, 'h') + self.check_block(block, """\ + my_block: + %"c" = add i32 %".1", %".2" + %"e" = sub i32 %".1", %".2" + %"g" = mul i32 %".1", %".2" + """) + self.check_block(bb_new, """\ + foo: + %"d" = fadd i32 %".1", %".2" + %"f" = fsub i32 %".1", %".2" + %"h" = fmul i32 %".1", %".2" + br label %"foo" + """) + + def test_if_then(self): + block = self.block(name='one') + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + a = builder.add(z, z, 'a') + with builder.if_then(a) as bbend: + builder.add(z, z, 'b') + # Block will be terminated implicitly + self.assertIs(builder.block, bbend) + c = builder.add(z, z, 'c') + with builder.if_then(c): + builder.add(z, z, 'd') + builder.branch(block) + # No implicit termination + self.check_func_body(builder.function, """\ + one: + %"a" = add i1 0, 0 + br i1 %"a", label %"one.if", label %"one.endif" + one.if: + %"b" = add i1 0, 0 + br label %"one.endif" + one.endif: + %"c" = add i1 0, 0 + br i1 %"c", label %"one.endif.if", label %"one.endif.endif" + one.endif.if: + %"d" = add i1 0, 0 + br label %"one" + one.endif.endif: + """) + + def test_if_then_nested(self): + # Implicit termination in a nested if/then + block = self.block(name='one') + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + a = builder.add(z, z, 'a') + with builder.if_then(a): + b = builder.add(z, z, 'b') + with builder.if_then(b): + builder.add(z, z, 'c') + builder.ret_void() + self.check_func_body(builder.function, """\ + one: + %"a" = add i1 0, 0 + br i1 %"a", label %"one.if", label %"one.endif" + one.if: + %"b" = add i1 0, 0 + br i1 %"b", label %"one.if.if", label %"one.if.endif" + one.endif: + ret void + one.if.if: + %"c" = add i1 0, 0 + br label %"one.if.endif" + one.if.endif: + br label %"one.endif" + """) + + def test_if_then_long_label(self): + full_label = 'Long' * 20 + block = self.block(name=full_label) + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + a = builder.add(z, z, 'a') + with builder.if_then(a): + b = builder.add(z, z, 'b') + with builder.if_then(b): + builder.add(z, z, 'c') + builder.ret_void() + self.check_func_body(builder.function, """\ + {full_label}: + %"a" = add i1 0, 0 + br i1 %"a", label %"{label}.if", label %"{label}.endif" + {label}.if: + %"b" = add i1 0, 0 + br i1 %"b", label %"{label}.if.if", label %"{label}.if.endif" + {label}.endif: + ret void + {label}.if.if: + %"c" = add i1 0, 0 + br label %"{label}.if.endif" + {label}.if.endif: + br label %"{label}.endif" + """.format(full_label=full_label, label=full_label[:25] + '..')) + + def test_if_then_likely(self): + def check(likely): + block = self.block(name='one') + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + with builder.if_then(z, likely=likely): + pass + self.check_block(block, """\ + one: + br i1 0, label %"one.if", label %"one.endif", !prof !0 + """) + return builder + builder = check(True) + self.check_metadata(builder.module, """\ + !0 = !{ !"branch_weights", i32 99, i32 1 } + """) + builder = check(False) + self.check_metadata(builder.module, """\ + !0 = !{ !"branch_weights", i32 1, i32 99 } + """) + + def test_if_else(self): + block = self.block(name='one') + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + a = builder.add(z, z, 'a') + with builder.if_else(a) as (then, otherwise): + with then: + builder.add(z, z, 'b') + with otherwise: + builder.add(z, z, 'c') + # Each block will be terminated implicitly + with builder.if_else(a) as (then, otherwise): + with then: + builder.branch(block) + with otherwise: + builder.ret_void() + # No implicit termination + self.check_func_body(builder.function, """\ + one: + %"a" = add i1 0, 0 + br i1 %"a", label %"one.if", label %"one.else" + one.if: + %"b" = add i1 0, 0 + br label %"one.endif" + one.else: + %"c" = add i1 0, 0 + br label %"one.endif" + one.endif: + br i1 %"a", label %"one.endif.if", label %"one.endif.else" + one.endif.if: + br label %"one" + one.endif.else: + ret void + one.endif.endif: + """) + + def test_if_else_likely(self): + def check(likely): + block = self.block(name='one') + builder = ir.IRBuilder(block) + z = ir.Constant(int1, 0) + with builder.if_else(z, likely=likely) as (then, otherwise): + with then: + builder.branch(block) + with otherwise: + builder.ret_void() + self.check_func_body(builder.function, """\ + one: + br i1 0, label %"one.if", label %"one.else", !prof !0 + one.if: + br label %"one" + one.else: + ret void + one.endif: + """) + return builder + builder = check(True) + self.check_metadata(builder.module, """\ + !0 = !{ !"branch_weights", i32 99, i32 1 } + """) + builder = check(False) + self.check_metadata(builder.module, """\ + !0 = !{ !"branch_weights", i32 1, i32 99 } + """) + + def test_positioning(self): + """ + Test IRBuilder.position_{before,after,at_start,at_end}. + """ + func = self.function() + builder = ir.IRBuilder() + z = ir.Constant(int32, 0) + bb_one = func.append_basic_block(name='one') + bb_two = func.append_basic_block(name='two') + bb_three = func.append_basic_block(name='three') + # .at_start(empty block) + builder.position_at_start(bb_one) + builder.add(z, z, 'a') + # .at_end(empty block) + builder.position_at_end(bb_two) + builder.add(z, z, 'm') + builder.add(z, z, 'n') + # .at_start(block) + builder.position_at_start(bb_two) + o = builder.add(z, z, 'o') + builder.add(z, z, 'p') + # .at_end(block) + builder.position_at_end(bb_one) + b = builder.add(z, z, 'b') + # .after(instr) + builder.position_after(o) + builder.add(z, z, 'q') + # .before(instr) + builder.position_before(b) + builder.add(z, z, 'c') + self.check_block(bb_one, """\ + one: + %"a" = add i32 0, 0 + %"c" = add i32 0, 0 + %"b" = add i32 0, 0 + """) + self.check_block(bb_two, """\ + two: + %"o" = add i32 0, 0 + %"q" = add i32 0, 0 + %"p" = add i32 0, 0 + %"m" = add i32 0, 0 + %"n" = add i32 0, 0 + """) + self.check_block(bb_three, """\ + three: + """) + + def test_instruction_removal(self): + func = self.function() + builder = ir.IRBuilder() + blk = func.append_basic_block(name='entry') + builder.position_at_end(blk) + k = ir.Constant(int32, 1234) + a = builder.add(k, k, 'a') + retvoid = builder.ret_void() + self.assertTrue(blk.is_terminated) + builder.remove(retvoid) + self.assertFalse(blk.is_terminated) + b = builder.mul(a, a, 'b') + c = builder.add(b, b, 'c') + builder.remove(c) + builder.ret_void() + self.assertTrue(blk.is_terminated) + self.check_block(blk, """\ + entry: + %"a" = add i32 1234, 1234 + %"b" = mul i32 %"a", %"a" + ret void + """) + + def test_metadata(self): + block = self.block(name='my_block') + builder = ir.IRBuilder(block) + builder.debug_metadata = builder.module.add_metadata([]) + builder.alloca(ir.PointerType(int32), name='c') + self.check_block(block, """\ + my_block: + %"c" = alloca i32*, !dbg !0 + """) + + +class TestTypes(TestBase): + + def has_logical_equality(self, ty): + while isinstance(ty, ir.PointerType): + ty = ty.pointee + return not isinstance(ty, ir.LabelType) + + def assorted_types(self): + """ + A bunch of mutually unequal types + """ + # Avoid polluting the namespace + context = ir.Context() + types = [ + ir.LabelType(), ir.VoidType(), + ir.FunctionType(int1, (int8, int8)), ir.FunctionType(int1, (int8,)), + ir.FunctionType(int1, (int8,), var_arg=True), + ir.FunctionType(int8, (int8,)), + int1, int8, int32, flt, dbl, + ir.ArrayType(flt, 5), ir.ArrayType(dbl, 5), ir.ArrayType(dbl, 4), + ir.LiteralStructType((int1, int8)), ir.LiteralStructType((int8, + int1)), + context.get_identified_type("MyType1"), + context.get_identified_type("MyType2"), + ] + types += [ir.PointerType(tp) for tp in types + if not isinstance(tp, (ir.VoidType, ir.LabelType))] + + return types + + def test_pickling(self): + types = self.assorted_types() + for ty in types: + newty = self.assert_pickle_correctly(ty) + if self.has_logical_equality(ty): + self.assertEqual(newty, ty) + + def test_comparisons(self): + types = self.assorted_types() + for a, b in itertools.product(types, types): + if a is not b: + self.assertFalse(a == b, (a, b)) + self.assertTrue(a != b, (a, b)) + # We assume copy.copy() works fine here... + for tp in types: + other = copy.copy(tp) + if self.has_logical_equality(tp): + self.assertTrue(tp == other, (tp, other)) + self.assertFalse(tp != other, (tp, other)) + else: + self.assertFalse(tp == other, (tp, other)) + self.assertTrue(tp != other, (tp, other)) + + def test_str(self): + """ + Test the string representation of types. + """ + self.assertEqual(str(int1), 'i1') + self.assertEqual(str(ir.IntType(29)), 'i29') + self.assertEqual(str(flt), 'float') + self.assertEqual(str(dbl), 'double') + self.assertEqual(str(ir.VoidType()), 'void') + self.assertEqual(str(ir.FunctionType(int1, ())), 'i1 ()') + self.assertEqual(str(ir.FunctionType(int1, (flt,))), 'i1 (float)') + self.assertEqual(str(ir.FunctionType(int1, (flt, dbl))), + 'i1 (float, double)') + self.assertEqual(str(ir.FunctionType(int1, (), var_arg=True)), + 'i1 (...)') + self.assertEqual(str(ir.FunctionType(int1, (flt,), var_arg=True)), + 'i1 (float, ...)') + self.assertEqual(str(ir.FunctionType(int1, (flt, dbl), var_arg=True)), + 'i1 (float, double, ...)') + self.assertEqual(str(ir.PointerType(int32)), 'i32*') + self.assertEqual(str(ir.PointerType(ir.PointerType(int32))), 'i32**') + self.assertEqual(str(ir.ArrayType(int1, 5)), '[5 x i1]') + self.assertEqual(str(ir.ArrayType(ir.PointerType(int1), 5)), + '[5 x i1*]') + self.assertEqual(str(ir.PointerType(ir.ArrayType(int1, 5))), + '[5 x i1]*') + self.assertEqual(str(ir.LiteralStructType((int1,))), '{i1}') + self.assertEqual(str(ir.LiteralStructType((int1, flt))), '{i1, float}') + self.assertEqual(str(ir.LiteralStructType(( + ir.PointerType(int1), ir.LiteralStructType((int32, int8))))), + '{i1*, {i32, i8}}') + self.assertEqual(str(ir.LiteralStructType((int1,), packed=True)), + '<{i1}>') + self.assertEqual(str(ir.LiteralStructType((int1, flt), packed=True)), + '<{i1, float}>') + + # Avoid polluting the namespace + context = ir.Context() + mytype = context.get_identified_type("MyType") + self.assertEqual(str(mytype), "%\"MyType\"") + mytype1 = context.get_identified_type("MyType\\") + self.assertEqual(str(mytype1), "%\"MyType\\5c\"") + mytype2 = context.get_identified_type("MyType\"") + self.assertEqual(str(mytype2), "%\"MyType\\22\"") + + def test_hash(self): + for typ in filter(self.has_logical_equality, self.assorted_types()): + self.assertEqual(hash(typ), hash(copy.copy(typ))) + + def test_gep(self): + def check_constant(tp, i, expected): + actual = tp.gep(ir.Constant(int32, i)) + self.assertEqual(actual, expected) + + def check_index_type(tp): + index = ir.Constant(dbl, 1.0) + with self.assertRaises(TypeError): + tp.gep(index) + + tp = ir.PointerType(dbl) + for i in range(5): + check_constant(tp, i, dbl) + check_index_type(tp) + + tp = ir.ArrayType(int1, 3) + for i in range(3): + check_constant(tp, i, int1) + check_index_type(tp) + + tp = ir.LiteralStructType((dbl, ir.LiteralStructType((int1, int8)))) + check_constant(tp, 0, dbl) + check_constant(tp, 1, ir.LiteralStructType((int1, int8))) + with self.assertRaises(IndexError): + tp.gep(ir.Constant(int32, 2)) + check_index_type(tp) + + context = ir.Context() + tp = ir.IdentifiedStructType(context, "MyType") + tp.set_body(dbl, ir.LiteralStructType((int1, int8))) + check_constant(tp, 0, dbl) + check_constant(tp, 1, ir.LiteralStructType((int1, int8))) + with self.assertRaises(IndexError): + tp.gep(ir.Constant(int32, 2)) + check_index_type(tp) + + def test_abi_size(self): + td = llvm.create_target_data("e-m:e-i64:64-f80:128-n8:16:32:64-S128") + + def check(tp, expected): + self.assertEqual(tp.get_abi_size(td), expected) + check(int8, 1) + check(int32, 4) + check(int64, 8) + check(ir.ArrayType(int8, 5), 5) + check(ir.ArrayType(int32, 5), 20) + check(ir.LiteralStructType((dbl, flt, flt)), 16) + + def test_abi_alignment(self): + td = llvm.create_target_data("e-m:e-i64:64-f80:128-n8:16:32:64-S128") + + def check(tp, expected): + self.assertIn(tp.get_abi_alignment(td), expected) + check(int8, (1, 2, 4)) + check(int32, (4,)) + check(int64, (8,)) + check(ir.ArrayType(int8, 5), (1, 2, 4)) + check(ir.ArrayType(int32, 5), (4,)) + check(ir.LiteralStructType((dbl, flt, flt)), (8,)) + + def test_identified_struct(self): + context = ir.Context() + mytype = context.get_identified_type("MyType") + module = ir.Module(context=context) + self.assertTrue(mytype.is_opaque) + self.assert_valid_ir(module) + oldstr = str(module) + mytype.set_body(ir.IntType(32), ir.IntType(64), ir.FloatType()) + self.assertFalse(mytype.is_opaque) + self.assert_valid_ir(module) + self.assertNotEqual(oldstr, str(module)) + + def test_target_data_non_default_context(self): + context = ir.Context() + mytype = context.get_identified_type("MyType") + mytype.elements = [ir.IntType(32)] + td = llvm.create_target_data("e-m:e-i64:64-f80:128-n8:16:32:64-S128") + self.assertEqual(mytype.get_abi_size(td, context=context), 4) + + def test_vector(self): + vecty = ir.VectorType(ir.IntType(32), 8) + self.assertEqual(str(vecty), "<8 x i32>") + + +def c32(i): + return ir.Constant(int32, i) + + +class TestConstant(TestBase): + + def test_integers(self): + c = ir.Constant(int32, 42) + self.assertEqual(str(c), 'i32 42') + c = ir.Constant(int1, 1) + self.assertEqual(str(c), 'i1 1') + c = ir.Constant(int1, 0) + self.assertEqual(str(c), 'i1 0') + c = ir.Constant(int1, True) + self.assertEqual(str(c), 'i1 true') + c = ir.Constant(int1, False) + self.assertEqual(str(c), 'i1 false') + c = ir.Constant(int1, ir.Undefined) + self.assertEqual(str(c), 'i1 undef') + c = ir.Constant(int1, None) + self.assertEqual(str(c), 'i1 0') + + def test_reals(self): + # XXX Test NaNs and infs + c = ir.Constant(flt, 1.5) + self.assertEqual(str(c), 'float 0x3ff8000000000000') + c = ir.Constant(flt, -1.5) + self.assertEqual(str(c), 'float 0xbff8000000000000') + c = ir.Constant(dbl, 1.5) + self.assertEqual(str(c), 'double 0x3ff8000000000000') + c = ir.Constant(dbl, -1.5) + self.assertEqual(str(c), 'double 0xbff8000000000000') + c = ir.Constant(dbl, ir.Undefined) + self.assertEqual(str(c), 'double undef') + c = ir.Constant(dbl, None) + self.assertEqual(str(c), 'double 0.0') + + def test_arrays(self): + c = ir.Constant(ir.ArrayType(int32, 3), (c32(5), c32(6), c32(4))) + self.assertEqual(str(c), '[3 x i32] [i32 5, i32 6, i32 4]') + c = ir.Constant(ir.ArrayType(int32, 2), (c32(5), c32(ir.Undefined))) + self.assertEqual(str(c), '[2 x i32] [i32 5, i32 undef]') + + c = ir.Constant.literal_array((c32(5), c32(6), c32(ir.Undefined))) + self.assertEqual(str(c), '[3 x i32] [i32 5, i32 6, i32 undef]') + with self.assertRaises(TypeError) as raises: + ir.Constant.literal_array((c32(5), ir.Constant(flt, 1.5))) + self.assertEqual(str(raises.exception), + "all elements must have the same type") + + c = ir.Constant(ir.ArrayType(int32, 2), ir.Undefined) + self.assertEqual(str(c), '[2 x i32] undef') + c = ir.Constant(ir.ArrayType(int32, 2), None) + self.assertEqual(str(c), '[2 x i32] zeroinitializer') + # Raw array syntax + c = ir.Constant(ir.ArrayType(int8, 11), bytearray(b"foobar_123\x80")) + self.assertEqual(str(c), r'[11 x i8] c"foobar_123\80"') + c = ir.Constant(ir.ArrayType(int8, 4), bytearray(b"\x00\x01\x04\xff")) + self.assertEqual(str(c), r'[4 x i8] c"\00\01\04\ff"') + # Recursive instantiation of inner constants + c = ir.Constant(ir.ArrayType(int32, 3), (5, ir.Undefined, 6)) + self.assertEqual(str(c), '[3 x i32] [i32 5, i32 undef, i32 6]') + # Invalid number of args + with self.assertRaises(ValueError): + ir.Constant(ir.ArrayType(int32, 3), (5, 6)) + + def test_vector(self): + vecty = ir.VectorType(ir.IntType(32), 8) + vals = [1, 2, 4, 3, 8, 6, 9, 7] + vec = ir.Constant(vecty, vals) + vec_repr = "<8 x i32> <{}>".format( + ', '.join(map('i32 {}'.format, vals))) + self.assertEqual(str(vec), vec_repr) + + def test_non_nullable_int(self): + constant = ir.Constant(ir.IntType(32), None).constant + self.assertEqual(constant, 0) + + def test_structs(self): + st1 = ir.LiteralStructType((flt, int1)) + st2 = ir.LiteralStructType((int32, st1)) + c = ir.Constant(st1, (ir.Constant(ir.FloatType(), 1.5), + ir.Constant(int1, True))) + self.assertEqual(str(c), + '{float, i1} {float 0x3ff8000000000000, i1 true}') + c = ir.Constant.literal_struct((ir.Constant(ir.FloatType(), 1.5), + ir.Constant(int1, True))) + self.assertEqual(c.type, st1) + self.assertEqual(str(c), + '{float, i1} {float 0x3ff8000000000000, i1 true}') + c = ir.Constant.literal_struct((ir.Constant(ir.FloatType(), 1.5), + ir.Constant(int1, ir.Undefined))) + self.assertEqual(c.type, st1) + self.assertEqual(str(c), + '{float, i1} {float 0x3ff8000000000000, i1 undef}') + c = ir.Constant(st1, ir.Undefined) + self.assertEqual(str(c), '{float, i1} undef') + c = ir.Constant(st1, None) + self.assertEqual(str(c), '{float, i1} zeroinitializer') + # Recursive instantiation of inner constants + c1 = ir.Constant(st1, (1.5, True)) + self.assertEqual(str(c1), + '{float, i1} {float 0x3ff8000000000000, i1 true}') + c2 = ir.Constant(st2, (42, c1)) + self.assertEqual(str(c2), ('{i32, {float, i1}} {i32 42, {float, i1} ' + '{float 0x3ff8000000000000, i1 true}}')) + c3 = ir.Constant(st2, (42, (1.5, True))) + self.assertEqual(str(c3), str(c2)) + # Invalid number of args + with self.assertRaises(ValueError): + ir.Constant(st2, (4, 5, 6)) + + def test_undefined_literal_struct_pickling(self): + i8 = ir.IntType(8) + st = ir.Constant(ir.LiteralStructType([i8, i8]), ir.Undefined) + self.assert_pickle_correctly(st) + + def test_type_instantiaton(self): + """ + Instantiating a type should create a constant. + """ + c = int8(42) + self.assertIsInstance(c, ir.Constant) + self.assertEqual(str(c), 'i8 42') + c = int1(True) + self.assertIsInstance(c, ir.Constant) + self.assertEqual(str(c), 'i1 true') + # Arrays + at = ir.ArrayType(int32, 3) + c = at([c32(4), c32(5), c32(6)]) + self.assertEqual(str(c), '[3 x i32] [i32 4, i32 5, i32 6]') + c = at([4, 5, 6]) + self.assertEqual(str(c), '[3 x i32] [i32 4, i32 5, i32 6]') + c = at(None) + self.assertEqual(str(c), '[3 x i32] zeroinitializer') + with self.assertRaises(ValueError): + at([4, 5, 6, 7]) + # Structs + st1 = ir.LiteralStructType((flt, int1)) + st2 = ir.LiteralStructType((int32, st1)) + c = st1((1.5, True)) + self.assertEqual(str(c), ('{float, i1} {float 0x3ff8000000000000, i1 ' + 'true}')) + c = st2((42, (1.5, True))) + self.assertEqual(str(c), ('{i32, {float, i1}} {i32 42, {float, i1} ' + '{float 0x3ff8000000000000, i1 true}}')) + + def test_repr(self): + """ + Constants should have a useful repr(). + """ + c = int32(42) + self.assertEqual(repr(c), "") + + def test_encoding_problem(self): + c = ir.Constant(ir.ArrayType(ir.IntType(8), 256), + bytearray(range(256))) + m = self.module() + gv = ir.GlobalVariable(m, c.type, "myconstant") + gv.global_constant = True + gv.initializer = c + # With utf-8, the following will cause: + # UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position + # 136: invalid continuation byte + parsed = llvm.parse_assembly(str(m)) + # Make sure the encoding does not modify the IR + reparsed = llvm.parse_assembly(str(parsed)) + self.assertEqual(str(parsed), str(reparsed)) + + def test_gep(self): + m = self.module() + tp = ir.LiteralStructType((flt, int1)) + gv = ir.GlobalVariable(m, tp, "myconstant") + c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) + self.assertEqual(str(c), + 'getelementptr ({float, i1}, {float, i1}* @"myconstant", i32 0, i32 1)') # noqa E501 + self.assertEqual(c.type, ir.PointerType(int1)) + + const = ir.Constant(tp, None) + with self.assertRaises(TypeError): + const.gep([ir.Constant(int32, 0)]) + + const_ptr = ir.Constant(tp.as_pointer(), None) + c2 = const_ptr.gep([ir.Constant(int32, 0)]) + self.assertEqual(str(c2), + 'getelementptr ({float, i1}, {float, i1}* null, i32 0)') # noqa E501 + self.assertEqual(c.type, ir.PointerType(int1)) + + def test_gep_addrspace_globalvar(self): + m = self.module() + tp = ir.LiteralStructType((flt, int1)) + addrspace = 4 + + gv = ir.GlobalVariable(m, tp, "myconstant", addrspace=addrspace) + self.assertEqual(gv.addrspace, addrspace) + c = gv.gep([ir.Constant(int32, x) for x in (0, 1)]) + self.assertEqual(c.type.addrspace, addrspace) + self.assertEqual(str(c), + ('getelementptr ({float, i1}, {float, i1} ' + 'addrspace(4)* @"myconstant", i32 0, i32 1)')) + self.assertEqual(c.type, ir.PointerType(int1, addrspace=addrspace)) + + def test_trunc(self): + c = ir.Constant(int64, 1).trunc(int32) + self.assertEqual(str(c), 'trunc (i64 1 to i32)') + + def test_zext(self): + c = ir.Constant(int32, 1).zext(int64) + self.assertEqual(str(c), 'zext (i32 1 to i64)') + + def test_sext(self): + c = ir.Constant(int32, -1).sext(int64) + self.assertEqual(str(c), 'sext (i32 -1 to i64)') + + def test_fptrunc(self): + c = ir.Constant(flt, 1).fptrunc(hlf) + self.assertEqual(str(c), 'fptrunc (float 0x3ff0000000000000 to half)') + + def test_fpext(self): + c = ir.Constant(flt, 1).fpext(dbl) + self.assertEqual(str(c), 'fpext (float 0x3ff0000000000000 to double)') + + def test_bitcast(self): + m = self.module() + gv = ir.GlobalVariable(m, int32, "myconstant") + c = gv.bitcast(int64.as_pointer()) + self.assertEqual(str(c), 'bitcast (i32* @"myconstant" to i64*)') + + def test_fptoui(self): + c = ir.Constant(flt, 1).fptoui(int32) + self.assertEqual(str(c), 'fptoui (float 0x3ff0000000000000 to i32)') + + def test_uitofp(self): + c = ir.Constant(int32, 1).uitofp(flt) + self.assertEqual(str(c), 'uitofp (i32 1 to float)') + + def test_fptosi(self): + c = ir.Constant(flt, 1).fptosi(int32) + self.assertEqual(str(c), 'fptosi (float 0x3ff0000000000000 to i32)') + + def test_sitofp(self): + c = ir.Constant(int32, 1).sitofp(flt) + self.assertEqual(str(c), 'sitofp (i32 1 to float)') + + def test_ptrtoint_1(self): + ptr = ir.Constant(int64.as_pointer(), None) + one = ir.Constant(int32, 1) + c = ptr.ptrtoint(int32) + + self.assertRaises(TypeError, one.ptrtoint, int64) + self.assertRaises(TypeError, ptr.ptrtoint, flt) + self.assertEqual(str(c), 'ptrtoint (i64* null to i32)') + + def test_ptrtoint_2(self): + m = self.module() + gv = ir.GlobalVariable(m, int32, "myconstant") + c = gv.ptrtoint(int64) + self.assertEqual(str(c), 'ptrtoint (i32* @"myconstant" to i64)') + + self.assertRaisesRegex( + TypeError, + r"can only ptrtoint\(\) to integer type, not 'i64\*'", + gv.ptrtoint, + int64.as_pointer()) + + c2 = ir.Constant(int32, 0) + self.assertRaisesRegex( + TypeError, + r"can only call ptrtoint\(\) on pointer type, not 'i32'", + c2.ptrtoint, + int64) + + def test_inttoptr(self): + one = ir.Constant(int32, 1) + pi = ir.Constant(flt, 3.14) + c = one.inttoptr(int64.as_pointer()) + + self.assertRaises(TypeError, one.inttoptr, int64) + self.assertRaises(TypeError, pi.inttoptr, int64.as_pointer()) + self.assertEqual(str(c), 'inttoptr (i32 1 to i64*)') + + def test_neg(self): + one = ir.Constant(int32, 1) + self.assertEqual(str(one.neg()), 'sub (i32 0, i32 1)') + + def test_not(self): + one = ir.Constant(int32, 1) + self.assertEqual(str(one.not_()), 'xor (i32 1, i32 -1)') + + def test_fneg(self): + one = ir.Constant(flt, 1) + self.assertEqual(str(one.fneg()), 'fneg (float 0x3ff0000000000000)') + + def test_int_binops(self): + one = ir.Constant(int32, 1) + two = ir.Constant(int32, 2) + + oracle = {one.shl: 'shl', one.lshr: 'lshr', one.ashr: 'ashr', + one.add: 'add', one.sub: 'sub', one.mul: 'mul', + one.udiv: 'udiv', one.sdiv: 'sdiv', one.urem: 'urem', + one.srem: 'srem', one.or_: 'or', one.and_: 'and', + one.xor: 'xor'} + for fn, irop in oracle.items(): + self.assertEqual(str(fn(two)), irop + ' (i32 1, i32 2)') + + # unsigned integer compare + oracle = {'==': 'eq', '!=': 'ne', '>': + 'ugt', '>=': 'uge', '<': 'ult', '<=': 'ule'} + for cop, cond in oracle.items(): + actual = str(one.icmp_unsigned(cop, two)) + expected = 'icmp ' + cond + ' (i32 1, i32 2)' + self.assertEqual(actual, expected) + + # signed integer compare + oracle = {'==': 'eq', '!=': 'ne', + '>': 'sgt', '>=': 'sge', '<': 'slt', '<=': 'sle'} + for cop, cond in oracle.items(): + actual = str(one.icmp_signed(cop, two)) + expected = 'icmp ' + cond + ' (i32 1, i32 2)' + self.assertEqual(actual, expected) + + def test_flt_binops(self): + one = ir.Constant(flt, 1) + two = ir.Constant(flt, 2) + + oracle = {one.fadd: 'fadd', one.fsub: 'fsub', one.fmul: 'fmul', + one.fdiv: 'fdiv', one.frem: 'frem'} + for fn, irop in oracle.items(): + actual = str(fn(two)) + expected = irop + (' (float 0x3ff0000000000000,' + ' float 0x4000000000000000)') + self.assertEqual(actual, expected) + + # ordered float compare + oracle = {'==': 'oeq', '!=': 'one', '>': 'ogt', '>=': 'oge', + '<': 'olt', '<=': 'ole'} + for cop, cond in oracle.items(): + actual = str(one.fcmp_ordered(cop, two)) + expected = 'fcmp ' + cond + (' (float 0x3ff0000000000000,' + ' float 0x4000000000000000)') + self.assertEqual(actual, expected) + + # unordered float compare + oracle = {'==': 'ueq', '!=': 'une', '>': 'ugt', '>=': 'uge', + '<': 'ult', '<=': 'ule'} + for cop, cond in oracle.items(): + actual = str(one.fcmp_unordered(cop, two)) + expected = 'fcmp ' + cond + (' (float 0x3ff0000000000000,' + ' float 0x4000000000000000)') + self.assertEqual(actual, expected) + + +class TestTransforms(TestBase): + def test_call_transform(self): + mod = ir.Module() + foo = ir.Function(mod, ir.FunctionType(ir.VoidType(), ()), "foo") + bar = ir.Function(mod, ir.FunctionType(ir.VoidType(), ()), "bar") + builder = ir.IRBuilder() + builder.position_at_end(foo.append_basic_block()) + call = builder.call(foo, ()) + self.assertEqual(call.callee, foo) + modified = ir.replace_all_calls(mod, foo, bar) + self.assertIn(call, modified) + self.assertNotEqual(call.callee, foo) + self.assertEqual(call.callee, bar) + + +class TestSingleton(TestBase): + def test_undefined(self): + self.assertIs(ir.Undefined, ir.values._Undefined()) + self.assertIs(ir.Undefined, copy.copy(ir.Undefined)) + self.assertIs(ir.Undefined, copy.deepcopy(ir.Undefined)) + self.assert_pickle_correctly(ir.Undefined) + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/python3.11/site-packages/llvmlite/tests/test_refprune.py b/lib/python3.11/site-packages/llvmlite/tests/test_refprune.py new file mode 100644 index 0000000000000000000000000000000000000000..f2948d03fbcbc64a100b0544457b7c1063758f84 --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/test_refprune.py @@ -0,0 +1,526 @@ +import unittest +from llvmlite import ir +from llvmlite import binding as llvm +from llvmlite.tests import TestCase + +from . import refprune_proto as proto + + +def _iterate_cases(generate_test): + def wrap(fn): + def wrapped(self): + return generate_test(self, fn) + wrapped.__doc__ = f"generated test for {fn.__module__}.{fn.__name__}" + return wrapped + + for k, case_fn in proto.__dict__.items(): + if k.startswith('case'): + yield f'test_{k}', wrap(case_fn) + + +class TestRefPrunePrototype(TestCase): + """ + Test that the prototype is working. + """ + def generate_test(self, case_gen): + nodes, edges, expected = case_gen() + got = proto.FanoutAlgorithm(nodes, edges).run() + self.assertEqual(expected, got) + + # Generate tests + for name, case in _iterate_cases(generate_test): + locals()[name] = case + + +ptr_ty = ir.IntType(8).as_pointer() + + +class TestRefPrunePass(TestCase): + """ + Test that the C++ implementation matches the expected behavior as for + the prototype. + + This generates a LLVM module for each test case, runs the pruner and checks + that the expected results are achieved. + """ + + def make_incref(self, m): + fnty = ir.FunctionType(ir.VoidType(), [ptr_ty]) + return ir.Function(m, fnty, name='NRT_incref') + + def make_decref(self, m): + fnty = ir.FunctionType(ir.VoidType(), [ptr_ty]) + return ir.Function(m, fnty, name='NRT_decref') + + def make_switcher(self, m): + fnty = ir.FunctionType(ir.IntType(32), ()) + return ir.Function(m, fnty, name='switcher') + + def make_brancher(self, m): + fnty = ir.FunctionType(ir.IntType(1), ()) + return ir.Function(m, fnty, name='brancher') + + def generate_ir(self, nodes, edges): + # Build LLVM module for the CFG + m = ir.Module() + + incref_fn = self.make_incref(m) + decref_fn = self.make_decref(m) + switcher_fn = self.make_switcher(m) + brancher_fn = self.make_brancher(m) + + fnty = ir.FunctionType(ir.VoidType(), [ptr_ty]) + fn = ir.Function(m, fnty, name='main') + [ptr] = fn.args + ptr.name = 'mem' + # populate the BB nodes + bbmap = {} + for bb in edges: + bbmap[bb] = fn.append_basic_block(bb) + # populate the BB + builder = ir.IRBuilder() + for bb, jump_targets in edges.items(): + builder.position_at_end(bbmap[bb]) + # Insert increfs and decrefs + for action in nodes[bb]: + if action == 'incref': + builder.call(incref_fn, [ptr]) + elif action == 'decref': + builder.call(decref_fn, [ptr]) + else: + raise AssertionError('unreachable') + + # Insert the terminator. + # Switch base on the number of jump targets. + n_targets = len(jump_targets) + if n_targets == 0: + builder.ret_void() + elif n_targets == 1: + [dst] = jump_targets + builder.branch(bbmap[dst]) + elif n_targets == 2: + [left, right] = jump_targets + sel = builder.call(brancher_fn, ()) + builder.cbranch(sel, bbmap[left], bbmap[right]) + elif n_targets > 2: + sel = builder.call(switcher_fn, ()) + [head, *tail] = jump_targets + + sw = builder.switch(sel, default=bbmap[head]) + for i, dst in enumerate(tail): + sw.add_case(sel.type(i), bbmap[dst]) + else: + raise AssertionError('unreachable') + + return m + + def apply_refprune(self, irmod): + mod = llvm.parse_assembly(str(irmod)) + pm = llvm.ModulePassManager() + pm.add_refprune_pass() + pm.run(mod) + return mod + + def check(self, mod, expected, nodes): + # preprocess incref/decref locations + d = {} + for k, vs in nodes.items(): + n_incref = vs.count('incref') + n_decref = vs.count('decref') + d[k] = {'incref': n_incref, 'decref': n_decref} + for k, stats in d.items(): + if expected.get(k): + stats['incref'] -= 1 + for dec_bb in expected[k]: + d[dec_bb]['decref'] -= 1 + + # find the main function + for f in mod.functions: + if f.name == 'main': + break + # check each BB + for bb in f.blocks: + stats = d[bb.name] + text = str(bb) + n_incref = text.count('NRT_incref') + n_decref = text.count('NRT_decref') + self.assertEqual(stats['incref'], n_incref, msg=f'BB {bb}') + self.assertEqual(stats['decref'], n_decref, msg=f'BB {bb}') + + def generate_test(self, case_gen): + nodes, edges, expected = case_gen() + irmod = self.generate_ir(nodes, edges) + outmod = self.apply_refprune(irmod) + self.check(outmod, expected, nodes) + + # Generate tests + for name, case in _iterate_cases(generate_test): + locals()[name] = case + + +class BaseTestByIR(TestCase): + refprune_bitmask = 0 + + prologue = r""" +declare void @NRT_incref(i8* %ptr) +declare void @NRT_decref(i8* %ptr) +""" + + def check(self, irmod, subgraph_limit=None): + mod = llvm.parse_assembly(f"{self.prologue}\n{irmod}") + pm = llvm.ModulePassManager() + if subgraph_limit is None: + pm.add_refprune_pass(self.refprune_bitmask) + else: + pm.add_refprune_pass(self.refprune_bitmask, + subgraph_limit=subgraph_limit) + before = llvm.dump_refprune_stats() + pm.run(mod) + after = llvm.dump_refprune_stats() + return mod, after - before + + +class TestPerBB(BaseTestByIR): + refprune_bitmask = llvm.RefPruneSubpasses.PER_BB + + per_bb_ir_1 = r""" +define void @main(i8* %ptr) { + call void @NRT_incref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_bb_1(self): + mod, stats = self.check(self.per_bb_ir_1) + self.assertEqual(stats.basicblock, 2) + + per_bb_ir_2 = r""" +define void @main(i8* %ptr) { + call void @NRT_incref(i8* %ptr) + call void @NRT_incref(i8* %ptr) + call void @NRT_incref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_bb_2(self): + mod, stats = self.check(self.per_bb_ir_2) + self.assertEqual(stats.basicblock, 4) + # not pruned + self.assertIn("call void @NRT_incref(i8* %ptr)", str(mod)) + + per_bb_ir_3 = r""" +define void @main(i8* %ptr, i8* %other) { + call void @NRT_incref(i8* %ptr) + call void @NRT_incref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %other) + ret void +} +""" + + def test_per_bb_3(self): + mod, stats = self.check(self.per_bb_ir_3) + self.assertEqual(stats.basicblock, 2) + # not pruned + self.assertIn("call void @NRT_decref(i8* %other)", str(mod)) + + per_bb_ir_4 = r""" +; reordered +define void @main(i8* %ptr, i8* %other) { + call void @NRT_incref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %other) + call void @NRT_incref(i8* %ptr) + ret void +} +""" + + def test_per_bb_4(self): + mod, stats = self.check(self.per_bb_ir_4) + self.assertEqual(stats.basicblock, 4) + # not pruned + self.assertIn("call void @NRT_decref(i8* %other)", str(mod)) + + +class TestDiamond(BaseTestByIR): + refprune_bitmask = llvm.RefPruneSubpasses.DIAMOND + + per_diamond_1 = r""" +define void @main(i8* %ptr) { +bb_A: + call void @NRT_incref(i8* %ptr) + br label %bb_B +bb_B: + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_diamond_1(self): + mod, stats = self.check(self.per_diamond_1) + self.assertEqual(stats.diamond, 2) + + per_diamond_2 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + br label %bb_D +bb_C: + br label %bb_D +bb_D: + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_diamond_2(self): + mod, stats = self.check(self.per_diamond_2) + self.assertEqual(stats.diamond, 2) + + per_diamond_3 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + br label %bb_D +bb_C: + call void @NRT_decref(i8* %ptr) ; reject because of decref in diamond + br label %bb_D +bb_D: + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_diamond_3(self): + mod, stats = self.check(self.per_diamond_3) + self.assertEqual(stats.diamond, 0) + + per_diamond_4 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_incref(i8* %ptr) ; extra incref will not affect prune + br label %bb_D +bb_C: + br label %bb_D +bb_D: + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_diamond_4(self): + mod, stats = self.check(self.per_diamond_4) + self.assertEqual(stats.diamond, 2) + + per_diamond_5 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + br label %bb_D +bb_C: + br label %bb_D +bb_D: + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_per_diamond_5(self): + mod, stats = self.check(self.per_diamond_5) + self.assertEqual(stats.diamond, 4) + + +class TestFanout(BaseTestByIR): + """More complex cases are tested in TestRefPrunePass + """ + + refprune_bitmask = llvm.RefPruneSubpasses.FANOUT + + fanout_1 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + ret void +bb_C: + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_fanout_1(self): + mod, stats = self.check(self.fanout_1) + self.assertEqual(stats.fanout, 3) + + fanout_2 = r""" +define void @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + ret void +bb_C: + call void @NRT_decref(i8* %ptr) + br label %bb_B ; illegal jump to other decref +} +""" + + def test_fanout_2(self): + mod, stats = self.check(self.fanout_2) + self.assertEqual(stats.fanout, 0) + + fanout_3 = r""" +define void @main(i8* %ptr, i1 %cond) { +bb_A: + call void @NRT_incref(i8* %ptr) + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + ret void +bb_C: + call void @NRT_decref(i8* %ptr) + call void @NRT_decref(i8* %ptr) + ret void +} +""" + + def test_fanout_3(self): + mod, stats = self.check(self.fanout_3) + self.assertEqual(stats.fanout, 6) + + def test_fanout_3_limited(self): + # With subgraph limit at 1, it is essentially turning off the fanout + # pruner. + mod, stats = self.check(self.fanout_3, subgraph_limit=1) + self.assertEqual(stats.fanout, 0) + + +class TestFanoutRaise(BaseTestByIR): + refprune_bitmask = llvm.RefPruneSubpasses.FANOUT_RAISE + + fanout_raise_1 = r""" +define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + ret i32 0 +bb_C: + store i8* null, i8** %excinfo, !numba_exception_output !0 + ret i32 1 +} +!0 = !{i1 true} +""" + + def test_fanout_raise_1(self): + mod, stats = self.check(self.fanout_raise_1) + self.assertEqual(stats.fanout_raise, 2) + + fanout_raise_2 = r""" +define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + ret i32 0 +bb_C: + store i8* null, i8** %excinfo, !numba_exception_typo !0 ; bad metadata + ret i32 1 +} + +!0 = !{i1 true} +""" + + def test_fanout_raise_2(self): + # This is ensuring that fanout_raise is not pruning when the metadata + # is incorrectly named. + mod, stats = self.check(self.fanout_raise_2) + self.assertEqual(stats.fanout_raise, 0) + + fanout_raise_3 = r""" +define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + ret i32 0 +bb_C: + store i8* null, i8** %excinfo, !numba_exception_output !0 + ret i32 1 +} + +!0 = !{i32 1} ; ok; use i32 +""" + + def test_fanout_raise_3(self): + mod, stats = self.check(self.fanout_raise_3) + self.assertEqual(stats.fanout_raise, 2) + + fanout_raise_4 = r""" +define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + ret i32 1 ; BAD; all tails are raising without decref +bb_C: + ret i32 1 ; BAD; all tails are raising without decref +} + +!0 = !{i1 1} +""" + + def test_fanout_raise_4(self): + mod, stats = self.check(self.fanout_raise_4) + self.assertEqual(stats.fanout_raise, 0) + + fanout_raise_5 = r""" +define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) { +bb_A: + call void @NRT_incref(i8* %ptr) + br i1 %cond, label %bb_B, label %bb_C +bb_B: + call void @NRT_decref(i8* %ptr) + br label %common.ret +bb_C: + store i8* null, i8** %excinfo, !numba_exception_output !0 + br label %common.ret +common.ret: + %common.ret.op = phi i32 [ 0, %bb_B ], [ 1, %bb_C ] + ret i32 %common.ret.op +} +!0 = !{i1 1} +""" + + def test_fanout_raise_5(self): + mod, stats = self.check(self.fanout_raise_5) + self.assertEqual(stats.fanout_raise, 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/lib/python3.11/site-packages/llvmlite/tests/test_valuerepr.py b/lib/python3.11/site-packages/llvmlite/tests/test_valuerepr.py new file mode 100644 index 0000000000000000000000000000000000000000..f8d7e4b2c073ecdfd5ae8c985ebd9108245bd78f --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/tests/test_valuerepr.py @@ -0,0 +1,60 @@ +import math +import sys +import unittest + +from llvmlite.ir import ( + Constant, FloatType, DoubleType, LiteralStructType, IntType, + ArrayType, HalfType) +from llvmlite.tests import TestCase + + +int8 = IntType(8) +int16 = IntType(16) + + +PY36_OR_LATER = sys.version_info[:2] >= (3, 6) + + +class TestValueRepr(TestCase): + + def test_double_repr(self): + def check_repr(val, expected): + c = Constant(DoubleType(), val) + self.assertEqual(str(c), expected) + check_repr(math.pi, "double 0x400921fb54442d18") + check_repr(float('inf'), "double 0x7ff0000000000000") + check_repr(float('-inf'), "double 0xfff0000000000000") + + def test_float_repr(self): + def check_repr(val, expected): + c = Constant(FloatType(), val) + self.assertEqual(str(c), expected) + check_repr(math.pi, "float 0x400921fb60000000") + check_repr(float('inf'), "float 0x7ff0000000000000") + check_repr(float('-inf'), "float 0xfff0000000000000") + + @unittest.skipUnless(PY36_OR_LATER, 'py36+ only') + def test_half_repr(self): + def check_repr(val, expected): + c = Constant(HalfType(), val) + self.assertEqual(str(c), expected) + check_repr(math.pi, "half 0x4009200000000000") + check_repr(float('inf'), "half 0x7ff0000000000000") + check_repr(float('-inf'), "half 0xfff0000000000000") + + def test_struct_repr(self): + tp = LiteralStructType([int8, int16]) + c = Constant(tp, (Constant(int8, 100), Constant(int16, 1000))) + self.assertEqual(str(c), "{i8, i16} {i8 100, i16 1000}") + + def test_array_repr(self): + tp = ArrayType(int8, 3) + values = [Constant(int8, x) for x in (5, 10, -15)] + c = Constant(tp, values) + self.assertEqual(str(c), "[3 x i8] [i8 5, i8 10, i8 -15]") + c = Constant(tp, bytearray(b"\x01\x02\x03")) + self.assertEqual(str(c), '[3 x i8] c"\\01\\02\\03"') + + +if __name__ == "__main__": + unittest.main() diff --git a/lib/python3.11/site-packages/llvmlite/utils.py b/lib/python3.11/site-packages/llvmlite/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..e07ecd370f45b3af0fe67f9a0ac6ea1cee16db3f --- /dev/null +++ b/lib/python3.11/site-packages/llvmlite/utils.py @@ -0,0 +1,29 @@ +import os +import sys + + +# This module must be importable without loading the binding, to avoid +# bootstrapping issues in setup.py. + +def get_library_name(): + """ + Return the name of the llvmlite shared library file. + """ + if os.name == 'posix': + if sys.platform == 'darwin': + return 'libllvmlite.dylib' + else: + return 'libllvmlite.so' + else: + assert os.name == 'nt' + return 'llvmlite.dll' + + +def get_library_files(): + """ + Return the names of shared library files needed for this platform. + """ + files = [get_library_name()] + if os.name == 'nt': + files.extend(['msvcr120.dll', 'msvcp120.dll']) + return files diff --git a/lib/python3.11/site-packages/markupsafe/__init__.py b/lib/python3.11/site-packages/markupsafe/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..21d31960385611ad029826a36417fe50a17ca557 --- /dev/null +++ b/lib/python3.11/site-packages/markupsafe/__init__.py @@ -0,0 +1,304 @@ +import functools +import re +import string +import sys +import typing as t + +if t.TYPE_CHECKING: + import typing_extensions as te + + class HasHTML(te.Protocol): + def __html__(self) -> str: + pass + + _P = te.ParamSpec("_P") + + +__version__ = "2.1.3" + +_strip_comments_re = re.compile(r"", re.DOTALL) +_strip_tags_re = re.compile(r"<.*?>", re.DOTALL) + + +def _simple_escaping_wrapper(func: "t.Callable[_P, str]") -> "t.Callable[_P, Markup]": + @functools.wraps(func) + def wrapped(self: "Markup", *args: "_P.args", **kwargs: "_P.kwargs") -> "Markup": + arg_list = _escape_argspec(list(args), enumerate(args), self.escape) + _escape_argspec(kwargs, kwargs.items(), self.escape) + return self.__class__(func(self, *arg_list, **kwargs)) # type: ignore[arg-type] + + return wrapped # type: ignore[return-value] + + +class Markup(str): + """A string that is ready to be safely inserted into an HTML or XML + document, either because it was escaped or because it was marked + safe. + + Passing an object to the constructor converts it to text and wraps + it to mark it safe without escaping. To escape the text, use the + :meth:`escape` class method instead. + + >>> Markup("Hello, World!") + Markup('Hello, World!') + >>> Markup(42) + Markup('42') + >>> Markup.escape("Hello, World!") + Markup('Hello <em>World</em>!') + + This implements the ``__html__()`` interface that some frameworks + use. Passing an object that implements ``__html__()`` will wrap the + output of that method, marking it safe. + + >>> class Foo: + ... def __html__(self): + ... return 'foo' + ... + >>> Markup(Foo()) + Markup('foo') + + This is a subclass of :class:`str`. It has the same methods, but + escapes their arguments and returns a ``Markup`` instance. + + >>> Markup("%s") % ("foo & bar",) + Markup('foo & bar') + >>> Markup("Hello ") + "" + Markup('Hello <foo>') + """ + + __slots__ = () + + def __new__( + cls, base: t.Any = "", encoding: t.Optional[str] = None, errors: str = "strict" + ) -> "te.Self": + if hasattr(base, "__html__"): + base = base.__html__() + + if encoding is None: + return super().__new__(cls, base) + + return super().__new__(cls, base, encoding, errors) + + def __html__(self) -> "te.Self": + return self + + def __add__(self, other: t.Union[str, "HasHTML"]) -> "te.Self": + if isinstance(other, str) or hasattr(other, "__html__"): + return self.__class__(super().__add__(self.escape(other))) + + return NotImplemented + + def __radd__(self, other: t.Union[str, "HasHTML"]) -> "te.Self": + if isinstance(other, str) or hasattr(other, "__html__"): + return self.escape(other).__add__(self) + + return NotImplemented + + def __mul__(self, num: "te.SupportsIndex") -> "te.Self": + if isinstance(num, int): + return self.__class__(super().__mul__(num)) + + return NotImplemented + + __rmul__ = __mul__ + + def __mod__(self, arg: t.Any) -> "te.Self": + if isinstance(arg, tuple): + # a tuple of arguments, each wrapped + arg = tuple(_MarkupEscapeHelper(x, self.escape) for x in arg) + elif hasattr(type(arg), "__getitem__") and not isinstance(arg, str): + # a mapping of arguments, wrapped + arg = _MarkupEscapeHelper(arg, self.escape) + else: + # a single argument, wrapped with the helper and a tuple + arg = (_MarkupEscapeHelper(arg, self.escape),) + + return self.__class__(super().__mod__(arg)) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({super().__repr__()})" + + def join(self, seq: t.Iterable[t.Union[str, "HasHTML"]]) -> "te.Self": + return self.__class__(super().join(map(self.escape, seq))) + + join.__doc__ = str.join.__doc__ + + def split( # type: ignore[override] + self, sep: t.Optional[str] = None, maxsplit: int = -1 + ) -> t.List["te.Self"]: + return [self.__class__(v) for v in super().split(sep, maxsplit)] + + split.__doc__ = str.split.__doc__ + + def rsplit( # type: ignore[override] + self, sep: t.Optional[str] = None, maxsplit: int = -1 + ) -> t.List["te.Self"]: + return [self.__class__(v) for v in super().rsplit(sep, maxsplit)] + + rsplit.__doc__ = str.rsplit.__doc__ + + def splitlines( # type: ignore[override] + self, keepends: bool = False + ) -> t.List["te.Self"]: + return [self.__class__(v) for v in super().splitlines(keepends)] + + splitlines.__doc__ = str.splitlines.__doc__ + + def unescape(self) -> str: + """Convert escaped markup back into a text string. This replaces + HTML entities with the characters they represent. + + >>> Markup("Main » About").unescape() + 'Main » About' + """ + from html import unescape + + return unescape(str(self)) + + def striptags(self) -> str: + """:meth:`unescape` the markup, remove tags, and normalize + whitespace to single spaces. + + >>> Markup("Main »\tAbout").striptags() + 'Main » About' + """ + # Use two regexes to avoid ambiguous matches. + value = _strip_comments_re.sub("", self) + value = _strip_tags_re.sub("", value) + value = " ".join(value.split()) + return self.__class__(value).unescape() + + @classmethod + def escape(cls, s: t.Any) -> "te.Self": + """Escape a string. Calls :func:`escape` and ensures that for + subclasses the correct type is returned. + """ + rv = escape(s) + + if rv.__class__ is not cls: + return cls(rv) + + return rv # type: ignore[return-value] + + __getitem__ = _simple_escaping_wrapper(str.__getitem__) + capitalize = _simple_escaping_wrapper(str.capitalize) + title = _simple_escaping_wrapper(str.title) + lower = _simple_escaping_wrapper(str.lower) + upper = _simple_escaping_wrapper(str.upper) + replace = _simple_escaping_wrapper(str.replace) + ljust = _simple_escaping_wrapper(str.ljust) + rjust = _simple_escaping_wrapper(str.rjust) + lstrip = _simple_escaping_wrapper(str.lstrip) + rstrip = _simple_escaping_wrapper(str.rstrip) + center = _simple_escaping_wrapper(str.center) + strip = _simple_escaping_wrapper(str.strip) + translate = _simple_escaping_wrapper(str.translate) + expandtabs = _simple_escaping_wrapper(str.expandtabs) + swapcase = _simple_escaping_wrapper(str.swapcase) + zfill = _simple_escaping_wrapper(str.zfill) + casefold = _simple_escaping_wrapper(str.casefold) + + if sys.version_info >= (3, 9): + removeprefix = _simple_escaping_wrapper(str.removeprefix) + removesuffix = _simple_escaping_wrapper(str.removesuffix) + + def partition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]: + l, s, r = super().partition(self.escape(sep)) + cls = self.__class__ + return cls(l), cls(s), cls(r) + + def rpartition(self, sep: str) -> t.Tuple["te.Self", "te.Self", "te.Self"]: + l, s, r = super().rpartition(self.escape(sep)) + cls = self.__class__ + return cls(l), cls(s), cls(r) + + def format(self, *args: t.Any, **kwargs: t.Any) -> "te.Self": + formatter = EscapeFormatter(self.escape) + return self.__class__(formatter.vformat(self, args, kwargs)) + + def format_map( # type: ignore[override] + self, map: t.Mapping[str, t.Any] + ) -> "te.Self": + formatter = EscapeFormatter(self.escape) + return self.__class__(formatter.vformat(self, (), map)) + + def __html_format__(self, format_spec: str) -> "te.Self": + if format_spec: + raise ValueError("Unsupported format specification for Markup.") + + return self + + +class EscapeFormatter(string.Formatter): + __slots__ = ("escape",) + + def __init__(self, escape: t.Callable[[t.Any], Markup]) -> None: + self.escape = escape + super().__init__() + + def format_field(self, value: t.Any, format_spec: str) -> str: + if hasattr(value, "__html_format__"): + rv = value.__html_format__(format_spec) + elif hasattr(value, "__html__"): + if format_spec: + raise ValueError( + f"Format specifier {format_spec} given, but {type(value)} does not" + " define __html_format__. A class that defines __html__ must define" + " __html_format__ to work with format specifiers." + ) + rv = value.__html__() + else: + # We need to make sure the format spec is str here as + # otherwise the wrong callback methods are invoked. + rv = string.Formatter.format_field(self, value, str(format_spec)) + return str(self.escape(rv)) + + +_ListOrDict = t.TypeVar("_ListOrDict", list, dict) + + +def _escape_argspec( + obj: _ListOrDict, iterable: t.Iterable[t.Any], escape: t.Callable[[t.Any], Markup] +) -> _ListOrDict: + """Helper for various string-wrapped functions.""" + for key, value in iterable: + if isinstance(value, str) or hasattr(value, "__html__"): + obj[key] = escape(value) + + return obj + + +class _MarkupEscapeHelper: + """Helper for :meth:`Markup.__mod__`.""" + + __slots__ = ("obj", "escape") + + def __init__(self, obj: t.Any, escape: t.Callable[[t.Any], Markup]) -> None: + self.obj = obj + self.escape = escape + + def __getitem__(self, item: t.Any) -> "te.Self": + return self.__class__(self.obj[item], self.escape) + + def __str__(self) -> str: + return str(self.escape(self.obj)) + + def __repr__(self) -> str: + return str(self.escape(repr(self.obj))) + + def __int__(self) -> int: + return int(self.obj) + + def __float__(self) -> float: + return float(self.obj) + + +# circular import +try: + from ._speedups import escape as escape + from ._speedups import escape_silent as escape_silent + from ._speedups import soft_str as soft_str +except ImportError: + from ._native import escape as escape + from ._native import escape_silent as escape_silent # noqa: F401 + from ._native import soft_str as soft_str # noqa: F401 diff --git a/lib/python3.11/site-packages/markupsafe/__pycache__/__init__.cpython-311.pyc b/lib/python3.11/site-packages/markupsafe/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..76755930c704c9e8bb0692e0641855f36d5ab671 Binary files /dev/null and b/lib/python3.11/site-packages/markupsafe/__pycache__/__init__.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/markupsafe/__pycache__/_native.cpython-311.pyc b/lib/python3.11/site-packages/markupsafe/__pycache__/_native.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ab54ccfda85c3a8944d1a8394af4867bae039d5 Binary files /dev/null and b/lib/python3.11/site-packages/markupsafe/__pycache__/_native.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/markupsafe/_native.py b/lib/python3.11/site-packages/markupsafe/_native.py new file mode 100644 index 0000000000000000000000000000000000000000..8117b2716d110074d9a81365c59343e81396b7f5 --- /dev/null +++ b/lib/python3.11/site-packages/markupsafe/_native.py @@ -0,0 +1,63 @@ +import typing as t + +from . import Markup + + +def escape(s: t.Any) -> Markup: + """Replace the characters ``&``, ``<``, ``>``, ``'``, and ``"`` in + the string with HTML-safe sequences. Use this if you need to display + text that might contain such characters in HTML. + + If the object has an ``__html__`` method, it is called and the + return value is assumed to already be safe for HTML. + + :param s: An object to be converted to a string and escaped. + :return: A :class:`Markup` string with the escaped text. + """ + if hasattr(s, "__html__"): + return Markup(s.__html__()) + + return Markup( + str(s) + .replace("&", "&") + .replace(">", ">") + .replace("<", "<") + .replace("'", "'") + .replace('"', """) + ) + + +def escape_silent(s: t.Optional[t.Any]) -> Markup: + """Like :func:`escape` but treats ``None`` as the empty string. + Useful with optional values, as otherwise you get the string + ``'None'`` when the value is ``None``. + + >>> escape(None) + Markup('None') + >>> escape_silent(None) + Markup('') + """ + if s is None: + return Markup() + + return escape(s) + + +def soft_str(s: t.Any) -> str: + """Convert an object to a string if it isn't already. This preserves + a :class:`Markup` string rather than converting it back to a basic + string, so it will still be marked as safe and won't be escaped + again. + + >>> value = escape("") + >>> value + Markup('<User 1>') + >>> escape(str(value)) + Markup('&lt;User 1&gt;') + >>> escape(soft_str(value)) + Markup('<User 1>') + """ + if not isinstance(s, str): + return str(s) + + return s diff --git a/lib/python3.11/site-packages/markupsafe/_speedups.c b/lib/python3.11/site-packages/markupsafe/_speedups.c new file mode 100644 index 0000000000000000000000000000000000000000..3c463fb82d53e9a9616acfbbece0eb3be6d0d5e7 --- /dev/null +++ b/lib/python3.11/site-packages/markupsafe/_speedups.c @@ -0,0 +1,320 @@ +#include + +static PyObject* markup; + +static int +init_constants(void) +{ + PyObject *module; + + /* import markup type so that we can mark the return value */ + module = PyImport_ImportModule("markupsafe"); + if (!module) + return 0; + markup = PyObject_GetAttrString(module, "Markup"); + Py_DECREF(module); + + return 1; +} + +#define GET_DELTA(inp, inp_end, delta) \ + while (inp < inp_end) { \ + switch (*inp++) { \ + case '"': \ + case '\'': \ + case '&': \ + delta += 4; \ + break; \ + case '<': \ + case '>': \ + delta += 3; \ + break; \ + } \ + } + +#define DO_ESCAPE(inp, inp_end, outp) \ + { \ + Py_ssize_t ncopy = 0; \ + while (inp < inp_end) { \ + switch (*inp) { \ + case '"': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = '#'; \ + *outp++ = '3'; \ + *outp++ = '4'; \ + *outp++ = ';'; \ + break; \ + case '\'': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = '#'; \ + *outp++ = '3'; \ + *outp++ = '9'; \ + *outp++ = ';'; \ + break; \ + case '&': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'a'; \ + *outp++ = 'm'; \ + *outp++ = 'p'; \ + *outp++ = ';'; \ + break; \ + case '<': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'l'; \ + *outp++ = 't'; \ + *outp++ = ';'; \ + break; \ + case '>': \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + outp += ncopy; ncopy = 0; \ + *outp++ = '&'; \ + *outp++ = 'g'; \ + *outp++ = 't'; \ + *outp++ = ';'; \ + break; \ + default: \ + ncopy++; \ + } \ + inp++; \ + } \ + memcpy(outp, inp-ncopy, sizeof(*outp)*ncopy); \ + } + +static PyObject* +escape_unicode_kind1(PyUnicodeObject *in) +{ + Py_UCS1 *inp = PyUnicode_1BYTE_DATA(in); + Py_UCS1 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS1 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, + PyUnicode_IS_ASCII(in) ? 127 : 255); + if (!out) + return NULL; + + inp = PyUnicode_1BYTE_DATA(in); + outp = PyUnicode_1BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + +static PyObject* +escape_unicode_kind2(PyUnicodeObject *in) +{ + Py_UCS2 *inp = PyUnicode_2BYTE_DATA(in); + Py_UCS2 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS2 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 65535); + if (!out) + return NULL; + + inp = PyUnicode_2BYTE_DATA(in); + outp = PyUnicode_2BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + + +static PyObject* +escape_unicode_kind4(PyUnicodeObject *in) +{ + Py_UCS4 *inp = PyUnicode_4BYTE_DATA(in); + Py_UCS4 *inp_end = inp + PyUnicode_GET_LENGTH(in); + Py_UCS4 *outp; + PyObject *out; + Py_ssize_t delta = 0; + + GET_DELTA(inp, inp_end, delta); + if (!delta) { + Py_INCREF(in); + return (PyObject*)in; + } + + out = PyUnicode_New(PyUnicode_GET_LENGTH(in) + delta, 1114111); + if (!out) + return NULL; + + inp = PyUnicode_4BYTE_DATA(in); + outp = PyUnicode_4BYTE_DATA(out); + DO_ESCAPE(inp, inp_end, outp); + return out; +} + +static PyObject* +escape_unicode(PyUnicodeObject *in) +{ + if (PyUnicode_READY(in)) + return NULL; + + switch (PyUnicode_KIND(in)) { + case PyUnicode_1BYTE_KIND: + return escape_unicode_kind1(in); + case PyUnicode_2BYTE_KIND: + return escape_unicode_kind2(in); + case PyUnicode_4BYTE_KIND: + return escape_unicode_kind4(in); + } + assert(0); /* shouldn't happen */ + return NULL; +} + +static PyObject* +escape(PyObject *self, PyObject *text) +{ + static PyObject *id_html; + PyObject *s = NULL, *rv = NULL, *html; + + if (id_html == NULL) { + id_html = PyUnicode_InternFromString("__html__"); + if (id_html == NULL) { + return NULL; + } + } + + /* we don't have to escape integers, bools or floats */ + if (PyLong_CheckExact(text) || + PyFloat_CheckExact(text) || PyBool_Check(text) || + text == Py_None) + return PyObject_CallFunctionObjArgs(markup, text, NULL); + + /* if the object has an __html__ method that performs the escaping */ + html = PyObject_GetAttr(text ,id_html); + if (html) { + s = PyObject_CallObject(html, NULL); + Py_DECREF(html); + if (s == NULL) { + return NULL; + } + /* Convert to Markup object */ + rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); + Py_DECREF(s); + return rv; + } + + /* otherwise make the object unicode if it isn't, then escape */ + PyErr_Clear(); + if (!PyUnicode_Check(text)) { + PyObject *unicode = PyObject_Str(text); + if (!unicode) + return NULL; + s = escape_unicode((PyUnicodeObject*)unicode); + Py_DECREF(unicode); + } + else + s = escape_unicode((PyUnicodeObject*)text); + + /* convert the unicode string into a markup object. */ + rv = PyObject_CallFunctionObjArgs(markup, (PyObject*)s, NULL); + Py_DECREF(s); + return rv; +} + + +static PyObject* +escape_silent(PyObject *self, PyObject *text) +{ + if (text != Py_None) + return escape(self, text); + return PyObject_CallFunctionObjArgs(markup, NULL); +} + + +static PyObject* +soft_str(PyObject *self, PyObject *s) +{ + if (!PyUnicode_Check(s)) + return PyObject_Str(s); + Py_INCREF(s); + return s; +} + + +static PyMethodDef module_methods[] = { + { + "escape", + (PyCFunction)escape, + METH_O, + "Replace the characters ``&``, ``<``, ``>``, ``'``, and ``\"`` in" + " the string with HTML-safe sequences. Use this if you need to display" + " text that might contain such characters in HTML.\n\n" + "If the object has an ``__html__`` method, it is called and the" + " return value is assumed to already be safe for HTML.\n\n" + ":param s: An object to be converted to a string and escaped.\n" + ":return: A :class:`Markup` string with the escaped text.\n" + }, + { + "escape_silent", + (PyCFunction)escape_silent, + METH_O, + "Like :func:`escape` but treats ``None`` as the empty string." + " Useful with optional values, as otherwise you get the string" + " ``'None'`` when the value is ``None``.\n\n" + ">>> escape(None)\n" + "Markup('None')\n" + ">>> escape_silent(None)\n" + "Markup('')\n" + }, + { + "soft_str", + (PyCFunction)soft_str, + METH_O, + "Convert an object to a string if it isn't already. This preserves" + " a :class:`Markup` string rather than converting it back to a basic" + " string, so it will still be marked as safe and won't be escaped" + " again.\n\n" + ">>> value = escape(\"\")\n" + ">>> value\n" + "Markup('<User 1>')\n" + ">>> escape(str(value))\n" + "Markup('&lt;User 1&gt;')\n" + ">>> escape(soft_str(value))\n" + "Markup('<User 1>')\n" + }, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static struct PyModuleDef module_definition = { + PyModuleDef_HEAD_INIT, + "markupsafe._speedups", + NULL, + -1, + module_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit__speedups(void) +{ + if (!init_constants()) + return NULL; + + return PyModule_Create(&module_definition); +} diff --git a/lib/python3.11/site-packages/markupsafe/_speedups.cpython-311-darwin.so b/lib/python3.11/site-packages/markupsafe/_speedups.cpython-311-darwin.so new file mode 100644 index 0000000000000000000000000000000000000000..1b63f2eb76589bdebe01a385e13fe248dc1f9db1 Binary files /dev/null and b/lib/python3.11/site-packages/markupsafe/_speedups.cpython-311-darwin.so differ diff --git a/lib/python3.11/site-packages/markupsafe/_speedups.pyi b/lib/python3.11/site-packages/markupsafe/_speedups.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f673240f6d299917d829a5fdbf85d25d84dd0a72 --- /dev/null +++ b/lib/python3.11/site-packages/markupsafe/_speedups.pyi @@ -0,0 +1,9 @@ +from typing import Any +from typing import Optional + +from . import Markup + +def escape(s: Any) -> Markup: ... +def escape_silent(s: Optional[Any]) -> Markup: ... +def soft_str(s: Any) -> str: ... +def soft_unicode(s: Any) -> str: ... diff --git a/lib/python3.11/site-packages/markupsafe/py.typed b/lib/python3.11/site-packages/markupsafe/py.typed new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lib/python3.11/site-packages/mlx/__pycache__/_reprlib_fix.cpython-311.pyc b/lib/python3.11/site-packages/mlx/__pycache__/_reprlib_fix.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28703806a788a6a2081bf67ea3e54e4cde20f11a Binary files /dev/null and b/lib/python3.11/site-packages/mlx/__pycache__/_reprlib_fix.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/mlx/__pycache__/extension.cpython-311.pyc b/lib/python3.11/site-packages/mlx/__pycache__/extension.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ddfe23c64850eefd1bd949a2a9dd8951e45ecdc Binary files /dev/null and b/lib/python3.11/site-packages/mlx/__pycache__/extension.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/mlx/__pycache__/optimizers.cpython-311.pyc b/lib/python3.11/site-packages/mlx/__pycache__/optimizers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..066f6b7cc5d88d09ee92c9a699f28dfd58e7914b Binary files /dev/null and b/lib/python3.11/site-packages/mlx/__pycache__/optimizers.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/mlx/__pycache__/utils.cpython-311.pyc b/lib/python3.11/site-packages/mlx/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21f23cc05a938fcee95e53a369b12438c2de8479 Binary files /dev/null and b/lib/python3.11/site-packages/mlx/__pycache__/utils.cpython-311.pyc differ diff --git a/lib/python3.11/site-packages/mlx/_reprlib_fix.py b/lib/python3.11/site-packages/mlx/_reprlib_fix.py new file mode 100644 index 0000000000000000000000000000000000000000..02bf661dcee69b68b39023ca677f946fcc7d4105 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/_reprlib_fix.py @@ -0,0 +1,20 @@ +# Copyright © 2023 Apple Inc. + +import array +import reprlib + + +class FixedRepr(reprlib.Repr): + """Only route python array instances to repr_array.""" + + def repr_array(self, x, maxlevel): + if isinstance(x, array.array): + return super().repr_array(x, maxlevel) + else: + return self.repr_instance(x, maxlevel) + + +# We need to monkey-patch reprlib so that we can use the debugger without +# renaming the array to something else +fixed_repr = FixedRepr() +reprlib.repr = fixed_repr.repr diff --git a/lib/python3.11/site-packages/mlx/core.cpython-311-darwin.so b/lib/python3.11/site-packages/mlx/core.cpython-311-darwin.so new file mode 100644 index 0000000000000000000000000000000000000000..4fb6193d7925563f2e9782f36e52a68362ee426b --- /dev/null +++ b/lib/python3.11/site-packages/mlx/core.cpython-311-darwin.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e063225a72d2dac646b2b23007d980af2b9ee4bced7fe4adb409ff03369d9827 +size 1098840 diff --git a/lib/python3.11/site-packages/mlx/extension.py b/lib/python3.11/site-packages/mlx/extension.py new file mode 100644 index 0000000000000000000000000000000000000000..842cf667fc44b474f22e31da95e2d4fd13bcf9c7 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/extension.py @@ -0,0 +1,96 @@ +# Copyright © 2023 Apple Inc. + +import os +import re +import subprocess +import sys +from pathlib import Path + +from setuptools import Extension, find_namespace_packages, setup +from setuptools.command.build_ext import build_ext + +import mlx + +_MLX_PATH = str(mlx.__path__[0]) + + +# A CMakeExtension needs a sourcedir instead of a file list. +class CMakeExtension(Extension): + def __init__(self, name: str, sourcedir: str = "") -> None: + super().__init__(name, sources=[]) + self.sourcedir = os.fspath(Path(sourcedir).resolve()) + + +class CMakeBuild(build_ext): + def build_extension(self, ext: CMakeExtension) -> None: + # Must be in this form due to bug in .resolve() only fixed in Python 3.10+ + ext_fullpath = Path.cwd() / self.get_ext_fullpath(ext.name) # type: ignore[no-untyped-call] + extdir = ext_fullpath.parent.resolve() + + debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug + cfg = "Debug" if debug else "Release" + + # CMake lets you override the generator - we need to check this. + # Can be set with Conda-Build, for example. + cmake_generator = os.environ.get("CMAKE_GENERATOR", "") + + # Set Python_EXECUTABLE instead if you use PYBIND11_FINDPYTHON + # EXAMPLE_VERSION_INFO shows you how to pass a value into the C++ code + # from Python. + cmake_args = [ + f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}{os.sep}", + f"-DCMAKE_BUILD_TYPE={cfg}", + "-DBUILD_SHARED_LIBS=ON", + ] + build_args = [] + # Adding CMake arguments set as environment variable + # (needed e.g. to build for ARM OSx on conda-forge) + if "CMAKE_ARGS" in os.environ: + cmake_args += [item for item in os.environ["CMAKE_ARGS"].split(" ") if item] + + if sys.platform.startswith("darwin"): + # Cross-compile support for macOS - respect ARCHFLAGS if set + archs = re.findall(r"-arch (\S+)", os.environ.get("ARCHFLAGS", "")) + if archs: + cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))] + + # Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level + # across all generators. + if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ: + # self.parallel is a Python 3 only way to set parallel jobs by hand + # using -j in the build_ext call, not supported by pip or PyPA-build. + if hasattr(self, "parallel") and self.parallel: + # CMake 3.12+ only. + build_args += [f"-j{self.parallel}"] + + build_temp = Path(self.build_temp) / ext.name + if not build_temp.exists(): + build_temp.mkdir(parents=True) + + # Make sure cmake can find MLX + os.environ["MLX_DIR"] = _MLX_PATH + + subprocess.run( + ["cmake", ext.sourcedir, *cmake_args], cwd=build_temp, check=True + ) + subprocess.run( + ["cmake", "--build", ".", *build_args], cwd=build_temp, check=True + ) + + def run(self): + super().run() + + # Based on https://github.com/pypa/setuptools/blob/main/setuptools/command/build_ext.py#L102 + if self.inplace: + for ext in self.extensions: + if isinstance(ext, CMakeExtension): + # Resolve inplace package dir + build_py = self.get_finalized_command("build_py") + inplace_file, regular_file = self._get_inplace_equivalent( + build_py, ext + ) + + inplace_dir = str(Path(inplace_file).parent.resolve()) + regular_dir = str(Path(regular_file).parent.resolve()) + + self.copy_tree(regular_dir, inplace_dir) diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/Foundation.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/Foundation.hpp new file mode 100644 index 0000000000000000000000000000000000000000..8b64277ff5c3d773ace5dd2ad8d648955dd6e3cb --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/Foundation.hpp @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/Foundation.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSArray.hpp" +#include "NSAutoreleasePool.hpp" +#include "NSBundle.hpp" +#include "NSData.hpp" +#include "NSDate.hpp" +#include "NSDefines.hpp" +#include "NSDictionary.hpp" +#include "NSEnumerator.hpp" +#include "NSError.hpp" +#include "NSLock.hpp" +#include "NSNotification.hpp" +#include "NSNumber.hpp" +#include "NSObject.hpp" +#include "NSPrivate.hpp" +#include "NSProcessInfo.hpp" +#include "NSRange.hpp" +#include "NSSet.hpp" +#include "NSSharedPtr.hpp" +#include "NSString.hpp" +#include "NSTypes.hpp" +#include "NSURL.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSArray.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSArray.hpp new file mode 100644 index 0000000000000000000000000000000000000000..7ccdb80448b306b58d9ca6651d19ddfd6917799c --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSArray.hpp @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSArray.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +class Array : public Copying +{ +public: + static Array* array(); + static Array* array(const Object* pObject); + static Array* array(const Object* const* pObjects, UInteger count); + + static Array* alloc(); + + Array* init(); + Array* init(const Object* const* pObjects, UInteger count); + Array* init(const class Coder* pCoder); + + template + _Object* object(UInteger index) const; + UInteger count() const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::array() +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(array)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::array(const Object* pObject) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(arrayWithObject_), pObject); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::array(const Object* const* pObjects, UInteger count) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSArray), _NS_PRIVATE_SEL(arrayWithObjects_count_), pObjects, count); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSArray)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::init() +{ + return NS::Object::init(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::init(const Object* const* pObjects, UInteger count) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithObjects_count_), pObjects, count); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Array::init(const class Coder* pCoder) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::Array::count() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(count)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Object* NS::Array::object(UInteger index) const +{ + return Object::sendMessage<_Object*>(this, _NS_PRIVATE_SEL(objectAtIndex_), index); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSAutoreleasePool.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSAutoreleasePool.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3008590d480e60a2a450dadb52504d23254c8b23 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSAutoreleasePool.hpp @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSAutoreleasePool.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSObject.hpp" +#include "NSPrivate.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +class AutoreleasePool : public Object +{ +public: + static AutoreleasePool* alloc(); + AutoreleasePool* init(); + + void drain(); + + void addObject(Object* pObject); + + static void showPools(); +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::AutoreleasePool* NS::AutoreleasePool::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSAutoreleasePool)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::AutoreleasePool* NS::AutoreleasePool::init() +{ + return NS::Object::init(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::AutoreleasePool::drain() +{ + Object::sendMessage(this, _NS_PRIVATE_SEL(drain)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::AutoreleasePool::addObject(Object* pObject) +{ + Object::sendMessage(this, _NS_PRIVATE_SEL(addObject_), pObject); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::AutoreleasePool::showPools() +{ + Object::sendMessage(_NS_PRIVATE_CLS(NSAutoreleasePool), _NS_PRIVATE_SEL(showPools)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSBundle.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSBundle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..323d93f332ca1d82f5a247e3bf86b18c047bdb23 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSBundle.hpp @@ -0,0 +1,374 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSBundle.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSNotification.hpp" +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +_NS_CONST(NotificationName, BundleDidLoadNotification); +_NS_CONST(NotificationName, BundleResourceRequestLowDiskSpaceNotification); + +class String* LocalizedString(const String* pKey, const String*); +class String* LocalizedStringFromTable(const String* pKey, const String* pTbl, const String*); +class String* LocalizedStringFromTableInBundle(const String* pKey, const String* pTbl, const class Bundle* pBdle, const String*); +class String* LocalizedStringWithDefaultValue(const String* pKey, const String* pTbl, const class Bundle* pBdle, const String* pVal, const String*); + +class Bundle : public Referencing +{ +public: + static Bundle* mainBundle(); + + static Bundle* bundle(const class String* pPath); + static Bundle* bundle(const class URL* pURL); + + static Bundle* alloc(); + + Bundle* init(const class String* pPath); + Bundle* init(const class URL* pURL); + + class Array* allBundles() const; + class Array* allFrameworks() const; + + bool load(); + bool unload(); + + bool isLoaded() const; + + bool preflightAndReturnError(class Error** pError) const; + bool loadAndReturnError(class Error** pError); + + class URL* bundleURL() const; + class URL* resourceURL() const; + class URL* executableURL() const; + class URL* URLForAuxiliaryExecutable(const class String* pExecutableName) const; + + class URL* privateFrameworksURL() const; + class URL* sharedFrameworksURL() const; + class URL* sharedSupportURL() const; + class URL* builtInPlugInsURL() const; + class URL* appStoreReceiptURL() const; + + class String* bundlePath() const; + class String* resourcePath() const; + class String* executablePath() const; + class String* pathForAuxiliaryExecutable(const class String* pExecutableName) const; + + class String* privateFrameworksPath() const; + class String* sharedFrameworksPath() const; + class String* sharedSupportPath() const; + class String* builtInPlugInsPath() const; + + class String* bundleIdentifier() const; + class Dictionary* infoDictionary() const; + class Dictionary* localizedInfoDictionary() const; + class Object* objectForInfoDictionaryKey(const class String* pKey); + + class String* localizedString(const class String* pKey, const class String* pValue = nullptr, const class String* pTableName = nullptr) const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_PRIVATE_DEF_CONST(NS::NotificationName, BundleDidLoadNotification); +_NS_PRIVATE_DEF_CONST(NS::NotificationName, BundleResourceRequestLowDiskSpaceNotification); + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::LocalizedString(const String* pKey, const String*) +{ + return Bundle::mainBundle()->localizedString(pKey, nullptr, nullptr); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::LocalizedStringFromTable(const String* pKey, const String* pTbl, const String*) +{ + return Bundle::mainBundle()->localizedString(pKey, nullptr, pTbl); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::LocalizedStringFromTableInBundle(const String* pKey, const String* pTbl, const Bundle* pBdl, const String*) +{ + return pBdl->localizedString(pKey, nullptr, pTbl); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::LocalizedStringWithDefaultValue(const String* pKey, const String* pTbl, const Bundle* pBdl, const String* pVal, const String*) +{ + return pBdl->localizedString(pKey, pVal, pTbl); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::mainBundle() +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(mainBundle)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::bundle(const class String* pPath) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(bundleWithPath_), pPath); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::bundle(const class URL* pURL) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(bundleWithURL_), pURL); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::alloc() +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSBundle), _NS_PRIVATE_SEL(alloc)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::init(const String* pPath) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithPath_), pPath); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Bundle* NS::Bundle::init(const URL* pURL) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithURL_), pURL); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Bundle::allBundles() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(allBundles)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Bundle::allFrameworks() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(allFrameworks)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Bundle::load() +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(load)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Bundle::unload() +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unload)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Bundle::isLoaded() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(isLoaded)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Bundle::preflightAndReturnError(Error** pError) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(preflightAndReturnError_), pError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Bundle::loadAndReturnError(Error** pError) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(loadAndReturnError_), pError); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::bundleURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(bundleURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::resourceURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(resourceURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::executableURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(executableURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::URLForAuxiliaryExecutable(const String* pExecutableName) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(URLForAuxiliaryExecutable_), pExecutableName); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::privateFrameworksURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(privateFrameworksURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::sharedFrameworksURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(sharedFrameworksURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::sharedSupportURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(sharedSupportURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::builtInPlugInsURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(builtInPlugInsURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::URL* NS::Bundle::appStoreReceiptURL() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(appStoreReceiptURL)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::bundlePath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(bundlePath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::resourcePath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(resourcePath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::executablePath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(executablePath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::pathForAuxiliaryExecutable(const String* pExecutableName) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(pathForAuxiliaryExecutable_), pExecutableName); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::privateFrameworksPath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(privateFrameworksPath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::sharedFrameworksPath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(sharedFrameworksPath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::sharedSupportPath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(sharedSupportPath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::builtInPlugInsPath() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(builtInPlugInsPath)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::bundleIdentifier() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(bundleIdentifier)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Bundle::infoDictionary() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(infoDictionary)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Bundle::localizedInfoDictionary() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedInfoDictionary)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Object* NS::Bundle::objectForInfoDictionaryKey(const String* pKey) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(objectForInfoDictionaryKey_), pKey); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Bundle::localizedString(const String* pKey, const String* pValue /* = nullptr */, const String* pTableName /* = nullptr */) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedStringForKey_value_table_), pKey, pValue, pTableName); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSData.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSData.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ddfa6dd08f7a9e5fa6ffb736c74ec5f54439e7ec --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSData.hpp @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSData.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +class Data : public Copying +{ +public: + void* mutableBytes() const; + UInteger length() const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void* NS::Data::mutableBytes() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(mutableBytes)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::Data::length() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(length)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDate.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..61f10a95b738821710982fb3cab424b59078ef2b --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDate.hpp @@ -0,0 +1,53 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSDate.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSObject.hpp" +#include "NSPrivate.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ + +using TimeInterval = double; + +class Date : public Copying +{ +public: + static Date* dateWithTimeIntervalSinceNow(TimeInterval secs); +}; + +} // NS + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Date* NS::Date::dateWithTimeIntervalSinceNow(NS::TimeInterval secs) +{ + return NS::Object::sendMessage(_NS_PRIVATE_CLS(NSDate), _NS_PRIVATE_SEL(dateWithTimeIntervalSinceNow_), secs); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDefines.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDefines.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a042be631cdea60852e399c723e3c3f8209d9420 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDefines.hpp @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSDefines.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#define _NS_WEAK_IMPORT __attribute__((weak_import)) +#ifdef METALCPP_SYMBOL_VISIBILITY_HIDDEN +#define _NS_EXPORT __attribute__((visibility("hidden"))) +#else +#define _NS_EXPORT __attribute__((visibility("default"))) +#endif // METALCPP_SYMBOL_VISIBILITY_HIDDEN +#define _NS_EXTERN extern "C" _NS_EXPORT +#define _NS_INLINE inline __attribute__((always_inline)) +#define _NS_PACKED __attribute__((packed)) + +#define _NS_CONST(type, name) _NS_EXTERN type const name +#define _NS_ENUM(type, name) enum name : type +#define _NS_OPTIONS(type, name) \ + using name = type; \ + enum : name + +#define _NS_CAST_TO_UINT(value) static_cast(value) +#define _NS_VALIDATE_SIZE(ns, name) static_assert(sizeof(ns::name) == sizeof(ns##name), "size mismatch " #ns "::" #name) +#define _NS_VALIDATE_ENUM(ns, name) static_assert(_NS_CAST_TO_UINT(ns::name) == _NS_CAST_TO_UINT(ns##name), "value mismatch " #ns "::" #name) + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDictionary.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDictionary.hpp new file mode 100644 index 0000000000000000000000000000000000000000..078cd5c8f4211702e250da54df7c722b43cb36cc --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSDictionary.hpp @@ -0,0 +1,128 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSDictionary.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSEnumerator.hpp" +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +class Dictionary : public NS::Copying +{ +public: + static Dictionary* dictionary(); + static Dictionary* dictionary(const Object* pObject, const Object* pKey); + static Dictionary* dictionary(const Object* const* pObjects, const Object* const* pKeys, UInteger count); + + static Dictionary* alloc(); + + Dictionary* init(); + Dictionary* init(const Object* const* pObjects, const Object* const* pKeys, UInteger count); + Dictionary* init(const class Coder* pCoder); + + template + Enumerator<_KeyType>* keyEnumerator() const; + + template + _Object* object(const Object* pKey) const; + UInteger count() const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary() +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionary)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary(const Object* pObject, const Object* pKey) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionaryWithObject_forKey_), pObject, pKey); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::dictionary(const Object* const* pObjects, const Object* const* pKeys, UInteger count) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSDictionary), _NS_PRIVATE_SEL(dictionaryWithObjects_forKeys_count_), + pObjects, pKeys, count); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSDictionary)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::init() +{ + return NS::Object::init(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::init(const Object* const* pObjects, const Object* const* pKeys, UInteger count) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithObjects_forKeys_count_), pObjects, pKeys, count); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Dictionary::init(const class Coder* pCoder) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE NS::Enumerator<_KeyType>* NS::Dictionary::keyEnumerator() const +{ + return Object::sendMessage*>(this, _NS_PRIVATE_SEL(keyEnumerator)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Object* NS::Dictionary::object(const Object* pKey) const +{ + return Object::sendMessage<_Object*>(this, _NS_PRIVATE_SEL(objectForKey_), pKey); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::Dictionary::count() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(count)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSEnumerator.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSEnumerator.hpp new file mode 100644 index 0000000000000000000000000000000000000000..eed19dbac28b8ceb3e624bd4e49ce332486a346f --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSEnumerator.hpp @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSEnumerator.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +struct FastEnumerationState +{ + unsigned long state; + Object** itemsPtr; + unsigned long* mutationsPtr; + unsigned long extra[5]; +} _NS_PACKED; + +class FastEnumeration : public Referencing +{ +public: + NS::UInteger countByEnumerating(FastEnumerationState* pState, Object** pBuffer, NS::UInteger len); +}; + +template +class Enumerator : public Referencing, FastEnumeration> +{ +public: + _ObjectType* nextObject(); + class Array* allObjects(); +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::FastEnumeration::countByEnumerating(FastEnumerationState* pState, Object** pBuffer, NS::UInteger len) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(countByEnumeratingWithState_objects_count_), pState, pBuffer, len); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _ObjectType* NS::Enumerator<_ObjectType>::nextObject() +{ + return Object::sendMessage<_ObjectType*>(this, _NS_PRIVATE_SEL(nextObject)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE NS::Array* NS::Enumerator<_ObjectType>::allObjects() +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(allObjects)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSError.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSError.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f19ff861f7ca38e19526e1d54a2879fbbd8c8fa8 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSError.hpp @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSError.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSObject.hpp" +#include "NSPrivate.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +using ErrorDomain = class String*; + +_NS_CONST(ErrorDomain, CocoaErrorDomain); +_NS_CONST(ErrorDomain, POSIXErrorDomain); +_NS_CONST(ErrorDomain, OSStatusErrorDomain); +_NS_CONST(ErrorDomain, MachErrorDomain); + +using ErrorUserInfoKey = class String*; + +_NS_CONST(ErrorUserInfoKey, UnderlyingErrorKey); +_NS_CONST(ErrorUserInfoKey, LocalizedDescriptionKey); +_NS_CONST(ErrorUserInfoKey, LocalizedFailureReasonErrorKey); +_NS_CONST(ErrorUserInfoKey, LocalizedRecoverySuggestionErrorKey); +_NS_CONST(ErrorUserInfoKey, LocalizedRecoveryOptionsErrorKey); +_NS_CONST(ErrorUserInfoKey, RecoveryAttempterErrorKey); +_NS_CONST(ErrorUserInfoKey, HelpAnchorErrorKey); +_NS_CONST(ErrorUserInfoKey, DebugDescriptionErrorKey); +_NS_CONST(ErrorUserInfoKey, LocalizedFailureErrorKey); +_NS_CONST(ErrorUserInfoKey, StringEncodingErrorKey); +_NS_CONST(ErrorUserInfoKey, URLErrorKey); +_NS_CONST(ErrorUserInfoKey, FilePathErrorKey); + +class Error : public Copying +{ +public: + static Error* error(ErrorDomain domain, Integer code, class Dictionary* pDictionary); + + static Error* alloc(); + Error* init(); + Error* init(ErrorDomain domain, Integer code, class Dictionary* pDictionary); + + Integer code() const; + ErrorDomain domain() const; + class Dictionary* userInfo() const; + + class String* localizedDescription() const; + class Array* localizedRecoveryOptions() const; + class String* localizedRecoverySuggestion() const; + class String* localizedFailureReason() const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, CocoaErrorDomain); +_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, POSIXErrorDomain); +_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, OSStatusErrorDomain); +_NS_PRIVATE_DEF_CONST(NS::ErrorDomain, MachErrorDomain); + +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, UnderlyingErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedDescriptionKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedFailureReasonErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedRecoverySuggestionErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedRecoveryOptionsErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, RecoveryAttempterErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, HelpAnchorErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, DebugDescriptionErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, LocalizedFailureErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, StringEncodingErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, URLErrorKey); +_NS_PRIVATE_DEF_CONST(NS::ErrorUserInfoKey, FilePathErrorKey); + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Error* NS::Error::error(ErrorDomain domain, Integer code, class Dictionary* pDictionary) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSError), _NS_PRIVATE_SEL(errorWithDomain_code_userInfo_), domain, code, pDictionary); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Error* NS::Error::alloc() +{ + return Object::alloc(_NS_PRIVATE_CLS(NSError)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Error* NS::Error::init() +{ + return Object::init(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Error* NS::Error::init(ErrorDomain domain, Integer code, class Dictionary* pDictionary) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithDomain_code_userInfo_), domain, code, pDictionary); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Integer NS::Error::code() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(code)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::ErrorDomain NS::Error::domain() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(domain)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Error::userInfo() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(userInfo)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Error::localizedDescription() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedDescription)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Array* NS::Error::localizedRecoveryOptions() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedRecoveryOptions)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Error::localizedRecoverySuggestion() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedRecoverySuggestion)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Error::localizedFailureReason() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(localizedFailureReason)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSLock.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSLock.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ca371fbae8030d33f36aafd9c1f03b53da622ba9 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSLock.hpp @@ -0,0 +1,118 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSLock.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSObject.hpp" +#include "NSPrivate.hpp" +#include "NSTypes.hpp" +#include "NSDate.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ + +template +class Locking : public _Base +{ +public: + void lock(); + void unlock(); +}; + +class Condition : public Locking +{ +public: + static Condition* alloc(); + + Condition* init(); + + void wait(); + bool waitUntilDate(Date* pLimit); + void signal(); + void broadcast(); +}; + +} // NS + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE void NS::Locking<_Class, _Base>::lock() +{ + NS::Object::sendMessage(this, _NS_PRIVATE_SEL(lock)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE void NS::Locking<_Class, _Base>::unlock() +{ + NS::Object::sendMessage(this, _NS_PRIVATE_SEL(unlock)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Condition* NS::Condition::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSCondition)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Condition* NS::Condition::init() +{ + return NS::Object::init(); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::Condition::wait() +{ + NS::Object::sendMessage(this, _NS_PRIVATE_SEL(wait)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Condition::waitUntilDate(NS::Date* pLimit) +{ + return NS::Object::sendMessage(this, _NS_PRIVATE_SEL(waitUntilDate_), pLimit); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::Condition::signal() +{ + NS::Object::sendMessage(this, _NS_PRIVATE_SEL(signal)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::Condition::broadcast() +{ + NS::Object::sendMessage(this, _NS_PRIVATE_SEL(broadcast)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNotification.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNotification.hpp new file mode 100644 index 0000000000000000000000000000000000000000..49cf2d4a498f362f02685a953b249315e82ad23c --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNotification.hpp @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSNotification.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSDictionary.hpp" +#include "NSObject.hpp" +#include "NSString.hpp" +#include "NSTypes.hpp" +#include + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +using NotificationName = class String*; + +class Notification : public NS::Referencing +{ +public: + NS::String* name() const; + NS::Object* object() const; + NS::Dictionary* userInfo() const; +}; + +using ObserverBlock = void(^)(Notification*); +using ObserverFunction = std::function; + +class NotificationCenter : public NS::Referencing +{ + public: + static class NotificationCenter* defaultCenter(); + Object* addObserver(NotificationName name, Object* pObj, void* pQueue, ObserverBlock block); + Object* addObserver(NotificationName name, Object* pObj, void* pQueue, ObserverFunction &handler); + void removeObserver(Object* pObserver); + +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Notification::name() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(name)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Object* NS::Notification::object() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(object)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Dictionary* NS::Notification::userInfo() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(userInfo)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::NotificationCenter* NS::NotificationCenter::defaultCenter() +{ + return NS::Object::sendMessage(_NS_PRIVATE_CLS(NSNotificationCenter), _NS_PRIVATE_SEL(defaultCenter)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Object* NS::NotificationCenter::addObserver(NS::NotificationName name, Object* pObj, void* pQueue, NS::ObserverBlock block) +{ + return NS::Object::sendMessage(this, _NS_PRIVATE_SEL(addObserverName_object_queue_block_), name, pObj, pQueue, block); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Object* NS::NotificationCenter::addObserver(NS::NotificationName name, Object* pObj, void* pQueue, NS::ObserverFunction &handler) +{ + __block ObserverFunction blockFunction = handler; + + return addObserver(name, pObj, pQueue, ^(NS::Notification* pNotif) {blockFunction(pNotif);}); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::NotificationCenter::removeObserver(Object* pObserver) +{ + return NS::Object::sendMessage(this, _NS_PRIVATE_SEL(removeObserver_), pObserver); +} + diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNumber.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNumber.hpp new file mode 100644 index 0000000000000000000000000000000000000000..13c7802487a8d5ab94660f1e24871d5ff25b1e9c --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSNumber.hpp @@ -0,0 +1,501 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSNumber.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSObjCRuntime.hpp" +#include "NSObject.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +class Value : public Copying +{ +public: + static Value* value(const void* pValue, const char* pType); + static Value* value(const void* pPointer); + + static Value* alloc(); + + Value* init(const void* pValue, const char* pType); + Value* init(const class Coder* pCoder); + + void getValue(void* pValue, UInteger size) const; + const char* objCType() const; + + bool isEqualToValue(Value* pValue) const; + void* pointerValue() const; +}; + +class Number : public Copying +{ +public: + static Number* number(char value); + static Number* number(unsigned char value); + static Number* number(short value); + static Number* number(unsigned short value); + static Number* number(int value); + static Number* number(unsigned int value); + static Number* number(long value); + static Number* number(unsigned long value); + static Number* number(long long value); + static Number* number(unsigned long long value); + static Number* number(float value); + static Number* number(double value); + static Number* number(bool value); + + static Number* alloc(); + + Number* init(const class Coder* pCoder); + Number* init(char value); + Number* init(unsigned char value); + Number* init(short value); + Number* init(unsigned short value); + Number* init(int value); + Number* init(unsigned int value); + Number* init(long value); + Number* init(unsigned long value); + Number* init(long long value); + Number* init(unsigned long long value); + Number* init(float value); + Number* init(double value); + Number* init(bool value); + + char charValue() const; + unsigned char unsignedCharValue() const; + short shortValue() const; + unsigned short unsignedShortValue() const; + int intValue() const; + unsigned int unsignedIntValue() const; + long longValue() const; + unsigned long unsignedLongValue() const; + long long longLongValue() const; + unsigned long long unsignedLongLongValue() const; + float floatValue() const; + double doubleValue() const; + bool boolValue() const; + Integer integerValue() const; + UInteger unsignedIntegerValue() const; + class String* stringValue() const; + + ComparisonResult compare(const Number* pOtherNumber) const; + bool isEqualToNumber(const Number* pNumber) const; + + class String* descriptionWithLocale(const Object* pLocale) const; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Value* NS::Value::value(const void* pValue, const char* pType) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSValue), _NS_PRIVATE_SEL(valueWithBytes_objCType_), pValue, pType); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Value* NS::Value::value(const void* pPointer) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSValue), _NS_PRIVATE_SEL(valueWithPointer_), pPointer); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Value* NS::Value::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Value* NS::Value::init(const void* pValue, const char* pType) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithBytes_objCType_), pValue, pType); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Value* NS::Value::init(const class Coder* pCoder) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void NS::Value::getValue(void* pValue, UInteger size) const +{ + Object::sendMessage(this, _NS_PRIVATE_SEL(getValue_size_), pValue, size); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE const char* NS::Value::objCType() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(objCType)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Value::isEqualToValue(Value* pValue) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(isEqualToValue_), pValue); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE void* NS::Value::pointerValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(pointerValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(char value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithChar_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(unsigned char value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedChar_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(short value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithShort_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(unsigned short value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedShort_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(int value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithInt_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(unsigned int value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedInt_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(long value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(unsigned long value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(long long value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithLongLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(unsigned long long value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithUnsignedLongLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(float value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithFloat_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(double value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithDouble_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::number(bool value) +{ + return Object::sendMessage(_NS_PRIVATE_CLS(NSNumber), _NS_PRIVATE_SEL(numberWithBool_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::alloc() +{ + return NS::Object::alloc(_NS_PRIVATE_CLS(NSNumber)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(const Coder* pCoder) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithCoder_), pCoder); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(char value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithChar_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(unsigned char value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithUnsignedChar_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(short value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithShort_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(unsigned short value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithUnsignedShort_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(int value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithInt_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(unsigned int value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithUnsignedInt_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(long value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(unsigned long value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithUnsignedLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(long long value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithLongLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(unsigned long long value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithUnsignedLongLong_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(float value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithFloat_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(double value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithDouble_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Number* NS::Number::init(bool value) +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(initWithBool_), value); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE char NS::Number::charValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(charValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE unsigned char NS::Number::unsignedCharValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedCharValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE short NS::Number::shortValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(shortValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE unsigned short NS::Number::unsignedShortValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedShortValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE int NS::Number::intValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(intValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE unsigned int NS::Number::unsignedIntValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedIntValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE long NS::Number::longValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(longValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE unsigned long NS::Number::unsignedLongValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedLongValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE long long NS::Number::longLongValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(longLongValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE unsigned long long NS::Number::unsignedLongLongValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedLongLongValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE float NS::Number::floatValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(floatValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE double NS::Number::doubleValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(doubleValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Number::boolValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(boolValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::Integer NS::Number::integerValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(integerValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::Number::unsignedIntegerValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(unsignedIntegerValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Number::stringValue() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(stringValue)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::ComparisonResult NS::Number::compare(const Number* pOtherNumber) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(compare_), pOtherNumber); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Number::isEqualToNumber(const Number* pNumber) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(isEqualToNumber_), pNumber); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Number::descriptionWithLocale(const Object* pLocale) const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(descriptionWithLocale_), pLocale); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObjCRuntime.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObjCRuntime.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a3860e94a466a26fe6de09e751076dcfbae149e4 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObjCRuntime.hpp @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSObjCRuntime.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSTypes.hpp" + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ + +_NS_ENUM(Integer, ComparisonResult) { + OrderedAscending = -1L, + OrderedSame, + OrderedDescending +}; + +const Integer NotFound = IntegerMax; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObject.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObject.hpp new file mode 100644 index 0000000000000000000000000000000000000000..957071bcaf5ed7b50c4911612c48e72e65304435 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSObject.hpp @@ -0,0 +1,302 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSObject.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include "NSDefines.hpp" +#include "NSPrivate.hpp" +#include "NSTypes.hpp" + +#include +#include + +#include + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +template +class _NS_EXPORT Referencing : public _Base +{ +public: + _Class* retain(); + void release(); + + _Class* autorelease(); + + UInteger retainCount() const; +}; + +template +class Copying : public Referencing<_Class, _Base> +{ +public: + _Class* copy() const; +}; + +template +class SecureCoding : public Referencing<_Class, _Base> +{ +}; + +class Object : public Referencing +{ +public: + UInteger hash() const; + bool isEqual(const Object* pObject) const; + + class String* description() const; + class String* debugDescription() const; + +protected: + friend class Referencing; + + template + static _Class* alloc(const char* pClassName); + template + static _Class* alloc(const void* pClass); + template + _Class* init(); + + template + static _Dst bridgingCast(const void* pObj); + static class MethodSignature* methodSignatureForSelector(const void* pObj, SEL selector); + static bool respondsToSelector(const void* pObj, SEL selector); + template + static constexpr bool doesRequireMsgSendStret(); + template + static _Ret sendMessage(const void* pObj, SEL selector, _Args... args); + template + static _Ret sendMessageSafe(const void* pObj, SEL selector, _Args... args); + +private: + Object() = delete; + Object(const Object&) = delete; + ~Object() = delete; + + Object& operator=(const Object&) = delete; +}; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Referencing<_Class, _Base>::retain() +{ + return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(retain)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE void NS::Referencing<_Class, _Base>::release() +{ + Object::sendMessage(this, _NS_PRIVATE_SEL(release)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Referencing<_Class, _Base>::autorelease() +{ + return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(autorelease)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE NS::UInteger NS::Referencing<_Class, _Base>::retainCount() const +{ + return Object::sendMessage(this, _NS_PRIVATE_SEL(retainCount)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Copying<_Class, _Base>::copy() const +{ + return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(copy)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Dst NS::Object::bridgingCast(const void* pObj) +{ +#ifdef __OBJC__ + return (__bridge _Dst)pObj; +#else + return (_Dst)pObj; +#endif // __OBJC__ +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret() +{ +#if (defined(__i386__) || defined(__x86_64__)) + constexpr size_t kStructLimit = (sizeof(std::uintptr_t) << 1); + + return sizeof(_Type) > kStructLimit; +#elif defined(__arm64__) + return false; +#elif defined(__arm__) + constexpr size_t kStructLimit = sizeof(std::uintptr_t); + + return std::is_class(_Type) && (sizeof(_Type) > kStructLimit); +#else +#error "Unsupported architecture!" +#endif +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template <> +_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret() +{ + return false; +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Ret NS::Object::sendMessage(const void* pObj, SEL selector, _Args... args) +{ +#if (defined(__i386__) || defined(__x86_64__)) + if constexpr (std::is_floating_point<_Ret>()) + { + using SendMessageProcFpret = _Ret (*)(const void*, SEL, _Args...); + + const SendMessageProcFpret pProc = reinterpret_cast(&objc_msgSend_fpret); + + return (*pProc)(pObj, selector, args...); + } + else +#endif // ( defined( __i386__ ) || defined( __x86_64__ ) ) +#if !defined(__arm64__) + if constexpr (doesRequireMsgSendStret<_Ret>()) + { + using SendMessageProcStret = void (*)(_Ret*, const void*, SEL, _Args...); + + const SendMessageProcStret pProc = reinterpret_cast(&objc_msgSend_stret); + _Ret ret; + + (*pProc)(&ret, pObj, selector, args...); + + return ret; + } + else +#endif // !defined( __arm64__ ) + { + using SendMessageProc = _Ret (*)(const void*, SEL, _Args...); + + const SendMessageProc pProc = reinterpret_cast(&objc_msgSend); + + return (*pProc)(pObj, selector, args...); + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::MethodSignature* NS::Object::methodSignatureForSelector(const void* pObj, SEL selector) +{ + return sendMessage(pObj, _NS_PRIVATE_SEL(methodSignatureForSelector_), selector); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Object::respondsToSelector(const void* pObj, SEL selector) +{ + return sendMessage(pObj, _NS_PRIVATE_SEL(respondsToSelector_), selector); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Ret NS::Object::sendMessageSafe(const void* pObj, SEL selector, _Args... args) +{ + if ((respondsToSelector(pObj, selector)) || (nullptr != methodSignatureForSelector(pObj, selector))) + { + return sendMessage<_Ret>(pObj, selector, args...); + } + + if constexpr (!std::is_void<_Ret>::value) + { + return 0; + } +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Object::alloc(const char* pClassName) +{ + return sendMessage<_Class*>(objc_lookUpClass(pClassName), _NS_PRIVATE_SEL(alloc)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Object::alloc(const void* pClass) +{ + return sendMessage<_Class*>(pClass, _NS_PRIVATE_SEL(alloc)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +template +_NS_INLINE _Class* NS::Object::init() +{ + return sendMessage<_Class*>(this, _NS_PRIVATE_SEL(init)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::UInteger NS::Object::hash() const +{ + return sendMessage(this, _NS_PRIVATE_SEL(hash)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE bool NS::Object::isEqual(const Object* pObject) const +{ + return sendMessage(this, _NS_PRIVATE_SEL(isEqual_), pObject); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Object::description() const +{ + return sendMessage(this, _NS_PRIVATE_SEL(description)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +_NS_INLINE NS::String* NS::Object::debugDescription() const +{ + return sendMessageSafe(this, _NS_PRIVATE_SEL(debugDescription)); +} + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSPrivate.hpp b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSPrivate.hpp new file mode 100644 index 0000000000000000000000000000000000000000..af5ffb148fa6e6c932d86dfe70a894006ffb4eb0 --- /dev/null +++ b/lib/python3.11/site-packages/mlx/include/metal_cpp/Foundation/NSPrivate.hpp @@ -0,0 +1,507 @@ +//------------------------------------------------------------------------------------------------------------------------------------------------------------- +// +// Foundation/NSPrivate.hpp +// +// Copyright 2020-2023 Apple Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#pragma once + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#include + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#define _NS_PRIVATE_CLS(symbol) (Private::Class::s_k##symbol) +#define _NS_PRIVATE_SEL(accessor) (Private::Selector::s_k##accessor) + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#if defined(NS_PRIVATE_IMPLEMENTATION) + +#ifdef METALCPP_SYMBOL_VISIBILITY_HIDDEN +#define _NS_PRIVATE_VISIBILITY __attribute__((visibility("hidden"))) +#else +#define _NS_PRIVATE_VISIBILITY __attribute__((visibility("default"))) +#endif // METALCPP_SYMBOL_VISIBILITY_HIDDEN + +#define _NS_PRIVATE_IMPORT __attribute__((weak_import)) + +#ifdef __OBJC__ +#define _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol) ((__bridge void*)objc_lookUpClass(#symbol)) +#define _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol) ((__bridge void*)objc_getProtocol(#symbol)) +#else +#define _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol) objc_lookUpClass(#symbol) +#define _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol) objc_getProtocol(#symbol) +#endif // __OBJC__ + +#define _NS_PRIVATE_DEF_CLS(symbol) void* s_k##symbol _NS_PRIVATE_VISIBILITY = _NS_PRIVATE_OBJC_LOOKUP_CLASS(symbol) +#define _NS_PRIVATE_DEF_PRO(symbol) void* s_k##symbol _NS_PRIVATE_VISIBILITY = _NS_PRIVATE_OBJC_GET_PROTOCOL(symbol) +#define _NS_PRIVATE_DEF_SEL(accessor, symbol) SEL s_k##accessor _NS_PRIVATE_VISIBILITY = sel_registerName(symbol) +#define _NS_PRIVATE_DEF_CONST(type, symbol) \ + _NS_EXTERN type const NS##symbol _NS_PRIVATE_IMPORT; \ + type const NS::symbol = (nullptr != &NS##symbol) ? NS##symbol : nullptr + +#else + +#define _NS_PRIVATE_DEF_CLS(symbol) extern void* s_k##symbol +#define _NS_PRIVATE_DEF_PRO(symbol) extern void* s_k##symbol +#define _NS_PRIVATE_DEF_SEL(accessor, symbol) extern SEL s_k##accessor +#define _NS_PRIVATE_DEF_CONST(type, symbol) extern type const NS::symbol + +#endif // NS_PRIVATE_IMPLEMENTATION + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +namespace Private +{ + namespace Class + { + + _NS_PRIVATE_DEF_CLS(NSArray); + _NS_PRIVATE_DEF_CLS(NSAutoreleasePool); + _NS_PRIVATE_DEF_CLS(NSBundle); + _NS_PRIVATE_DEF_CLS(NSCondition); + _NS_PRIVATE_DEF_CLS(NSDate); + _NS_PRIVATE_DEF_CLS(NSDictionary); + _NS_PRIVATE_DEF_CLS(NSError); + _NS_PRIVATE_DEF_CLS(NSNotificationCenter); + _NS_PRIVATE_DEF_CLS(NSNumber); + _NS_PRIVATE_DEF_CLS(NSObject); + _NS_PRIVATE_DEF_CLS(NSProcessInfo); + _NS_PRIVATE_DEF_CLS(NSSet); + _NS_PRIVATE_DEF_CLS(NSString); + _NS_PRIVATE_DEF_CLS(NSURL); + _NS_PRIVATE_DEF_CLS(NSValue); + + } // Class +} // Private +} // MTL + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +namespace Private +{ + namespace Protocol + { + + } // Protocol +} // Private +} // NS + +//------------------------------------------------------------------------------------------------------------------------------------------------------------- + +namespace NS +{ +namespace Private +{ + namespace Selector + { + + _NS_PRIVATE_DEF_SEL(addObject_, + "addObject:"); + _NS_PRIVATE_DEF_SEL(addObserverName_object_queue_block_, + "addObserverForName:object:queue:usingBlock:"); + _NS_PRIVATE_DEF_SEL(activeProcessorCount, + "activeProcessorCount"); + _NS_PRIVATE_DEF_SEL(allBundles, + "allBundles"); + _NS_PRIVATE_DEF_SEL(allFrameworks, + "allFrameworks"); + _NS_PRIVATE_DEF_SEL(allObjects, + "allObjects"); + _NS_PRIVATE_DEF_SEL(alloc, + "alloc"); + _NS_PRIVATE_DEF_SEL(appStoreReceiptURL, + "appStoreReceiptURL"); + _NS_PRIVATE_DEF_SEL(arguments, + "arguments"); + _NS_PRIVATE_DEF_SEL(array, + "array"); + _NS_PRIVATE_DEF_SEL(arrayWithObject_, + "arrayWithObject:"); + _NS_PRIVATE_DEF_SEL(arrayWithObjects_count_, + "arrayWithObjects:count:"); + _NS_PRIVATE_DEF_SEL(automaticTerminationSupportEnabled, + "automaticTerminationSupportEnabled"); + _NS_PRIVATE_DEF_SEL(autorelease, + "autorelease"); + _NS_PRIVATE_DEF_SEL(beginActivityWithOptions_reason_, + "beginActivityWithOptions:reason:"); + _NS_PRIVATE_DEF_SEL(boolValue, + "boolValue"); + _NS_PRIVATE_DEF_SEL(broadcast, + "broadcast"); + _NS_PRIVATE_DEF_SEL(builtInPlugInsPath, + "builtInPlugInsPath"); + _NS_PRIVATE_DEF_SEL(builtInPlugInsURL, + "builtInPlugInsURL"); + _NS_PRIVATE_DEF_SEL(bundleIdentifier, + "bundleIdentifier"); + _NS_PRIVATE_DEF_SEL(bundlePath, + "bundlePath"); + _NS_PRIVATE_DEF_SEL(bundleURL, + "bundleURL"); + _NS_PRIVATE_DEF_SEL(bundleWithPath_, + "bundleWithPath:"); + _NS_PRIVATE_DEF_SEL(bundleWithURL_, + "bundleWithURL:"); + _NS_PRIVATE_DEF_SEL(caseInsensitiveCompare_, + "caseInsensitiveCompare:"); + _NS_PRIVATE_DEF_SEL(characterAtIndex_, + "characterAtIndex:"); + _NS_PRIVATE_DEF_SEL(charValue, + "charValue"); + _NS_PRIVATE_DEF_SEL(countByEnumeratingWithState_objects_count_, + "countByEnumeratingWithState:objects:count:"); + _NS_PRIVATE_DEF_SEL(cStringUsingEncoding_, + "cStringUsingEncoding:"); + _NS_PRIVATE_DEF_SEL(code, + "code"); + _NS_PRIVATE_DEF_SEL(compare_, + "compare:"); + _NS_PRIVATE_DEF_SEL(copy, + "copy"); + _NS_PRIVATE_DEF_SEL(count, + "count"); + _NS_PRIVATE_DEF_SEL(dateWithTimeIntervalSinceNow_, + "dateWithTimeIntervalSinceNow:"); + _NS_PRIVATE_DEF_SEL(defaultCenter, + "defaultCenter"); + _NS_PRIVATE_DEF_SEL(descriptionWithLocale_, + "descriptionWithLocale:"); + _NS_PRIVATE_DEF_SEL(disableAutomaticTermination_, + "disableAutomaticTermination:"); + _NS_PRIVATE_DEF_SEL(disableSuddenTermination, + "disableSuddenTermination"); + _NS_PRIVATE_DEF_SEL(debugDescription, + "debugDescription"); + _NS_PRIVATE_DEF_SEL(description, + "description"); + _NS_PRIVATE_DEF_SEL(dictionary, + "dictionary"); + _NS_PRIVATE_DEF_SEL(dictionaryWithObject_forKey_, + "dictionaryWithObject:forKey:"); + _NS_PRIVATE_DEF_SEL(dictionaryWithObjects_forKeys_count_, + "dictionaryWithObjects:forKeys:count:"); + _NS_PRIVATE_DEF_SEL(domain, + "domain"); + _NS_PRIVATE_DEF_SEL(doubleValue, + "doubleValue"); + _NS_PRIVATE_DEF_SEL(drain, + "drain"); + _NS_PRIVATE_DEF_SEL(enableAutomaticTermination_, + "enableAutomaticTermination:"); + _NS_PRIVATE_DEF_SEL(enableSuddenTermination, + "enableSuddenTermination"); + _NS_PRIVATE_DEF_SEL(endActivity_, + "endActivity:"); + _NS_PRIVATE_DEF_SEL(environment, + "environment"); + _NS_PRIVATE_DEF_SEL(errorWithDomain_code_userInfo_, + "errorWithDomain:code:userInfo:"); + _NS_PRIVATE_DEF_SEL(executablePath, + "executablePath"); + _NS_PRIVATE_DEF_SEL(executableURL, + "executableURL"); + _NS_PRIVATE_DEF_SEL(fileSystemRepresentation, + "fileSystemRepresentation"); + _NS_PRIVATE_DEF_SEL(fileURLWithPath_, + "fileURLWithPath:"); + _NS_PRIVATE_DEF_SEL(floatValue, + "floatValue"); + _NS_PRIVATE_DEF_SEL(fullUserName, + "fullUserName"); + _NS_PRIVATE_DEF_SEL(getValue_size_, + "getValue:size:"); + _NS_PRIVATE_DEF_SEL(globallyUniqueString, + "globallyUniqueString"); + _NS_PRIVATE_DEF_SEL(hash, + "hash"); + _NS_PRIVATE_DEF_SEL(hostName, + "hostName"); + _NS_PRIVATE_DEF_SEL(infoDictionary, + "infoDictionary"); + _NS_PRIVATE_DEF_SEL(init, + "init"); + _NS_PRIVATE_DEF_SEL(initFileURLWithPath_, + "initFileURLWithPath:"); + _NS_PRIVATE_DEF_SEL(initWithBool_, + "initWithBool:"); + _NS_PRIVATE_DEF_SEL(initWithBytes_objCType_, + "initWithBytes:objCType:"); + _NS_PRIVATE_DEF_SEL(initWithBytesNoCopy_length_encoding_freeWhenDone_, + "initWithBytesNoCopy:length:encoding:freeWhenDone:"); + _NS_PRIVATE_DEF_SEL(initWithChar_, + "initWithChar:"); + _NS_PRIVATE_DEF_SEL(initWithCoder_, + "initWithCoder:"); + _NS_PRIVATE_DEF_SEL(initWithCString_encoding_, + "initWithCString:encoding:"); + _NS_PRIVATE_DEF_SEL(initWithDomain_code_userInfo_, + "initWithDomain:code:userInfo:"); + _NS_PRIVATE_DEF_SEL(initWithDouble_, + "initWithDouble:"); + _NS_PRIVATE_DEF_SEL(initWithFloat_, + "initWithFloat:"); + _NS_PRIVATE_DEF_SEL(initWithInt_, + "initWithInt:"); + _NS_PRIVATE_DEF_SEL(initWithLong_, + "initWithLong:"); + _NS_PRIVATE_DEF_SEL(initWithLongLong_, + "initWithLongLong:"); + _NS_PRIVATE_DEF_SEL(initWithObjects_count_, + "initWithObjects:count:"); + _NS_PRIVATE_DEF_SEL(initWithObjects_forKeys_count_, + "initWithObjects:forKeys:count:"); + _NS_PRIVATE_DEF_SEL(initWithPath_, + "initWithPath:"); + _NS_PRIVATE_DEF_SEL(initWithShort_, + "initWithShort:"); + _NS_PRIVATE_DEF_SEL(initWithString_, + "initWithString:"); + _NS_PRIVATE_DEF_SEL(initWithUnsignedChar_, + "initWithUnsignedChar:"); + _NS_PRIVATE_DEF_SEL(initWithUnsignedInt_, + "initWithUnsignedInt:"); + _NS_PRIVATE_DEF_SEL(initWithUnsignedLong_, + "initWithUnsignedLong:"); + _NS_PRIVATE_DEF_SEL(initWithUnsignedLongLong_, + "initWithUnsignedLongLong:"); + _NS_PRIVATE_DEF_SEL(initWithUnsignedShort_, + "initWithUnsignedShort:"); + _NS_PRIVATE_DEF_SEL(initWithURL_, + "initWithURL:"); + _NS_PRIVATE_DEF_SEL(integerValue, + "integerValue"); + _NS_PRIVATE_DEF_SEL(intValue, + "intValue"); + _NS_PRIVATE_DEF_SEL(isEqual_, + "isEqual:"); + _NS_PRIVATE_DEF_SEL(isEqualToNumber_, + "isEqualToNumber:"); + _NS_PRIVATE_DEF_SEL(isEqualToString_, + "isEqualToString:"); + _NS_PRIVATE_DEF_SEL(isEqualToValue_, + "isEqualToValue:"); + _NS_PRIVATE_DEF_SEL(isiOSAppOnMac, + "isiOSAppOnMac"); + _NS_PRIVATE_DEF_SEL(isLoaded, + "isLoaded"); + _NS_PRIVATE_DEF_SEL(isLowPowerModeEnabled, + "isLowPowerModeEnabled"); + _NS_PRIVATE_DEF_SEL(isMacCatalystApp, + "isMacCatalystApp"); + _NS_PRIVATE_DEF_SEL(isOperatingSystemAtLeastVersion_, + "isOperatingSystemAtLeastVersion:"); + _NS_PRIVATE_DEF_SEL(keyEnumerator, + "keyEnumerator"); + _NS_PRIVATE_DEF_SEL(length, + "length"); + _NS_PRIVATE_DEF_SEL(lengthOfBytesUsingEncoding_, + "lengthOfBytesUsingEncoding:"); + _NS_PRIVATE_DEF_SEL(load, + "load"); + _NS_PRIVATE_DEF_SEL(loadAndReturnError_, + "loadAndReturnError:"); + _NS_PRIVATE_DEF_SEL(localizedDescription, + "localizedDescription"); + _NS_PRIVATE_DEF_SEL(localizedFailureReason, + "localizedFailureReason"); + _NS_PRIVATE_DEF_SEL(localizedInfoDictionary, + "localizedInfoDictionary"); + _NS_PRIVATE_DEF_SEL(localizedRecoveryOptions, + "localizedRecoveryOptions"); + _NS_PRIVATE_DEF_SEL(localizedRecoverySuggestion, + "localizedRecoverySuggestion"); + _NS_PRIVATE_DEF_SEL(localizedStringForKey_value_table_, + "localizedStringForKey:value:table:"); + _NS_PRIVATE_DEF_SEL(lock, + "lock"); + _NS_PRIVATE_DEF_SEL(longValue, + "longValue"); + _NS_PRIVATE_DEF_SEL(longLongValue, + "longLongValue"); + _NS_PRIVATE_DEF_SEL(mainBundle, + "mainBundle"); + _NS_PRIVATE_DEF_SEL(maximumLengthOfBytesUsingEncoding_, + "maximumLengthOfBytesUsingEncoding:"); + _NS_PRIVATE_DEF_SEL(methodSignatureForSelector_, + "methodSignatureForSelector:"); + _NS_PRIVATE_DEF_SEL(mutableBytes, + "mutableBytes"); + _NS_PRIVATE_DEF_SEL(name, + "name"); + _NS_PRIVATE_DEF_SEL(nextObject, + "nextObject"); + _NS_PRIVATE_DEF_SEL(numberWithBool_, + "numberWithBool:"); + _NS_PRIVATE_DEF_SEL(numberWithChar_, + "numberWithChar:"); + _NS_PRIVATE_DEF_SEL(numberWithDouble_, + "numberWithDouble:"); + _NS_PRIVATE_DEF_SEL(numberWithFloat_, + "numberWithFloat:"); + _NS_PRIVATE_DEF_SEL(numberWithInt_, + "numberWithInt:"); + _NS_PRIVATE_DEF_SEL(numberWithLong_, + "numberWithLong:"); + _NS_PRIVATE_DEF_SEL(numberWithLongLong_, + "numberWithLongLong:"); + _NS_PRIVATE_DEF_SEL(numberWithShort_, + "numberWithShort:"); + _NS_PRIVATE_DEF_SEL(numberWithUnsignedChar_, + "numberWithUnsignedChar:"); + _NS_PRIVATE_DEF_SEL(numberWithUnsignedInt_, + "numberWithUnsignedInt:"); + _NS_PRIVATE_DEF_SEL(numberWithUnsignedLong_, + "numberWithUnsignedLong:"); + _NS_PRIVATE_DEF_SEL(numberWithUnsignedLongLong_, + "numberWithUnsignedLongLong:"); + _NS_PRIVATE_DEF_SEL(numberWithUnsignedShort_, + "numberWithUnsignedShort:"); + _NS_PRIVATE_DEF_SEL(objCType, + "objCType"); + _NS_PRIVATE_DEF_SEL(object, + "object"); + _NS_PRIVATE_DEF_SEL(objectAtIndex_, + "objectAtIndex:"); + _NS_PRIVATE_DEF_SEL(objectEnumerator, + "objectEnumerator"); + _NS_PRIVATE_DEF_SEL(objectForInfoDictionaryKey_, + "objectForInfoDictionaryKey:"); + _NS_PRIVATE_DEF_SEL(objectForKey_, + "objectForKey:"); + _NS_PRIVATE_DEF_SEL(operatingSystem, + "operatingSystem"); + _NS_PRIVATE_DEF_SEL(operatingSystemVersion, + "operatingSystemVersion"); + _NS_PRIVATE_DEF_SEL(operatingSystemVersionString, + "operatingSystemVersionString"); + _NS_PRIVATE_DEF_SEL(pathForAuxiliaryExecutable_, + "pathForAuxiliaryExecutable:"); + _NS_PRIVATE_DEF_SEL(performActivityWithOptions_reason_usingBlock_, + "performActivityWithOptions:reason:usingBlock:"); + _NS_PRIVATE_DEF_SEL(performExpiringActivityWithReason_usingBlock_, + "performExpiringActivityWithReason:usingBlock:"); + _NS_PRIVATE_DEF_SEL(physicalMemory, + "physicalMemory"); + _NS_PRIVATE_DEF_SEL(pointerValue, + "pointerValue"); + _NS_PRIVATE_DEF_SEL(preflightAndReturnError_, + "preflightAndReturnError:"); + _NS_PRIVATE_DEF_SEL(privateFrameworksPath, + "privateFrameworksPath"); + _NS_PRIVATE_DEF_SEL(privateFrameworksURL, + "privateFrameworksURL"); + _NS_PRIVATE_DEF_SEL(processIdentifier, + "processIdentifier"); + _NS_PRIVATE_DEF_SEL(processInfo, + "processInfo"); + _NS_PRIVATE_DEF_SEL(processName, + "processName"); + _NS_PRIVATE_DEF_SEL(processorCount, + "processorCount"); + _NS_PRIVATE_DEF_SEL(rangeOfString_options_, + "rangeOfString:options:"); + _NS_PRIVATE_DEF_SEL(release, + "release"); + _NS_PRIVATE_DEF_SEL(removeObserver_, + "removeObserver:"); + _NS_PRIVATE_DEF_SEL(resourcePath, + "resourcePath"); + _NS_PRIVATE_DEF_SEL(resourceURL, + "resourceURL"); + _NS_PRIVATE_DEF_SEL(respondsToSelector_, + "respondsToSelector:"); + _NS_PRIVATE_DEF_SEL(retain, + "retain"); + _NS_PRIVATE_DEF_SEL(retainCount, + "retainCount"); + _NS_PRIVATE_DEF_SEL(setAutomaticTerminationSupportEnabled_, + "setAutomaticTerminationSupportEnabled:"); + _NS_PRIVATE_DEF_SEL(setProcessName_, + "setProcessName:"); + _NS_PRIVATE_DEF_SEL(sharedFrameworksPath, + "sharedFrameworksPath"); + _NS_PRIVATE_DEF_SEL(sharedFrameworksURL, + "sharedFrameworksURL"); + _NS_PRIVATE_DEF_SEL(sharedSupportPath, + "sharedSupportPath"); + _NS_PRIVATE_DEF_SEL(sharedSupportURL, + "sharedSupportURL"); + _NS_PRIVATE_DEF_SEL(shortValue, + "shortValue"); + _NS_PRIVATE_DEF_SEL(showPools, + "showPools"); + _NS_PRIVATE_DEF_SEL(signal, + "signal"); + _NS_PRIVATE_DEF_SEL(string, + "string"); + _NS_PRIVATE_DEF_SEL(stringValue, + "stringValue"); + _NS_PRIVATE_DEF_SEL(stringWithString_, + "stringWithString:"); + _NS_PRIVATE_DEF_SEL(stringWithCString_encoding_, + "stringWithCString:encoding:"); + _NS_PRIVATE_DEF_SEL(stringByAppendingString_, + "stringByAppendingString:"); + _NS_PRIVATE_DEF_SEL(systemUptime, + "systemUptime"); + _NS_PRIVATE_DEF_SEL(thermalState, + "thermalState"); + _NS_PRIVATE_DEF_SEL(unload, + "unload"); + _NS_PRIVATE_DEF_SEL(unlock, + "unlock"); + _NS_PRIVATE_DEF_SEL(unsignedCharValue, + "unsignedCharValue"); + _NS_PRIVATE_DEF_SEL(unsignedIntegerValue, + "unsignedIntegerValue"); + _NS_PRIVATE_DEF_SEL(unsignedIntValue, + "unsignedIntValue"); + _NS_PRIVATE_DEF_SEL(unsignedLongValue, + "unsignedLongValue"); + _NS_PRIVATE_DEF_SEL(unsignedLongLongValue, + "unsignedLongLongValue"); + _NS_PRIVATE_DEF_SEL(unsignedShortValue, + "unsignedShortValue"); + _NS_PRIVATE_DEF_SEL(URLForAuxiliaryExecutable_, + "URLForAuxiliaryExecutable:"); + _NS_PRIVATE_DEF_SEL(userInfo, + "userInfo"); + _NS_PRIVATE_DEF_SEL(userName, + "userName"); + _NS_PRIVATE_DEF_SEL(UTF8String, + "UTF8String"); + _NS_PRIVATE_DEF_SEL(valueWithBytes_objCType_, + "valueWithBytes:objCType:"); + _NS_PRIVATE_DEF_SEL(valueWithPointer_, + "valueWithPointer:"); + _NS_PRIVATE_DEF_SEL(wait, + "wait"); + _NS_PRIVATE_DEF_SEL(waitUntilDate_, + "waitUntilDate:"); + } // Class +} // Private +} // MTL + +//-------------------------------------------------------------------------------------------------------------------------------------------------------------