numba-cuda 0.22.0__cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _numba_cuda_redirector.pth +4 -0
- _numba_cuda_redirector.py +89 -0
- numba_cuda/VERSION +1 -0
- numba_cuda/__init__.py +6 -0
- numba_cuda/_version.py +11 -0
- numba_cuda/numba/cuda/__init__.py +70 -0
- numba_cuda/numba/cuda/_internal/cuda_bf16.py +16394 -0
- numba_cuda/numba/cuda/_internal/cuda_fp16.py +8112 -0
- numba_cuda/numba/cuda/api.py +580 -0
- numba_cuda/numba/cuda/api_util.py +76 -0
- numba_cuda/numba/cuda/args.py +72 -0
- numba_cuda/numba/cuda/bf16.py +397 -0
- numba_cuda/numba/cuda/cache_hints.py +287 -0
- numba_cuda/numba/cuda/cext/__init__.py +2 -0
- numba_cuda/numba/cuda/cext/_devicearray.cpp +159 -0
- numba_cuda/numba/cuda/cext/_devicearray.cpython-313-aarch64-linux-gnu.so +0 -0
- numba_cuda/numba/cuda/cext/_devicearray.h +29 -0
- numba_cuda/numba/cuda/cext/_dispatcher.cpp +1098 -0
- numba_cuda/numba/cuda/cext/_dispatcher.cpython-313-aarch64-linux-gnu.so +0 -0
- numba_cuda/numba/cuda/cext/_hashtable.cpp +532 -0
- numba_cuda/numba/cuda/cext/_hashtable.h +135 -0
- numba_cuda/numba/cuda/cext/_helperlib.c +71 -0
- numba_cuda/numba/cuda/cext/_helperlib.cpython-313-aarch64-linux-gnu.so +0 -0
- numba_cuda/numba/cuda/cext/_helpermod.c +82 -0
- numba_cuda/numba/cuda/cext/_pymodule.h +38 -0
- numba_cuda/numba/cuda/cext/_typeconv.cpp +206 -0
- numba_cuda/numba/cuda/cext/_typeconv.cpython-313-aarch64-linux-gnu.so +0 -0
- numba_cuda/numba/cuda/cext/_typeof.cpp +1159 -0
- numba_cuda/numba/cuda/cext/_typeof.h +19 -0
- numba_cuda/numba/cuda/cext/capsulethunk.h +111 -0
- numba_cuda/numba/cuda/cext/mviewbuf.c +385 -0
- numba_cuda/numba/cuda/cext/mviewbuf.cpython-313-aarch64-linux-gnu.so +0 -0
- numba_cuda/numba/cuda/cext/typeconv.cpp +212 -0
- numba_cuda/numba/cuda/cext/typeconv.hpp +101 -0
- numba_cuda/numba/cuda/cg.py +67 -0
- numba_cuda/numba/cuda/cgutils.py +1294 -0
- numba_cuda/numba/cuda/cloudpickle/__init__.py +21 -0
- numba_cuda/numba/cuda/cloudpickle/cloudpickle.py +1598 -0
- numba_cuda/numba/cuda/cloudpickle/cloudpickle_fast.py +17 -0
- numba_cuda/numba/cuda/codegen.py +541 -0
- numba_cuda/numba/cuda/compiler.py +1396 -0
- numba_cuda/numba/cuda/core/analysis.py +758 -0
- numba_cuda/numba/cuda/core/annotations/__init__.py +0 -0
- numba_cuda/numba/cuda/core/annotations/pretty_annotate.py +288 -0
- numba_cuda/numba/cuda/core/annotations/type_annotations.py +305 -0
- numba_cuda/numba/cuda/core/base.py +1332 -0
- numba_cuda/numba/cuda/core/boxing.py +1411 -0
- numba_cuda/numba/cuda/core/bytecode.py +728 -0
- numba_cuda/numba/cuda/core/byteflow.py +2346 -0
- numba_cuda/numba/cuda/core/caching.py +744 -0
- numba_cuda/numba/cuda/core/callconv.py +392 -0
- numba_cuda/numba/cuda/core/codegen.py +171 -0
- numba_cuda/numba/cuda/core/compiler.py +199 -0
- numba_cuda/numba/cuda/core/compiler_lock.py +85 -0
- numba_cuda/numba/cuda/core/compiler_machinery.py +497 -0
- numba_cuda/numba/cuda/core/config.py +650 -0
- numba_cuda/numba/cuda/core/consts.py +124 -0
- numba_cuda/numba/cuda/core/controlflow.py +989 -0
- numba_cuda/numba/cuda/core/entrypoints.py +57 -0
- numba_cuda/numba/cuda/core/environment.py +66 -0
- numba_cuda/numba/cuda/core/errors.py +917 -0
- numba_cuda/numba/cuda/core/event.py +511 -0
- numba_cuda/numba/cuda/core/funcdesc.py +330 -0
- numba_cuda/numba/cuda/core/generators.py +387 -0
- numba_cuda/numba/cuda/core/imputils.py +509 -0
- numba_cuda/numba/cuda/core/inline_closurecall.py +1787 -0
- numba_cuda/numba/cuda/core/interpreter.py +3617 -0
- numba_cuda/numba/cuda/core/ir.py +1812 -0
- numba_cuda/numba/cuda/core/ir_utils.py +2638 -0
- numba_cuda/numba/cuda/core/optional.py +129 -0
- numba_cuda/numba/cuda/core/options.py +262 -0
- numba_cuda/numba/cuda/core/postproc.py +249 -0
- numba_cuda/numba/cuda/core/pythonapi.py +1859 -0
- numba_cuda/numba/cuda/core/registry.py +46 -0
- numba_cuda/numba/cuda/core/removerefctpass.py +123 -0
- numba_cuda/numba/cuda/core/rewrites/__init__.py +26 -0
- numba_cuda/numba/cuda/core/rewrites/ir_print.py +91 -0
- numba_cuda/numba/cuda/core/rewrites/registry.py +104 -0
- numba_cuda/numba/cuda/core/rewrites/static_binop.py +41 -0
- numba_cuda/numba/cuda/core/rewrites/static_getitem.py +189 -0
- numba_cuda/numba/cuda/core/rewrites/static_raise.py +100 -0
- numba_cuda/numba/cuda/core/sigutils.py +68 -0
- numba_cuda/numba/cuda/core/ssa.py +498 -0
- numba_cuda/numba/cuda/core/targetconfig.py +330 -0
- numba_cuda/numba/cuda/core/tracing.py +231 -0
- numba_cuda/numba/cuda/core/transforms.py +956 -0
- numba_cuda/numba/cuda/core/typed_passes.py +867 -0
- numba_cuda/numba/cuda/core/typeinfer.py +1950 -0
- numba_cuda/numba/cuda/core/unsafe/__init__.py +0 -0
- numba_cuda/numba/cuda/core/unsafe/bytes.py +67 -0
- numba_cuda/numba/cuda/core/unsafe/eh.py +67 -0
- numba_cuda/numba/cuda/core/unsafe/refcount.py +98 -0
- numba_cuda/numba/cuda/core/untyped_passes.py +1979 -0
- numba_cuda/numba/cuda/cpython/builtins.py +1153 -0
- numba_cuda/numba/cuda/cpython/charseq.py +1218 -0
- numba_cuda/numba/cuda/cpython/cmathimpl.py +560 -0
- numba_cuda/numba/cuda/cpython/enumimpl.py +103 -0
- numba_cuda/numba/cuda/cpython/iterators.py +167 -0
- numba_cuda/numba/cuda/cpython/listobj.py +1326 -0
- numba_cuda/numba/cuda/cpython/mathimpl.py +499 -0
- numba_cuda/numba/cuda/cpython/numbers.py +1475 -0
- numba_cuda/numba/cuda/cpython/rangeobj.py +289 -0
- numba_cuda/numba/cuda/cpython/slicing.py +322 -0
- numba_cuda/numba/cuda/cpython/tupleobj.py +456 -0
- numba_cuda/numba/cuda/cpython/unicode.py +2865 -0
- numba_cuda/numba/cuda/cpython/unicode_support.py +1597 -0
- numba_cuda/numba/cuda/cpython/unsafe/__init__.py +0 -0
- numba_cuda/numba/cuda/cpython/unsafe/numbers.py +64 -0
- numba_cuda/numba/cuda/cpython/unsafe/tuple.py +92 -0
- numba_cuda/numba/cuda/cuda_paths.py +691 -0
- numba_cuda/numba/cuda/cudadecl.py +543 -0
- numba_cuda/numba/cuda/cudadrv/__init__.py +14 -0
- numba_cuda/numba/cuda/cudadrv/devicearray.py +954 -0
- numba_cuda/numba/cuda/cudadrv/devices.py +249 -0
- numba_cuda/numba/cuda/cudadrv/driver.py +3238 -0
- numba_cuda/numba/cuda/cudadrv/drvapi.py +435 -0
- numba_cuda/numba/cuda/cudadrv/dummyarray.py +562 -0
- numba_cuda/numba/cuda/cudadrv/enums.py +613 -0
- numba_cuda/numba/cuda/cudadrv/error.py +48 -0
- numba_cuda/numba/cuda/cudadrv/libs.py +220 -0
- numba_cuda/numba/cuda/cudadrv/linkable_code.py +184 -0
- numba_cuda/numba/cuda/cudadrv/mappings.py +14 -0
- numba_cuda/numba/cuda/cudadrv/ndarray.py +26 -0
- numba_cuda/numba/cuda/cudadrv/nvrtc.py +193 -0
- numba_cuda/numba/cuda/cudadrv/nvvm.py +756 -0
- numba_cuda/numba/cuda/cudadrv/rtapi.py +13 -0
- numba_cuda/numba/cuda/cudadrv/runtime.py +34 -0
- numba_cuda/numba/cuda/cudaimpl.py +983 -0
- numba_cuda/numba/cuda/cudamath.py +149 -0
- numba_cuda/numba/cuda/datamodel/__init__.py +7 -0
- numba_cuda/numba/cuda/datamodel/cuda_manager.py +66 -0
- numba_cuda/numba/cuda/datamodel/cuda_models.py +1446 -0
- numba_cuda/numba/cuda/datamodel/cuda_packer.py +224 -0
- numba_cuda/numba/cuda/datamodel/cuda_registry.py +22 -0
- numba_cuda/numba/cuda/datamodel/cuda_testing.py +153 -0
- numba_cuda/numba/cuda/datamodel/manager.py +11 -0
- numba_cuda/numba/cuda/datamodel/models.py +9 -0
- numba_cuda/numba/cuda/datamodel/packer.py +9 -0
- numba_cuda/numba/cuda/datamodel/registry.py +11 -0
- numba_cuda/numba/cuda/datamodel/testing.py +11 -0
- numba_cuda/numba/cuda/debuginfo.py +997 -0
- numba_cuda/numba/cuda/decorators.py +294 -0
- numba_cuda/numba/cuda/descriptor.py +35 -0
- numba_cuda/numba/cuda/device_init.py +155 -0
- numba_cuda/numba/cuda/deviceufunc.py +1021 -0
- numba_cuda/numba/cuda/dispatcher.py +2463 -0
- numba_cuda/numba/cuda/errors.py +72 -0
- numba_cuda/numba/cuda/extending.py +697 -0
- numba_cuda/numba/cuda/flags.py +178 -0
- numba_cuda/numba/cuda/fp16.py +357 -0
- numba_cuda/numba/cuda/include/12/cuda_bf16.h +5118 -0
- numba_cuda/numba/cuda/include/12/cuda_bf16.hpp +3865 -0
- numba_cuda/numba/cuda/include/12/cuda_fp16.h +5363 -0
- numba_cuda/numba/cuda/include/12/cuda_fp16.hpp +3483 -0
- numba_cuda/numba/cuda/include/13/cuda_bf16.h +5118 -0
- numba_cuda/numba/cuda/include/13/cuda_bf16.hpp +3865 -0
- numba_cuda/numba/cuda/include/13/cuda_fp16.h +5363 -0
- numba_cuda/numba/cuda/include/13/cuda_fp16.hpp +3483 -0
- numba_cuda/numba/cuda/initialize.py +24 -0
- numba_cuda/numba/cuda/intrinsics.py +531 -0
- numba_cuda/numba/cuda/itanium_mangler.py +214 -0
- numba_cuda/numba/cuda/kernels/__init__.py +2 -0
- numba_cuda/numba/cuda/kernels/reduction.py +265 -0
- numba_cuda/numba/cuda/kernels/transpose.py +65 -0
- numba_cuda/numba/cuda/libdevice.py +3386 -0
- numba_cuda/numba/cuda/libdevicedecl.py +20 -0
- numba_cuda/numba/cuda/libdevicefuncs.py +1060 -0
- numba_cuda/numba/cuda/libdeviceimpl.py +88 -0
- numba_cuda/numba/cuda/locks.py +19 -0
- numba_cuda/numba/cuda/lowering.py +1980 -0
- numba_cuda/numba/cuda/mathimpl.py +374 -0
- numba_cuda/numba/cuda/memory_management/__init__.py +4 -0
- numba_cuda/numba/cuda/memory_management/memsys.cu +99 -0
- numba_cuda/numba/cuda/memory_management/memsys.cuh +22 -0
- numba_cuda/numba/cuda/memory_management/nrt.cu +212 -0
- numba_cuda/numba/cuda/memory_management/nrt.cuh +48 -0
- numba_cuda/numba/cuda/memory_management/nrt.py +390 -0
- numba_cuda/numba/cuda/memory_management/nrt_context.py +438 -0
- numba_cuda/numba/cuda/misc/appdirs.py +594 -0
- numba_cuda/numba/cuda/misc/cffiimpl.py +24 -0
- numba_cuda/numba/cuda/misc/coverage_support.py +43 -0
- numba_cuda/numba/cuda/misc/dump_style.py +41 -0
- numba_cuda/numba/cuda/misc/findlib.py +75 -0
- numba_cuda/numba/cuda/misc/firstlinefinder.py +96 -0
- numba_cuda/numba/cuda/misc/gdb_hook.py +240 -0
- numba_cuda/numba/cuda/misc/literal.py +28 -0
- numba_cuda/numba/cuda/misc/llvm_pass_timings.py +412 -0
- numba_cuda/numba/cuda/misc/special.py +94 -0
- numba_cuda/numba/cuda/models.py +56 -0
- numba_cuda/numba/cuda/np/arraymath.py +5130 -0
- numba_cuda/numba/cuda/np/arrayobj.py +7635 -0
- numba_cuda/numba/cuda/np/extensions.py +11 -0
- numba_cuda/numba/cuda/np/linalg.py +3087 -0
- numba_cuda/numba/cuda/np/math/__init__.py +0 -0
- numba_cuda/numba/cuda/np/math/cmathimpl.py +558 -0
- numba_cuda/numba/cuda/np/math/mathimpl.py +487 -0
- numba_cuda/numba/cuda/np/math/numbers.py +1461 -0
- numba_cuda/numba/cuda/np/npdatetime.py +969 -0
- numba_cuda/numba/cuda/np/npdatetime_helpers.py +217 -0
- numba_cuda/numba/cuda/np/npyfuncs.py +1808 -0
- numba_cuda/numba/cuda/np/npyimpl.py +1027 -0
- numba_cuda/numba/cuda/np/numpy_support.py +798 -0
- numba_cuda/numba/cuda/np/polynomial/__init__.py +4 -0
- numba_cuda/numba/cuda/np/polynomial/polynomial_core.py +242 -0
- numba_cuda/numba/cuda/np/polynomial/polynomial_functions.py +380 -0
- numba_cuda/numba/cuda/np/ufunc/__init__.py +4 -0
- numba_cuda/numba/cuda/np/ufunc/decorators.py +203 -0
- numba_cuda/numba/cuda/np/ufunc/sigparse.py +68 -0
- numba_cuda/numba/cuda/np/ufunc/ufuncbuilder.py +65 -0
- numba_cuda/numba/cuda/np/ufunc_db.py +1282 -0
- numba_cuda/numba/cuda/np/unsafe/__init__.py +0 -0
- numba_cuda/numba/cuda/np/unsafe/ndarray.py +84 -0
- numba_cuda/numba/cuda/nvvmutils.py +254 -0
- numba_cuda/numba/cuda/printimpl.py +126 -0
- numba_cuda/numba/cuda/random.py +308 -0
- numba_cuda/numba/cuda/reshape_funcs.cu +156 -0
- numba_cuda/numba/cuda/serialize.py +267 -0
- numba_cuda/numba/cuda/simulator/__init__.py +63 -0
- numba_cuda/numba/cuda/simulator/_internal/__init__.py +4 -0
- numba_cuda/numba/cuda/simulator/_internal/cuda_bf16.py +2 -0
- numba_cuda/numba/cuda/simulator/api.py +179 -0
- numba_cuda/numba/cuda/simulator/bf16.py +4 -0
- numba_cuda/numba/cuda/simulator/compiler.py +38 -0
- numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +11 -0
- numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +462 -0
- numba_cuda/numba/cuda/simulator/cudadrv/devices.py +122 -0
- numba_cuda/numba/cuda/simulator/cudadrv/driver.py +66 -0
- numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +7 -0
- numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +7 -0
- numba_cuda/numba/cuda/simulator/cudadrv/error.py +10 -0
- numba_cuda/numba/cuda/simulator/cudadrv/libs.py +10 -0
- numba_cuda/numba/cuda/simulator/cudadrv/linkable_code.py +61 -0
- numba_cuda/numba/cuda/simulator/cudadrv/nvrtc.py +11 -0
- numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +32 -0
- numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +22 -0
- numba_cuda/numba/cuda/simulator/dispatcher.py +11 -0
- numba_cuda/numba/cuda/simulator/kernel.py +320 -0
- numba_cuda/numba/cuda/simulator/kernelapi.py +509 -0
- numba_cuda/numba/cuda/simulator/memory_management/__init__.py +4 -0
- numba_cuda/numba/cuda/simulator/memory_management/nrt.py +21 -0
- numba_cuda/numba/cuda/simulator/reduction.py +19 -0
- numba_cuda/numba/cuda/simulator/tests/support.py +4 -0
- numba_cuda/numba/cuda/simulator/vector_types.py +65 -0
- numba_cuda/numba/cuda/simulator_init.py +18 -0
- numba_cuda/numba/cuda/stubs.py +624 -0
- numba_cuda/numba/cuda/target.py +505 -0
- numba_cuda/numba/cuda/testing.py +347 -0
- numba_cuda/numba/cuda/tests/__init__.py +62 -0
- numba_cuda/numba/cuda/tests/benchmarks/__init__.py +0 -0
- numba_cuda/numba/cuda/tests/benchmarks/test_kernel_launch.py +119 -0
- numba_cuda/numba/cuda/tests/cloudpickle_main_class.py +9 -0
- numba_cuda/numba/cuda/tests/core/serialize_usecases.py +113 -0
- numba_cuda/numba/cuda/tests/core/test_itanium_mangler.py +83 -0
- numba_cuda/numba/cuda/tests/core/test_serialize.py +371 -0
- numba_cuda/numba/cuda/tests/cudadrv/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +147 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +161 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +397 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +24 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +180 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +313 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +191 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +621 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +247 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +100 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +200 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_events.py +53 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +72 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_init.py +138 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +43 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +15 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_linkable_code.py +58 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +348 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +128 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +301 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +174 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_nvrtc.py +28 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +185 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +39 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +23 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +38 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +48 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +44 -0
- numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +127 -0
- numba_cuda/numba/cuda/tests/cudapy/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +231 -0
- numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +50 -0
- numba_cuda/numba/cuda/tests/cudapy/cg_cache_usecases.py +36 -0
- numba_cuda/numba/cuda/tests/cudapy/complex_usecases.py +116 -0
- numba_cuda/numba/cuda/tests/cudapy/enum_usecases.py +59 -0
- numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +62 -0
- numba_cuda/numba/cuda/tests/cudapy/jitlink.ptx +28 -0
- numba_cuda/numba/cuda/tests/cudapy/overload_usecases.py +33 -0
- numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +104 -0
- numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +47 -0
- numba_cuda/numba/cuda/tests/cudapy/test_analysis.py +1122 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array.py +344 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_alignment.py +268 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +203 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +63 -0
- numba_cuda/numba/cuda/tests/cudapy/test_array_reductions.py +360 -0
- numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1815 -0
- numba_cuda/numba/cuda/tests/cudapy/test_bfloat16.py +599 -0
- numba_cuda/numba/cuda/tests/cudapy/test_bfloat16_bindings.py +377 -0
- numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +160 -0
- numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +27 -0
- numba_cuda/numba/cuda/tests/cudapy/test_byteflow.py +98 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cache_hints.py +210 -0
- numba_cuda/numba/cuda/tests/cudapy/test_caching.py +683 -0
- numba_cuda/numba/cuda/tests/cudapy/test_casting.py +265 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +42 -0
- numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +718 -0
- numba_cuda/numba/cuda/tests/cudapy/test_complex.py +370 -0
- numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +23 -0
- numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +142 -0
- numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +178 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +193 -0
- numba_cuda/numba/cuda/tests/cudapy/test_copy_propagate.py +131 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +438 -0
- numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +94 -0
- numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +101 -0
- numba_cuda/numba/cuda/tests/cudapy/test_debug.py +105 -0
- numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +978 -0
- numba_cuda/numba/cuda/tests/cudapy/test_debuginfo_types.py +476 -0
- numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +500 -0
- numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +820 -0
- numba_cuda/numba/cuda/tests/cudapy/test_enums.py +152 -0
- numba_cuda/numba/cuda/tests/cudapy/test_errors.py +111 -0
- numba_cuda/numba/cuda/tests/cudapy/test_exception.py +170 -0
- numba_cuda/numba/cuda/tests/cudapy/test_extending.py +1088 -0
- numba_cuda/numba/cuda/tests/cudapy/test_extending_types.py +71 -0
- numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +265 -0
- numba_cuda/numba/cuda/tests/cudapy/test_flow_control.py +1433 -0
- numba_cuda/numba/cuda/tests/cudapy/test_forall.py +57 -0
- numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +34 -0
- numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +69 -0
- numba_cuda/numba/cuda/tests/cudapy/test_globals.py +62 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +474 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +167 -0
- numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +92 -0
- numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +39 -0
- numba_cuda/numba/cuda/tests/cudapy/test_inline.py +170 -0
- numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +255 -0
- numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +1219 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +263 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ir.py +598 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py +276 -0
- numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +101 -0
- numba_cuda/numba/cuda/tests/cudapy/test_lang.py +68 -0
- numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +123 -0
- numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +194 -0
- numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +220 -0
- numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +173 -0
- numba_cuda/numba/cuda/tests/cudapy/test_make_function_to_jit_function.py +364 -0
- numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +47 -0
- numba_cuda/numba/cuda/tests/cudapy/test_math.py +842 -0
- numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +76 -0
- numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +78 -0
- numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +25 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +145 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +39 -0
- numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +82 -0
- numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +53 -0
- numba_cuda/numba/cuda/tests/cudapy/test_operator.py +504 -0
- numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +93 -0
- numba_cuda/numba/cuda/tests/cudapy/test_overload.py +402 -0
- numba_cuda/numba/cuda/tests/cudapy/test_powi.py +128 -0
- numba_cuda/numba/cuda/tests/cudapy/test_print.py +193 -0
- numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +37 -0
- numba_cuda/numba/cuda/tests/cudapy/test_random.py +117 -0
- numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +614 -0
- numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +130 -0
- numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +94 -0
- numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +83 -0
- numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +86 -0
- numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +40 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sm.py +457 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +233 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ssa.py +454 -0
- numba_cuda/numba/cuda/tests/cudapy/test_stream_api.py +56 -0
- numba_cuda/numba/cuda/tests/cudapy/test_sync.py +277 -0
- numba_cuda/numba/cuda/tests/cudapy/test_tracing.py +200 -0
- numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +90 -0
- numba_cuda/numba/cuda/tests/cudapy/test_typeconv.py +333 -0
- numba_cuda/numba/cuda/tests/cudapy/test_typeinfer.py +538 -0
- numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +585 -0
- numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +42 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +485 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +312 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +23 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +183 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +40 -0
- numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +40 -0
- numba_cuda/numba/cuda/tests/cudapy/test_warning.py +206 -0
- numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +446 -0
- numba_cuda/numba/cuda/tests/cudasim/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/cudasim/support.py +9 -0
- numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +111 -0
- numba_cuda/numba/cuda/tests/data/__init__.py +2 -0
- numba_cuda/numba/cuda/tests/data/cta_barrier.cu +28 -0
- numba_cuda/numba/cuda/tests/data/cuda_include.cu +10 -0
- numba_cuda/numba/cuda/tests/data/error.cu +12 -0
- numba_cuda/numba/cuda/tests/data/include/add.cuh +8 -0
- numba_cuda/numba/cuda/tests/data/jitlink.cu +28 -0
- numba_cuda/numba/cuda/tests/data/jitlink.ptx +49 -0
- numba_cuda/numba/cuda/tests/data/warn.cu +12 -0
- numba_cuda/numba/cuda/tests/doc_examples/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +2 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +54 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/include/mul.cuh +8 -0
- numba_cuda/numba/cuda/tests/doc_examples/ffi/saxpy.cu +14 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +86 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_cpointer.py +68 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +81 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +141 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +160 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +180 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +119 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_random.py +66 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +80 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +206 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +53 -0
- numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +76 -0
- numba_cuda/numba/cuda/tests/nocuda/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +452 -0
- numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +48 -0
- numba_cuda/numba/cuda/tests/nocuda/test_import.py +63 -0
- numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +252 -0
- numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +59 -0
- numba_cuda/numba/cuda/tests/nrt/__init__.py +9 -0
- numba_cuda/numba/cuda/tests/nrt/test_nrt.py +387 -0
- numba_cuda/numba/cuda/tests/nrt/test_nrt_refct.py +124 -0
- numba_cuda/numba/cuda/tests/support.py +900 -0
- numba_cuda/numba/cuda/typeconv/__init__.py +4 -0
- numba_cuda/numba/cuda/typeconv/castgraph.py +137 -0
- numba_cuda/numba/cuda/typeconv/rules.py +63 -0
- numba_cuda/numba/cuda/typeconv/typeconv.py +121 -0
- numba_cuda/numba/cuda/types/__init__.py +233 -0
- numba_cuda/numba/cuda/types/__init__.pyi +167 -0
- numba_cuda/numba/cuda/types/abstract.py +9 -0
- numba_cuda/numba/cuda/types/common.py +9 -0
- numba_cuda/numba/cuda/types/containers.py +9 -0
- numba_cuda/numba/cuda/types/cuda_abstract.py +533 -0
- numba_cuda/numba/cuda/types/cuda_common.py +110 -0
- numba_cuda/numba/cuda/types/cuda_containers.py +971 -0
- numba_cuda/numba/cuda/types/cuda_function_type.py +230 -0
- numba_cuda/numba/cuda/types/cuda_functions.py +798 -0
- numba_cuda/numba/cuda/types/cuda_iterators.py +120 -0
- numba_cuda/numba/cuda/types/cuda_misc.py +569 -0
- numba_cuda/numba/cuda/types/cuda_npytypes.py +690 -0
- numba_cuda/numba/cuda/types/cuda_scalars.py +280 -0
- numba_cuda/numba/cuda/types/ext_types.py +101 -0
- numba_cuda/numba/cuda/types/function_type.py +11 -0
- numba_cuda/numba/cuda/types/functions.py +9 -0
- numba_cuda/numba/cuda/types/iterators.py +9 -0
- numba_cuda/numba/cuda/types/misc.py +9 -0
- numba_cuda/numba/cuda/types/npytypes.py +9 -0
- numba_cuda/numba/cuda/types/scalars.py +9 -0
- numba_cuda/numba/cuda/typing/__init__.py +19 -0
- numba_cuda/numba/cuda/typing/arraydecl.py +939 -0
- numba_cuda/numba/cuda/typing/asnumbatype.py +130 -0
- numba_cuda/numba/cuda/typing/bufproto.py +70 -0
- numba_cuda/numba/cuda/typing/builtins.py +1209 -0
- numba_cuda/numba/cuda/typing/cffi_utils.py +219 -0
- numba_cuda/numba/cuda/typing/cmathdecl.py +47 -0
- numba_cuda/numba/cuda/typing/collections.py +138 -0
- numba_cuda/numba/cuda/typing/context.py +782 -0
- numba_cuda/numba/cuda/typing/ctypes_utils.py +125 -0
- numba_cuda/numba/cuda/typing/dictdecl.py +63 -0
- numba_cuda/numba/cuda/typing/enumdecl.py +74 -0
- numba_cuda/numba/cuda/typing/listdecl.py +147 -0
- numba_cuda/numba/cuda/typing/mathdecl.py +158 -0
- numba_cuda/numba/cuda/typing/npdatetime.py +322 -0
- numba_cuda/numba/cuda/typing/npydecl.py +749 -0
- numba_cuda/numba/cuda/typing/setdecl.py +115 -0
- numba_cuda/numba/cuda/typing/templates.py +1446 -0
- numba_cuda/numba/cuda/typing/typeof.py +301 -0
- numba_cuda/numba/cuda/ufuncs.py +746 -0
- numba_cuda/numba/cuda/utils.py +724 -0
- numba_cuda/numba/cuda/vector_types.py +214 -0
- numba_cuda/numba/cuda/vectorizers.py +260 -0
- numba_cuda-0.22.0.dist-info/METADATA +109 -0
- numba_cuda-0.22.0.dist-info/RECORD +487 -0
- numba_cuda-0.22.0.dist-info/WHEEL +6 -0
- numba_cuda-0.22.0.dist-info/licenses/LICENSE +26 -0
- numba_cuda-0.22.0.dist-info/licenses/LICENSE.numba +24 -0
- numba_cuda-0.22.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1812 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
3
|
+
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
import copy
|
|
6
|
+
import itertools
|
|
7
|
+
import os
|
|
8
|
+
import linecache
|
|
9
|
+
import pprint
|
|
10
|
+
import re
|
|
11
|
+
import sys
|
|
12
|
+
import operator
|
|
13
|
+
from types import FunctionType, BuiltinFunctionType
|
|
14
|
+
from functools import total_ordering
|
|
15
|
+
from io import StringIO
|
|
16
|
+
|
|
17
|
+
from numba.cuda import HAS_NUMBA
|
|
18
|
+
|
|
19
|
+
if HAS_NUMBA:
|
|
20
|
+
import numba
|
|
21
|
+
from numba.cuda.core import errors
|
|
22
|
+
from numba.cuda.core import config
|
|
23
|
+
from numba.cuda.utils import UNARY_BUILTINS_TO_OPERATORS, OPERATORS_TO_BUILTINS
|
|
24
|
+
from numba.cuda.core.errors import (
|
|
25
|
+
NotDefinedError,
|
|
26
|
+
RedefinedError,
|
|
27
|
+
VerificationError,
|
|
28
|
+
ConstantInferenceError,
|
|
29
|
+
)
|
|
30
|
+
from numba.cuda.core import consts
|
|
31
|
+
|
|
32
|
+
# terminal color markup
|
|
33
|
+
_termcolor = errors.termcolor()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Loc(object):
|
|
37
|
+
"""Source location"""
|
|
38
|
+
|
|
39
|
+
_defmatcher = re.compile(r"def\s+(\w+)")
|
|
40
|
+
|
|
41
|
+
def __init__(self, filename, line, col=None, maybe_decorator=False):
|
|
42
|
+
"""Arguments:
|
|
43
|
+
filename - name of the file
|
|
44
|
+
line - line in file
|
|
45
|
+
col - column
|
|
46
|
+
maybe_decorator - Set to True if location is likely a jit decorator
|
|
47
|
+
"""
|
|
48
|
+
self.filename = filename
|
|
49
|
+
self.line = line
|
|
50
|
+
self.col = col
|
|
51
|
+
self.lines = None # the source lines from the linecache
|
|
52
|
+
self.maybe_decorator = maybe_decorator
|
|
53
|
+
|
|
54
|
+
def __eq__(self, other):
|
|
55
|
+
# equivalence is solely based on filename, line and col
|
|
56
|
+
if type(self) is not type(other):
|
|
57
|
+
return False
|
|
58
|
+
if self.filename != other.filename:
|
|
59
|
+
return False
|
|
60
|
+
if self.line != other.line:
|
|
61
|
+
return False
|
|
62
|
+
if self.col != other.col:
|
|
63
|
+
return False
|
|
64
|
+
return True
|
|
65
|
+
|
|
66
|
+
def __ne__(self, other):
|
|
67
|
+
return not self.__eq__(other)
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def from_function_id(cls, func_id):
|
|
71
|
+
return cls(func_id.filename, func_id.firstlineno, maybe_decorator=True)
|
|
72
|
+
|
|
73
|
+
def __repr__(self):
|
|
74
|
+
return "Loc(filename=%s, line=%s, col=%s)" % (
|
|
75
|
+
self.filename,
|
|
76
|
+
self.line,
|
|
77
|
+
self.col,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def __str__(self):
|
|
81
|
+
if self.col is not None:
|
|
82
|
+
return "%s (%s:%s)" % (self.filename, self.line, self.col)
|
|
83
|
+
else:
|
|
84
|
+
return "%s (%s)" % (self.filename, self.line)
|
|
85
|
+
|
|
86
|
+
def _find_definition(self):
|
|
87
|
+
# try and find a def, go backwards from error line
|
|
88
|
+
fn_name = None
|
|
89
|
+
lines = self.get_lines()
|
|
90
|
+
for x in reversed(lines[: self.line - 1]):
|
|
91
|
+
# the strip and startswith is to handle user code with commented out
|
|
92
|
+
# 'def' or use of 'def' in a docstring.
|
|
93
|
+
if x.strip().startswith("def "):
|
|
94
|
+
fn_name = x
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
return fn_name
|
|
98
|
+
|
|
99
|
+
def _raw_function_name(self):
|
|
100
|
+
defn = self._find_definition()
|
|
101
|
+
if defn:
|
|
102
|
+
m = self._defmatcher.match(defn.strip())
|
|
103
|
+
if m:
|
|
104
|
+
return m.groups()[0]
|
|
105
|
+
# Probably exec(<string>) or REPL.
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
def get_lines(self):
|
|
109
|
+
if self.lines is None:
|
|
110
|
+
path = self._get_path()
|
|
111
|
+
# Avoid reading from dynamic string. They are most likely
|
|
112
|
+
# overridden. Problem started with Python 3.13. "<string>" seems
|
|
113
|
+
# to be something from multiprocessing.
|
|
114
|
+
lns = [] if path == "<string>" else linecache.getlines(path)
|
|
115
|
+
self.lines = lns
|
|
116
|
+
return self.lines
|
|
117
|
+
|
|
118
|
+
def _get_path(self):
|
|
119
|
+
path = None
|
|
120
|
+
try:
|
|
121
|
+
# Try to get a relative path
|
|
122
|
+
# ipython/jupyter input just returns as self.filename
|
|
123
|
+
path = os.path.relpath(self.filename)
|
|
124
|
+
except ValueError:
|
|
125
|
+
# Fallback to absolute path if error occurred in getting the
|
|
126
|
+
# relative path.
|
|
127
|
+
# This may happen on windows if the drive is different
|
|
128
|
+
path = os.path.abspath(self.filename)
|
|
129
|
+
return path
|
|
130
|
+
|
|
131
|
+
def strformat(self, nlines_up=2):
|
|
132
|
+
lines = self.get_lines()
|
|
133
|
+
|
|
134
|
+
use_line = self.line
|
|
135
|
+
|
|
136
|
+
if self.maybe_decorator:
|
|
137
|
+
# try and sort out a better `loc`, if it's suspected that this loc
|
|
138
|
+
# points at a jit decorator by virtue of
|
|
139
|
+
# `__code__.co_firstlineno`
|
|
140
|
+
|
|
141
|
+
# get lines, add a dummy entry at the start as lines count from
|
|
142
|
+
# 1 but list index counts from 0
|
|
143
|
+
tmplines = [""] + lines
|
|
144
|
+
|
|
145
|
+
if lines and use_line and "def " not in tmplines[use_line]:
|
|
146
|
+
# look forward 10 lines, unlikely anyone managed to stretch
|
|
147
|
+
# a jit call declaration over >10 lines?!
|
|
148
|
+
min_line = max(0, use_line)
|
|
149
|
+
max_line = use_line + 10
|
|
150
|
+
selected = tmplines[min_line:max_line]
|
|
151
|
+
index = 0
|
|
152
|
+
for idx, x in enumerate(selected):
|
|
153
|
+
if "def " in x:
|
|
154
|
+
index = idx
|
|
155
|
+
break
|
|
156
|
+
use_line = use_line + index
|
|
157
|
+
|
|
158
|
+
ret = [] # accumulates output
|
|
159
|
+
if lines and use_line > 0:
|
|
160
|
+
|
|
161
|
+
def count_spaces(string):
|
|
162
|
+
spaces = 0
|
|
163
|
+
for x in itertools.takewhile(str.isspace, str(string)):
|
|
164
|
+
spaces += 1
|
|
165
|
+
return spaces
|
|
166
|
+
|
|
167
|
+
# A few places in the code still use no `loc` or default to line 1
|
|
168
|
+
# this is often in places where exceptions are used for the purposes
|
|
169
|
+
# of flow control. As a result max is in use to prevent slice from
|
|
170
|
+
# `[negative: positive]`
|
|
171
|
+
selected = lines[max(0, use_line - nlines_up) : use_line]
|
|
172
|
+
|
|
173
|
+
# see if selected contains a definition
|
|
174
|
+
def_found = False
|
|
175
|
+
for x in selected:
|
|
176
|
+
if "def " in x:
|
|
177
|
+
def_found = True
|
|
178
|
+
|
|
179
|
+
# no definition found, try and find one
|
|
180
|
+
if not def_found:
|
|
181
|
+
# try and find a def, go backwards from error line
|
|
182
|
+
fn_name = None
|
|
183
|
+
for x in reversed(lines[: use_line - 1]):
|
|
184
|
+
if "def " in x:
|
|
185
|
+
fn_name = x
|
|
186
|
+
break
|
|
187
|
+
if fn_name:
|
|
188
|
+
ret.append(fn_name)
|
|
189
|
+
spaces = count_spaces(x)
|
|
190
|
+
ret.append(" " * (4 + spaces) + "<source elided>\n")
|
|
191
|
+
|
|
192
|
+
if selected:
|
|
193
|
+
ret.extend(selected[:-1])
|
|
194
|
+
ret.append(_termcolor.highlight(selected[-1]))
|
|
195
|
+
|
|
196
|
+
# point at the problem with a caret
|
|
197
|
+
spaces = count_spaces(selected[-1])
|
|
198
|
+
ret.append(" " * (spaces) + _termcolor.indicate("^"))
|
|
199
|
+
|
|
200
|
+
# if in the REPL source may not be available
|
|
201
|
+
if not ret:
|
|
202
|
+
if not lines:
|
|
203
|
+
ret = "<source missing, REPL/exec in use?>"
|
|
204
|
+
elif use_line <= 0:
|
|
205
|
+
ret = "<source line number missing>"
|
|
206
|
+
|
|
207
|
+
err = _termcolor.filename('\nFile "%s", line %d:') + "\n%s"
|
|
208
|
+
tmp = err % (self._get_path(), use_line, _termcolor.code("".join(ret)))
|
|
209
|
+
return tmp
|
|
210
|
+
|
|
211
|
+
def with_lineno(self, line, col=None):
|
|
212
|
+
"""
|
|
213
|
+
Return a new Loc with this line number.
|
|
214
|
+
"""
|
|
215
|
+
return type(self)(self.filename, line, col)
|
|
216
|
+
|
|
217
|
+
def short(self):
|
|
218
|
+
"""
|
|
219
|
+
Returns a short string
|
|
220
|
+
"""
|
|
221
|
+
shortfilename = os.path.basename(self.filename)
|
|
222
|
+
return "%s:%s" % (shortfilename, self.line)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# Used for annotating errors when source location is unknown.
|
|
226
|
+
unknown_loc = Loc("unknown location", 0, 0)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@total_ordering
|
|
230
|
+
class SlotEqualityCheckMixin(object):
|
|
231
|
+
# some ir nodes are __dict__ free using __slots__ instead, this mixin
|
|
232
|
+
# should not trigger the unintended creation of __dict__.
|
|
233
|
+
__slots__ = tuple()
|
|
234
|
+
|
|
235
|
+
def __eq__(self, other):
|
|
236
|
+
if type(self) is type(other):
|
|
237
|
+
for name in self.__slots__:
|
|
238
|
+
if getattr(self, name) != getattr(other, name):
|
|
239
|
+
return False
|
|
240
|
+
else:
|
|
241
|
+
return True
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
def __le__(self, other):
|
|
245
|
+
return str(self) <= str(other)
|
|
246
|
+
|
|
247
|
+
def __hash__(self):
|
|
248
|
+
return id(self)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@total_ordering
|
|
252
|
+
class EqualityCheckMixin(object):
|
|
253
|
+
"""Mixin for basic equality checking"""
|
|
254
|
+
|
|
255
|
+
def __eq__(self, other):
|
|
256
|
+
if type(self) is type(other):
|
|
257
|
+
|
|
258
|
+
def fixup(adict):
|
|
259
|
+
bad = ("loc", "scope")
|
|
260
|
+
d = dict(adict)
|
|
261
|
+
for x in bad:
|
|
262
|
+
d.pop(x, None)
|
|
263
|
+
return d
|
|
264
|
+
|
|
265
|
+
d1 = fixup(self.__dict__)
|
|
266
|
+
d2 = fixup(other.__dict__)
|
|
267
|
+
if d1 == d2:
|
|
268
|
+
return True
|
|
269
|
+
return False
|
|
270
|
+
|
|
271
|
+
def __le__(self, other):
|
|
272
|
+
return str(self) < str(other)
|
|
273
|
+
|
|
274
|
+
def __hash__(self):
|
|
275
|
+
return id(self)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class VarMap(object):
|
|
279
|
+
def __init__(self):
|
|
280
|
+
self._con = {}
|
|
281
|
+
|
|
282
|
+
def define(self, name, var):
|
|
283
|
+
if name in self._con:
|
|
284
|
+
raise RedefinedError(name)
|
|
285
|
+
else:
|
|
286
|
+
self._con[name] = var
|
|
287
|
+
|
|
288
|
+
def get(self, name):
|
|
289
|
+
try:
|
|
290
|
+
return self._con[name]
|
|
291
|
+
except KeyError:
|
|
292
|
+
raise NotDefinedError(name)
|
|
293
|
+
|
|
294
|
+
def __contains__(self, name):
|
|
295
|
+
return name in self._con
|
|
296
|
+
|
|
297
|
+
def __len__(self):
|
|
298
|
+
return len(self._con)
|
|
299
|
+
|
|
300
|
+
def __repr__(self):
|
|
301
|
+
return pprint.pformat(self._con)
|
|
302
|
+
|
|
303
|
+
def __hash__(self):
|
|
304
|
+
return hash(self.name)
|
|
305
|
+
|
|
306
|
+
def __iter__(self):
|
|
307
|
+
return self._con.iterkeys()
|
|
308
|
+
|
|
309
|
+
def __eq__(self, other):
|
|
310
|
+
if type(self) is type(other):
|
|
311
|
+
# check keys only, else __eq__ ref cycles, scope -> varmap -> var
|
|
312
|
+
return self._con.keys() == other._con.keys()
|
|
313
|
+
return False
|
|
314
|
+
|
|
315
|
+
def __ne__(self, other):
|
|
316
|
+
return not self.__eq__(other)
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
class AbstractRHS(object):
|
|
320
|
+
"""Abstract base class for anything that can be the RHS of an assignment.
|
|
321
|
+
This class **does not** define any methods.
|
|
322
|
+
"""
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class Inst(EqualityCheckMixin, AbstractRHS):
|
|
326
|
+
"""
|
|
327
|
+
Base class for all IR instructions.
|
|
328
|
+
"""
|
|
329
|
+
|
|
330
|
+
def list_vars(self):
|
|
331
|
+
"""
|
|
332
|
+
List the variables used (read or written) by the instruction.
|
|
333
|
+
"""
|
|
334
|
+
raise NotImplementedError
|
|
335
|
+
|
|
336
|
+
def _rec_list_vars(self, val):
|
|
337
|
+
"""
|
|
338
|
+
A recursive helper used to implement list_vars() in subclasses.
|
|
339
|
+
"""
|
|
340
|
+
if isinstance(val, Var):
|
|
341
|
+
return [val]
|
|
342
|
+
elif isinstance(val, Inst):
|
|
343
|
+
return val.list_vars()
|
|
344
|
+
elif isinstance(val, (list, tuple)):
|
|
345
|
+
lst = []
|
|
346
|
+
for v in val:
|
|
347
|
+
lst.extend(self._rec_list_vars(v))
|
|
348
|
+
return lst
|
|
349
|
+
elif isinstance(val, dict):
|
|
350
|
+
lst = []
|
|
351
|
+
for v in val.values():
|
|
352
|
+
lst.extend(self._rec_list_vars(v))
|
|
353
|
+
return lst
|
|
354
|
+
else:
|
|
355
|
+
return []
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class Stmt(Inst):
|
|
359
|
+
"""
|
|
360
|
+
Base class for IR statements (instructions which can appear on their
|
|
361
|
+
own in a Block).
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
# Whether this statement ends its basic block (i.e. it will either jump
|
|
365
|
+
# to another block or exit the function).
|
|
366
|
+
is_terminator = False
|
|
367
|
+
# Whether this statement exits the function.
|
|
368
|
+
is_exit = False
|
|
369
|
+
|
|
370
|
+
def list_vars(self):
|
|
371
|
+
return self._rec_list_vars(self.__dict__)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class Terminator(Stmt):
|
|
375
|
+
"""
|
|
376
|
+
IR statements that are terminators: the last statement in a block.
|
|
377
|
+
A terminator must either:
|
|
378
|
+
- exit the function
|
|
379
|
+
- jump to a block
|
|
380
|
+
|
|
381
|
+
All subclass of Terminator must override `.get_targets()` to return a list
|
|
382
|
+
of jump targets.
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
is_terminator = True
|
|
386
|
+
|
|
387
|
+
def get_targets(self):
|
|
388
|
+
raise NotImplementedError(type(self))
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
class Expr(Inst):
|
|
392
|
+
"""
|
|
393
|
+
An IR expression (an instruction which can only be part of a larger
|
|
394
|
+
statement).
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
def __init__(self, op, loc, **kws):
|
|
398
|
+
assert isinstance(op, str)
|
|
399
|
+
assert isinstance(loc, Loc)
|
|
400
|
+
self.op = op
|
|
401
|
+
self.loc = loc
|
|
402
|
+
self._kws = kws
|
|
403
|
+
|
|
404
|
+
def __getattr__(self, name):
|
|
405
|
+
if name.startswith("_"):
|
|
406
|
+
return Inst.__getattr__(self, name)
|
|
407
|
+
return self._kws[name]
|
|
408
|
+
|
|
409
|
+
def __setattr__(self, name, value):
|
|
410
|
+
if name in ("op", "loc", "_kws"):
|
|
411
|
+
self.__dict__[name] = value
|
|
412
|
+
else:
|
|
413
|
+
self._kws[name] = value
|
|
414
|
+
|
|
415
|
+
@classmethod
|
|
416
|
+
def binop(cls, fn, lhs, rhs, loc):
|
|
417
|
+
assert isinstance(fn, BuiltinFunctionType)
|
|
418
|
+
assert isinstance(lhs, Var)
|
|
419
|
+
assert isinstance(rhs, Var)
|
|
420
|
+
assert isinstance(loc, Loc)
|
|
421
|
+
op = "binop"
|
|
422
|
+
return cls(
|
|
423
|
+
op=op,
|
|
424
|
+
loc=loc,
|
|
425
|
+
fn=fn,
|
|
426
|
+
lhs=lhs,
|
|
427
|
+
rhs=rhs,
|
|
428
|
+
static_lhs=UNDEFINED,
|
|
429
|
+
static_rhs=UNDEFINED,
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
@classmethod
|
|
433
|
+
def inplace_binop(cls, fn, immutable_fn, lhs, rhs, loc):
|
|
434
|
+
assert isinstance(fn, BuiltinFunctionType)
|
|
435
|
+
assert isinstance(immutable_fn, BuiltinFunctionType)
|
|
436
|
+
assert isinstance(lhs, Var)
|
|
437
|
+
assert isinstance(rhs, Var)
|
|
438
|
+
assert isinstance(loc, Loc)
|
|
439
|
+
op = "inplace_binop"
|
|
440
|
+
return cls(
|
|
441
|
+
op=op,
|
|
442
|
+
loc=loc,
|
|
443
|
+
fn=fn,
|
|
444
|
+
immutable_fn=immutable_fn,
|
|
445
|
+
lhs=lhs,
|
|
446
|
+
rhs=rhs,
|
|
447
|
+
static_lhs=UNDEFINED,
|
|
448
|
+
static_rhs=UNDEFINED,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
@classmethod
|
|
452
|
+
def unary(cls, fn, value, loc):
|
|
453
|
+
assert isinstance(value, (str, Var, FunctionType))
|
|
454
|
+
assert isinstance(loc, Loc)
|
|
455
|
+
op = "unary"
|
|
456
|
+
fn = UNARY_BUILTINS_TO_OPERATORS.get(fn, fn)
|
|
457
|
+
return cls(op=op, loc=loc, fn=fn, value=value)
|
|
458
|
+
|
|
459
|
+
@classmethod
|
|
460
|
+
def call(
|
|
461
|
+
cls, func, args, kws, loc, vararg=None, varkwarg=None, target=None
|
|
462
|
+
):
|
|
463
|
+
assert isinstance(func, Var)
|
|
464
|
+
assert isinstance(loc, Loc)
|
|
465
|
+
op = "call"
|
|
466
|
+
return cls(
|
|
467
|
+
op=op,
|
|
468
|
+
loc=loc,
|
|
469
|
+
func=func,
|
|
470
|
+
args=args,
|
|
471
|
+
kws=kws,
|
|
472
|
+
vararg=vararg,
|
|
473
|
+
varkwarg=varkwarg,
|
|
474
|
+
target=target,
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
@classmethod
|
|
478
|
+
def build_tuple(cls, items, loc):
|
|
479
|
+
assert isinstance(loc, Loc)
|
|
480
|
+
op = "build_tuple"
|
|
481
|
+
return cls(op=op, loc=loc, items=items)
|
|
482
|
+
|
|
483
|
+
@classmethod
|
|
484
|
+
def build_list(cls, items, loc):
|
|
485
|
+
assert isinstance(loc, Loc)
|
|
486
|
+
op = "build_list"
|
|
487
|
+
return cls(op=op, loc=loc, items=items)
|
|
488
|
+
|
|
489
|
+
@classmethod
|
|
490
|
+
def build_set(cls, items, loc):
|
|
491
|
+
assert isinstance(loc, Loc)
|
|
492
|
+
op = "build_set"
|
|
493
|
+
return cls(op=op, loc=loc, items=items)
|
|
494
|
+
|
|
495
|
+
@classmethod
|
|
496
|
+
def build_map(cls, items, size, literal_value, value_indexes, loc):
|
|
497
|
+
assert isinstance(loc, Loc)
|
|
498
|
+
op = "build_map"
|
|
499
|
+
return cls(
|
|
500
|
+
op=op,
|
|
501
|
+
loc=loc,
|
|
502
|
+
items=items,
|
|
503
|
+
size=size,
|
|
504
|
+
literal_value=literal_value,
|
|
505
|
+
value_indexes=value_indexes,
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
@classmethod
|
|
509
|
+
def pair_first(cls, value, loc):
|
|
510
|
+
assert isinstance(value, Var)
|
|
511
|
+
op = "pair_first"
|
|
512
|
+
return cls(op=op, loc=loc, value=value)
|
|
513
|
+
|
|
514
|
+
@classmethod
|
|
515
|
+
def pair_second(cls, value, loc):
|
|
516
|
+
assert isinstance(value, Var)
|
|
517
|
+
assert isinstance(loc, Loc)
|
|
518
|
+
op = "pair_second"
|
|
519
|
+
return cls(op=op, loc=loc, value=value)
|
|
520
|
+
|
|
521
|
+
@classmethod
|
|
522
|
+
def getiter(cls, value, loc):
|
|
523
|
+
assert isinstance(value, Var)
|
|
524
|
+
assert isinstance(loc, Loc)
|
|
525
|
+
op = "getiter"
|
|
526
|
+
return cls(op=op, loc=loc, value=value)
|
|
527
|
+
|
|
528
|
+
@classmethod
|
|
529
|
+
def iternext(cls, value, loc):
|
|
530
|
+
assert isinstance(value, Var)
|
|
531
|
+
assert isinstance(loc, Loc)
|
|
532
|
+
op = "iternext"
|
|
533
|
+
return cls(op=op, loc=loc, value=value)
|
|
534
|
+
|
|
535
|
+
@classmethod
|
|
536
|
+
def exhaust_iter(cls, value, count, loc):
|
|
537
|
+
assert isinstance(value, Var)
|
|
538
|
+
assert isinstance(count, int)
|
|
539
|
+
assert isinstance(loc, Loc)
|
|
540
|
+
op = "exhaust_iter"
|
|
541
|
+
return cls(op=op, loc=loc, value=value, count=count)
|
|
542
|
+
|
|
543
|
+
@classmethod
|
|
544
|
+
def getattr(cls, value, attr, loc):
|
|
545
|
+
assert isinstance(value, Var)
|
|
546
|
+
assert isinstance(attr, str)
|
|
547
|
+
assert isinstance(loc, Loc)
|
|
548
|
+
op = "getattr"
|
|
549
|
+
return cls(op=op, loc=loc, value=value, attr=attr)
|
|
550
|
+
|
|
551
|
+
@classmethod
|
|
552
|
+
def getitem(cls, value, index, loc):
|
|
553
|
+
assert isinstance(value, Var)
|
|
554
|
+
assert isinstance(index, Var)
|
|
555
|
+
assert isinstance(loc, Loc)
|
|
556
|
+
op = "getitem"
|
|
557
|
+
fn = operator.getitem
|
|
558
|
+
return cls(op=op, loc=loc, value=value, index=index, fn=fn)
|
|
559
|
+
|
|
560
|
+
@classmethod
|
|
561
|
+
def typed_getitem(cls, value, dtype, index, loc):
|
|
562
|
+
assert isinstance(value, Var)
|
|
563
|
+
assert isinstance(loc, Loc)
|
|
564
|
+
op = "typed_getitem"
|
|
565
|
+
return cls(op=op, loc=loc, value=value, dtype=dtype, index=index)
|
|
566
|
+
|
|
567
|
+
@classmethod
|
|
568
|
+
def static_getitem(cls, value, index, index_var, loc):
|
|
569
|
+
assert isinstance(value, Var)
|
|
570
|
+
assert index_var is None or isinstance(index_var, Var)
|
|
571
|
+
assert isinstance(loc, Loc)
|
|
572
|
+
op = "static_getitem"
|
|
573
|
+
fn = operator.getitem
|
|
574
|
+
return cls(
|
|
575
|
+
op=op, loc=loc, value=value, index=index, index_var=index_var, fn=fn
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
@classmethod
|
|
579
|
+
def cast(cls, value, loc):
|
|
580
|
+
"""
|
|
581
|
+
A node for implicit casting at the return statement
|
|
582
|
+
"""
|
|
583
|
+
assert isinstance(value, Var)
|
|
584
|
+
assert isinstance(loc, Loc)
|
|
585
|
+
op = "cast"
|
|
586
|
+
return cls(op=op, value=value, loc=loc)
|
|
587
|
+
|
|
588
|
+
@classmethod
|
|
589
|
+
def phi(cls, loc):
|
|
590
|
+
"""Phi node"""
|
|
591
|
+
assert isinstance(loc, Loc)
|
|
592
|
+
return cls(op="phi", incoming_values=[], incoming_blocks=[], loc=loc)
|
|
593
|
+
|
|
594
|
+
@classmethod
|
|
595
|
+
def make_function(cls, name, code, closure, defaults, loc):
|
|
596
|
+
"""
|
|
597
|
+
A node for making a function object.
|
|
598
|
+
"""
|
|
599
|
+
assert isinstance(loc, Loc)
|
|
600
|
+
op = "make_function"
|
|
601
|
+
return cls(
|
|
602
|
+
op=op,
|
|
603
|
+
name=name,
|
|
604
|
+
code=code,
|
|
605
|
+
closure=closure,
|
|
606
|
+
defaults=defaults,
|
|
607
|
+
loc=loc,
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
@classmethod
|
|
611
|
+
def null(cls, loc):
|
|
612
|
+
"""
|
|
613
|
+
A node for null value.
|
|
614
|
+
|
|
615
|
+
This node is not handled by type inference. It is only added by
|
|
616
|
+
post-typing passes.
|
|
617
|
+
"""
|
|
618
|
+
assert isinstance(loc, Loc)
|
|
619
|
+
op = "null"
|
|
620
|
+
return cls(op=op, loc=loc)
|
|
621
|
+
|
|
622
|
+
@classmethod
|
|
623
|
+
def undef(cls, loc):
|
|
624
|
+
"""
|
|
625
|
+
A node for undefined value specifically from LOAD_FAST_AND_CLEAR opcode.
|
|
626
|
+
"""
|
|
627
|
+
assert isinstance(loc, Loc)
|
|
628
|
+
op = "undef"
|
|
629
|
+
return cls(op=op, loc=loc)
|
|
630
|
+
|
|
631
|
+
@classmethod
|
|
632
|
+
def dummy(cls, op, info, loc):
|
|
633
|
+
"""
|
|
634
|
+
A node for a dummy value.
|
|
635
|
+
|
|
636
|
+
This node is a place holder for carrying information through to a point
|
|
637
|
+
where it is rewritten into something valid. This node is not handled
|
|
638
|
+
by type inference or lowering. It's presence outside of the interpreter
|
|
639
|
+
renders IR as illegal.
|
|
640
|
+
"""
|
|
641
|
+
assert isinstance(loc, Loc)
|
|
642
|
+
assert isinstance(op, str)
|
|
643
|
+
return cls(op=op, info=info, loc=loc)
|
|
644
|
+
|
|
645
|
+
def __repr__(self):
|
|
646
|
+
if self.op == "call":
|
|
647
|
+
args = ", ".join(str(a) for a in self.args)
|
|
648
|
+
pres_order = (
|
|
649
|
+
self._kws.items()
|
|
650
|
+
if config.DIFF_IR == 0
|
|
651
|
+
else sorted(self._kws.items())
|
|
652
|
+
)
|
|
653
|
+
kws = ", ".join("%s=%s" % (k, v) for k, v in pres_order)
|
|
654
|
+
vararg = "*%s" % (self.vararg,) if self.vararg is not None else ""
|
|
655
|
+
arglist = ", ".join(filter(None, [args, vararg, kws]))
|
|
656
|
+
return "call %s(%s)" % (self.func, arglist)
|
|
657
|
+
elif self.op == "binop":
|
|
658
|
+
lhs, rhs = self.lhs, self.rhs
|
|
659
|
+
if self.fn == operator.contains:
|
|
660
|
+
lhs, rhs = rhs, lhs
|
|
661
|
+
fn = OPERATORS_TO_BUILTINS.get(self.fn, self.fn)
|
|
662
|
+
return "%s %s %s" % (lhs, fn, rhs)
|
|
663
|
+
else:
|
|
664
|
+
pres_order = (
|
|
665
|
+
self._kws.items()
|
|
666
|
+
if config.DIFF_IR == 0
|
|
667
|
+
else sorted(self._kws.items())
|
|
668
|
+
)
|
|
669
|
+
args = ("%s=%s" % (k, v) for k, v in pres_order)
|
|
670
|
+
return "%s(%s)" % (self.op, ", ".join(args))
|
|
671
|
+
|
|
672
|
+
def list_vars(self):
|
|
673
|
+
return self._rec_list_vars(self._kws)
|
|
674
|
+
|
|
675
|
+
def infer_constant(self):
|
|
676
|
+
raise ConstantInferenceError("%s" % self, loc=self.loc)
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
class SetItem(Stmt):
|
|
680
|
+
"""
|
|
681
|
+
target[index] = value
|
|
682
|
+
"""
|
|
683
|
+
|
|
684
|
+
def __init__(self, target, index, value, loc):
|
|
685
|
+
assert isinstance(target, Var)
|
|
686
|
+
assert isinstance(index, Var)
|
|
687
|
+
assert isinstance(value, Var)
|
|
688
|
+
assert isinstance(loc, Loc)
|
|
689
|
+
self.target = target
|
|
690
|
+
self.index = index
|
|
691
|
+
self.value = value
|
|
692
|
+
self.loc = loc
|
|
693
|
+
|
|
694
|
+
def __repr__(self):
|
|
695
|
+
return "%s[%s] = %s" % (self.target, self.index, self.value)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
class StaticSetItem(Stmt):
|
|
699
|
+
"""
|
|
700
|
+
target[constant index] = value
|
|
701
|
+
"""
|
|
702
|
+
|
|
703
|
+
def __init__(self, target, index, index_var, value, loc):
|
|
704
|
+
assert isinstance(target, Var)
|
|
705
|
+
assert not isinstance(index, Var)
|
|
706
|
+
assert isinstance(index_var, Var)
|
|
707
|
+
assert isinstance(value, Var)
|
|
708
|
+
assert isinstance(loc, Loc)
|
|
709
|
+
self.target = target
|
|
710
|
+
self.index = index
|
|
711
|
+
self.index_var = index_var
|
|
712
|
+
self.value = value
|
|
713
|
+
self.loc = loc
|
|
714
|
+
|
|
715
|
+
def __repr__(self):
|
|
716
|
+
return "%s[%r] = %s" % (self.target, self.index, self.value)
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
class DelItem(Stmt):
|
|
720
|
+
"""
|
|
721
|
+
del target[index]
|
|
722
|
+
"""
|
|
723
|
+
|
|
724
|
+
def __init__(self, target, index, loc):
|
|
725
|
+
assert isinstance(target, Var)
|
|
726
|
+
assert isinstance(index, Var)
|
|
727
|
+
assert isinstance(loc, Loc)
|
|
728
|
+
self.target = target
|
|
729
|
+
self.index = index
|
|
730
|
+
self.loc = loc
|
|
731
|
+
|
|
732
|
+
def __repr__(self):
|
|
733
|
+
return "del %s[%s]" % (self.target, self.index)
|
|
734
|
+
|
|
735
|
+
|
|
736
|
+
class SetAttr(Stmt):
|
|
737
|
+
def __init__(self, target, attr, value, loc):
|
|
738
|
+
assert isinstance(target, Var)
|
|
739
|
+
assert isinstance(attr, str)
|
|
740
|
+
assert isinstance(value, Var)
|
|
741
|
+
assert isinstance(loc, Loc)
|
|
742
|
+
self.target = target
|
|
743
|
+
self.attr = attr
|
|
744
|
+
self.value = value
|
|
745
|
+
self.loc = loc
|
|
746
|
+
|
|
747
|
+
def __repr__(self):
|
|
748
|
+
return "(%s).%s = %s" % (self.target, self.attr, self.value)
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
class DelAttr(Stmt):
|
|
752
|
+
def __init__(self, target, attr, loc):
|
|
753
|
+
assert isinstance(target, Var)
|
|
754
|
+
assert isinstance(attr, str)
|
|
755
|
+
assert isinstance(loc, Loc)
|
|
756
|
+
self.target = target
|
|
757
|
+
self.attr = attr
|
|
758
|
+
self.loc = loc
|
|
759
|
+
|
|
760
|
+
def __repr__(self):
|
|
761
|
+
return "del (%s).%s" % (self.target, self.attr)
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
class StoreMap(Stmt):
|
|
765
|
+
def __init__(self, dct, key, value, loc):
|
|
766
|
+
assert isinstance(dct, Var)
|
|
767
|
+
assert isinstance(key, Var)
|
|
768
|
+
assert isinstance(value, Var)
|
|
769
|
+
assert isinstance(loc, Loc)
|
|
770
|
+
self.dct = dct
|
|
771
|
+
self.key = key
|
|
772
|
+
self.value = value
|
|
773
|
+
self.loc = loc
|
|
774
|
+
|
|
775
|
+
def __repr__(self):
|
|
776
|
+
return "%s[%s] = %s" % (self.dct, self.key, self.value)
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
class Del(Stmt):
|
|
780
|
+
def __init__(self, value, loc):
|
|
781
|
+
assert isinstance(value, str)
|
|
782
|
+
if HAS_NUMBA:
|
|
783
|
+
assert isinstance(loc, (Loc, numba.core.ir.Loc))
|
|
784
|
+
else:
|
|
785
|
+
assert isinstance(loc, (Loc))
|
|
786
|
+
self.value = value
|
|
787
|
+
self.loc = loc
|
|
788
|
+
|
|
789
|
+
def __str__(self):
|
|
790
|
+
return "del %s" % self.value
|
|
791
|
+
|
|
792
|
+
|
|
793
|
+
class Raise(Terminator):
|
|
794
|
+
is_exit = True
|
|
795
|
+
|
|
796
|
+
def __init__(self, exception, loc):
|
|
797
|
+
assert exception is None or isinstance(exception, Var)
|
|
798
|
+
assert isinstance(loc, Loc)
|
|
799
|
+
self.exception = exception
|
|
800
|
+
self.loc = loc
|
|
801
|
+
|
|
802
|
+
def __str__(self):
|
|
803
|
+
return "raise %s" % self.exception
|
|
804
|
+
|
|
805
|
+
def get_targets(self):
|
|
806
|
+
return []
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
class StaticRaise(Terminator):
|
|
810
|
+
"""
|
|
811
|
+
Raise an exception class and arguments known at compile-time.
|
|
812
|
+
Note that if *exc_class* is None, a bare "raise" statement is implied
|
|
813
|
+
(i.e. re-raise the current exception).
|
|
814
|
+
"""
|
|
815
|
+
|
|
816
|
+
is_exit = True
|
|
817
|
+
|
|
818
|
+
def __init__(self, exc_class, exc_args, loc):
|
|
819
|
+
assert exc_class is None or isinstance(exc_class, type)
|
|
820
|
+
assert isinstance(loc, Loc)
|
|
821
|
+
assert exc_args is None or isinstance(exc_args, tuple)
|
|
822
|
+
self.exc_class = exc_class
|
|
823
|
+
self.exc_args = exc_args
|
|
824
|
+
self.loc = loc
|
|
825
|
+
|
|
826
|
+
def __str__(self):
|
|
827
|
+
if self.exc_class is None:
|
|
828
|
+
return "<static> raise"
|
|
829
|
+
elif self.exc_args is None:
|
|
830
|
+
return "<static> raise %s" % (self.exc_class,)
|
|
831
|
+
else:
|
|
832
|
+
return "<static> raise %s(%s)" % (
|
|
833
|
+
self.exc_class,
|
|
834
|
+
", ".join(map(repr, self.exc_args)),
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
def get_targets(self):
|
|
838
|
+
return []
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
class DynamicRaise(Terminator):
|
|
842
|
+
"""
|
|
843
|
+
Raise an exception class and some argument *values* unknown at compile-time.
|
|
844
|
+
Note that if *exc_class* is None, a bare "raise" statement is implied
|
|
845
|
+
(i.e. re-raise the current exception).
|
|
846
|
+
"""
|
|
847
|
+
|
|
848
|
+
is_exit = True
|
|
849
|
+
|
|
850
|
+
def __init__(self, exc_class, exc_args, loc):
|
|
851
|
+
assert exc_class is None or isinstance(exc_class, type)
|
|
852
|
+
assert isinstance(loc, Loc)
|
|
853
|
+
assert exc_args is None or isinstance(exc_args, tuple)
|
|
854
|
+
self.exc_class = exc_class
|
|
855
|
+
self.exc_args = exc_args
|
|
856
|
+
self.loc = loc
|
|
857
|
+
|
|
858
|
+
def __str__(self):
|
|
859
|
+
if self.exc_class is None:
|
|
860
|
+
return "<dynamic> raise"
|
|
861
|
+
elif self.exc_args is None:
|
|
862
|
+
return "<dynamic> raise %s" % (self.exc_class,)
|
|
863
|
+
else:
|
|
864
|
+
return "<dynamic> raise %s(%s)" % (
|
|
865
|
+
self.exc_class,
|
|
866
|
+
", ".join(map(repr, self.exc_args)),
|
|
867
|
+
)
|
|
868
|
+
|
|
869
|
+
def get_targets(self):
|
|
870
|
+
return []
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
class TryRaise(Stmt):
|
|
874
|
+
"""A raise statement inside a try-block
|
|
875
|
+
Similar to ``Raise`` but does not terminate.
|
|
876
|
+
"""
|
|
877
|
+
|
|
878
|
+
def __init__(self, exception, loc):
|
|
879
|
+
assert exception is None or isinstance(exception, Var)
|
|
880
|
+
assert isinstance(loc, Loc)
|
|
881
|
+
self.exception = exception
|
|
882
|
+
self.loc = loc
|
|
883
|
+
|
|
884
|
+
def __str__(self):
|
|
885
|
+
return "try_raise %s" % self.exception
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
class StaticTryRaise(Stmt):
|
|
889
|
+
"""A raise statement inside a try-block.
|
|
890
|
+
Similar to ``StaticRaise`` but does not terminate.
|
|
891
|
+
"""
|
|
892
|
+
|
|
893
|
+
def __init__(self, exc_class, exc_args, loc):
|
|
894
|
+
assert exc_class is None or isinstance(exc_class, type)
|
|
895
|
+
assert isinstance(loc, Loc)
|
|
896
|
+
assert exc_args is None or isinstance(exc_args, tuple)
|
|
897
|
+
self.exc_class = exc_class
|
|
898
|
+
self.exc_args = exc_args
|
|
899
|
+
self.loc = loc
|
|
900
|
+
|
|
901
|
+
def __str__(self):
|
|
902
|
+
if self.exc_class is None:
|
|
903
|
+
return "static_try_raise"
|
|
904
|
+
elif self.exc_args is None:
|
|
905
|
+
return f"static_try_raise {self.exc_class}"
|
|
906
|
+
else:
|
|
907
|
+
args = ", ".join(map(repr, self.exc_args))
|
|
908
|
+
return f"static_try_raise {self.exc_class}({args})"
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
class DynamicTryRaise(Stmt):
|
|
912
|
+
"""A raise statement inside a try-block.
|
|
913
|
+
Similar to ``DynamicRaise`` but does not terminate.
|
|
914
|
+
"""
|
|
915
|
+
|
|
916
|
+
def __init__(self, exc_class, exc_args, loc):
|
|
917
|
+
assert exc_class is None or isinstance(exc_class, type)
|
|
918
|
+
assert isinstance(loc, Loc)
|
|
919
|
+
assert exc_args is None or isinstance(exc_args, tuple)
|
|
920
|
+
self.exc_class = exc_class
|
|
921
|
+
self.exc_args = exc_args
|
|
922
|
+
self.loc = loc
|
|
923
|
+
|
|
924
|
+
def __str__(self):
|
|
925
|
+
if self.exc_class is None:
|
|
926
|
+
return "dynamic_try_raise"
|
|
927
|
+
elif self.exc_args is None:
|
|
928
|
+
return f"dynamic_try_raise {self.exc_class}"
|
|
929
|
+
else:
|
|
930
|
+
args = ", ".join(map(repr, self.exc_args))
|
|
931
|
+
return f"dynamic_try_raise {self.exc_class}({args})"
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
class Return(Terminator):
|
|
935
|
+
"""
|
|
936
|
+
Return to caller.
|
|
937
|
+
"""
|
|
938
|
+
|
|
939
|
+
is_exit = True
|
|
940
|
+
|
|
941
|
+
def __init__(self, value, loc):
|
|
942
|
+
assert isinstance(value, Var), type(value)
|
|
943
|
+
assert isinstance(loc, Loc)
|
|
944
|
+
self.value = value
|
|
945
|
+
self.loc = loc
|
|
946
|
+
|
|
947
|
+
def __str__(self):
|
|
948
|
+
return "return %s" % self.value
|
|
949
|
+
|
|
950
|
+
def get_targets(self):
|
|
951
|
+
return []
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
class Jump(Terminator):
|
|
955
|
+
"""
|
|
956
|
+
Unconditional branch.
|
|
957
|
+
"""
|
|
958
|
+
|
|
959
|
+
def __init__(self, target, loc):
|
|
960
|
+
assert isinstance(loc, Loc)
|
|
961
|
+
self.target = target
|
|
962
|
+
self.loc = loc
|
|
963
|
+
|
|
964
|
+
def __str__(self):
|
|
965
|
+
return "jump %s" % self.target
|
|
966
|
+
|
|
967
|
+
def get_targets(self):
|
|
968
|
+
return [self.target]
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
class Branch(Terminator):
|
|
972
|
+
"""
|
|
973
|
+
Conditional branch.
|
|
974
|
+
"""
|
|
975
|
+
|
|
976
|
+
def __init__(self, cond, truebr, falsebr, loc):
|
|
977
|
+
assert isinstance(cond, Var)
|
|
978
|
+
assert isinstance(loc, Loc)
|
|
979
|
+
self.cond = cond
|
|
980
|
+
self.truebr = truebr
|
|
981
|
+
self.falsebr = falsebr
|
|
982
|
+
self.loc = loc
|
|
983
|
+
|
|
984
|
+
def __str__(self):
|
|
985
|
+
return "branch %s, %s, %s" % (self.cond, self.truebr, self.falsebr)
|
|
986
|
+
|
|
987
|
+
def get_targets(self):
|
|
988
|
+
return [self.truebr, self.falsebr]
|
|
989
|
+
|
|
990
|
+
|
|
991
|
+
class Assign(Stmt):
|
|
992
|
+
"""
|
|
993
|
+
Assign to a variable.
|
|
994
|
+
"""
|
|
995
|
+
|
|
996
|
+
def __init__(self, value, target, loc):
|
|
997
|
+
assert isinstance(value, AbstractRHS)
|
|
998
|
+
assert isinstance(target, Var)
|
|
999
|
+
assert isinstance(loc, Loc)
|
|
1000
|
+
self.value = value
|
|
1001
|
+
self.target = target
|
|
1002
|
+
self.loc = loc
|
|
1003
|
+
|
|
1004
|
+
def __str__(self):
|
|
1005
|
+
return "%s = %s" % (self.target, self.value)
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
class Print(Stmt):
|
|
1009
|
+
"""
|
|
1010
|
+
Print some values.
|
|
1011
|
+
"""
|
|
1012
|
+
|
|
1013
|
+
def __init__(self, args, vararg, loc):
|
|
1014
|
+
assert all(isinstance(x, Var) for x in args)
|
|
1015
|
+
assert vararg is None or isinstance(vararg, Var)
|
|
1016
|
+
assert isinstance(loc, Loc)
|
|
1017
|
+
self.args = tuple(args)
|
|
1018
|
+
self.vararg = vararg
|
|
1019
|
+
# Constant-inferred arguments
|
|
1020
|
+
self.consts = {}
|
|
1021
|
+
self.loc = loc
|
|
1022
|
+
|
|
1023
|
+
def __str__(self):
|
|
1024
|
+
return "print(%s)" % ", ".join(str(v) for v in self.args)
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
class Yield(Inst):
|
|
1028
|
+
def __init__(self, value, loc, index):
|
|
1029
|
+
assert isinstance(value, Var)
|
|
1030
|
+
assert isinstance(loc, Loc)
|
|
1031
|
+
self.value = value
|
|
1032
|
+
self.loc = loc
|
|
1033
|
+
self.index = index
|
|
1034
|
+
|
|
1035
|
+
def __str__(self):
|
|
1036
|
+
return "yield %s" % (self.value,)
|
|
1037
|
+
|
|
1038
|
+
def list_vars(self):
|
|
1039
|
+
return [self.value]
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
class EnterWith(Stmt):
|
|
1043
|
+
"""Enter a "with" context"""
|
|
1044
|
+
|
|
1045
|
+
def __init__(self, contextmanager, begin, end, loc):
|
|
1046
|
+
"""
|
|
1047
|
+
Parameters
|
|
1048
|
+
----------
|
|
1049
|
+
contextmanager : IR value
|
|
1050
|
+
begin, end : int
|
|
1051
|
+
The beginning and the ending offset of the with-body.
|
|
1052
|
+
loc : ir.Loc instance
|
|
1053
|
+
Source location
|
|
1054
|
+
"""
|
|
1055
|
+
assert isinstance(contextmanager, Var)
|
|
1056
|
+
assert isinstance(loc, Loc)
|
|
1057
|
+
self.contextmanager = contextmanager
|
|
1058
|
+
self.begin = begin
|
|
1059
|
+
self.end = end
|
|
1060
|
+
self.loc = loc
|
|
1061
|
+
|
|
1062
|
+
def __str__(self):
|
|
1063
|
+
return "enter_with {}".format(self.contextmanager)
|
|
1064
|
+
|
|
1065
|
+
def list_vars(self):
|
|
1066
|
+
return [self.contextmanager]
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
class PopBlock(Stmt):
|
|
1070
|
+
"""Marker statement for a pop block op code"""
|
|
1071
|
+
|
|
1072
|
+
def __init__(self, loc):
|
|
1073
|
+
assert isinstance(loc, Loc)
|
|
1074
|
+
self.loc = loc
|
|
1075
|
+
|
|
1076
|
+
def __str__(self):
|
|
1077
|
+
return "pop_block"
|
|
1078
|
+
|
|
1079
|
+
|
|
1080
|
+
class Arg(EqualityCheckMixin, AbstractRHS):
|
|
1081
|
+
def __init__(self, name, index, loc):
|
|
1082
|
+
assert isinstance(name, str)
|
|
1083
|
+
assert isinstance(index, int)
|
|
1084
|
+
assert isinstance(loc, Loc)
|
|
1085
|
+
self.name = name
|
|
1086
|
+
self.index = index
|
|
1087
|
+
self.loc = loc
|
|
1088
|
+
|
|
1089
|
+
def __repr__(self):
|
|
1090
|
+
return "arg(%d, name=%s)" % (self.index, self.name)
|
|
1091
|
+
|
|
1092
|
+
def infer_constant(self):
|
|
1093
|
+
raise ConstantInferenceError("%s" % self, loc=self.loc)
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
class Const(EqualityCheckMixin, AbstractRHS):
|
|
1097
|
+
def __init__(self, value, loc, use_literal_type=True):
|
|
1098
|
+
assert isinstance(loc, Loc)
|
|
1099
|
+
self.value = value
|
|
1100
|
+
self.loc = loc
|
|
1101
|
+
# Note: need better way to tell if this is a literal or not.
|
|
1102
|
+
self.use_literal_type = use_literal_type
|
|
1103
|
+
|
|
1104
|
+
def __repr__(self):
|
|
1105
|
+
return "const(%s, %s)" % (type(self.value).__name__, self.value)
|
|
1106
|
+
|
|
1107
|
+
def infer_constant(self):
|
|
1108
|
+
return self.value
|
|
1109
|
+
|
|
1110
|
+
def __deepcopy__(self, memo):
|
|
1111
|
+
# Override to not copy constant values in code
|
|
1112
|
+
return Const(
|
|
1113
|
+
value=self.value,
|
|
1114
|
+
loc=self.loc,
|
|
1115
|
+
use_literal_type=self.use_literal_type,
|
|
1116
|
+
)
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
class Global(EqualityCheckMixin, AbstractRHS):
|
|
1120
|
+
def __init__(self, name, value, loc):
|
|
1121
|
+
assert isinstance(loc, Loc)
|
|
1122
|
+
self.name = name
|
|
1123
|
+
self.value = value
|
|
1124
|
+
self.loc = loc
|
|
1125
|
+
|
|
1126
|
+
def __str__(self):
|
|
1127
|
+
return "global(%s: %s)" % (self.name, self.value)
|
|
1128
|
+
|
|
1129
|
+
def infer_constant(self):
|
|
1130
|
+
return self.value
|
|
1131
|
+
|
|
1132
|
+
def __deepcopy__(self, memo):
|
|
1133
|
+
# don't copy value since it can fail (e.g. modules)
|
|
1134
|
+
# value is readonly and doesn't need copying
|
|
1135
|
+
return Global(self.name, self.value, copy.deepcopy(self.loc))
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
class FreeVar(EqualityCheckMixin, AbstractRHS):
|
|
1139
|
+
"""
|
|
1140
|
+
A freevar, as loaded by LOAD_DECREF.
|
|
1141
|
+
(i.e. a variable defined in an enclosing non-global scope)
|
|
1142
|
+
"""
|
|
1143
|
+
|
|
1144
|
+
def __init__(self, index, name, value, loc):
|
|
1145
|
+
assert isinstance(index, int)
|
|
1146
|
+
assert isinstance(name, str)
|
|
1147
|
+
assert isinstance(loc, Loc)
|
|
1148
|
+
# index inside __code__.co_freevars
|
|
1149
|
+
self.index = index
|
|
1150
|
+
# variable name
|
|
1151
|
+
self.name = name
|
|
1152
|
+
# frozen value
|
|
1153
|
+
self.value = value
|
|
1154
|
+
self.loc = loc
|
|
1155
|
+
|
|
1156
|
+
def __str__(self):
|
|
1157
|
+
return "freevar(%s: %s)" % (self.name, self.value)
|
|
1158
|
+
|
|
1159
|
+
def infer_constant(self):
|
|
1160
|
+
return self.value
|
|
1161
|
+
|
|
1162
|
+
def __deepcopy__(self, memo):
|
|
1163
|
+
# Override to not copy constant values in code
|
|
1164
|
+
return FreeVar(
|
|
1165
|
+
index=self.index, name=self.name, value=self.value, loc=self.loc
|
|
1166
|
+
)
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
class Var(EqualityCheckMixin, AbstractRHS):
|
|
1170
|
+
"""
|
|
1171
|
+
Attributes
|
|
1172
|
+
-----------
|
|
1173
|
+
- scope: Scope
|
|
1174
|
+
|
|
1175
|
+
- name: str
|
|
1176
|
+
|
|
1177
|
+
- loc: Loc
|
|
1178
|
+
Definition location
|
|
1179
|
+
"""
|
|
1180
|
+
|
|
1181
|
+
def __init__(self, scope, name, loc):
|
|
1182
|
+
# NOTE: Use of scope=None should be removed.
|
|
1183
|
+
assert scope is None or isinstance(scope, Scope)
|
|
1184
|
+
assert isinstance(name, str)
|
|
1185
|
+
assert isinstance(loc, Loc)
|
|
1186
|
+
self.scope = scope
|
|
1187
|
+
self.name = name
|
|
1188
|
+
self.loc = loc
|
|
1189
|
+
|
|
1190
|
+
def __repr__(self):
|
|
1191
|
+
return "Var(%s, %s)" % (self.name, self.loc.short())
|
|
1192
|
+
|
|
1193
|
+
def __str__(self):
|
|
1194
|
+
return self.name
|
|
1195
|
+
|
|
1196
|
+
@property
|
|
1197
|
+
def is_temp(self):
|
|
1198
|
+
return self.name.startswith("$")
|
|
1199
|
+
|
|
1200
|
+
@property
|
|
1201
|
+
def unversioned_name(self):
|
|
1202
|
+
"""The unversioned name of this variable, i.e. SSA renaming removed"""
|
|
1203
|
+
for k, redef_set in self.scope.var_redefinitions.items():
|
|
1204
|
+
if self.name in redef_set:
|
|
1205
|
+
return k
|
|
1206
|
+
return self.name
|
|
1207
|
+
|
|
1208
|
+
@property
|
|
1209
|
+
def versioned_names(self):
|
|
1210
|
+
"""Known versioned names for this variable, i.e. known variable names in
|
|
1211
|
+
the scope that have been formed from applying SSA to this variable
|
|
1212
|
+
"""
|
|
1213
|
+
return self.scope.get_versions_of(self.unversioned_name)
|
|
1214
|
+
|
|
1215
|
+
@property
|
|
1216
|
+
def all_names(self):
|
|
1217
|
+
"""All known versioned and unversioned names for this variable"""
|
|
1218
|
+
return self.versioned_names | {
|
|
1219
|
+
self.unversioned_name,
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
def __deepcopy__(self, memo):
|
|
1223
|
+
out = Var(copy.deepcopy(self.scope, memo), self.name, self.loc)
|
|
1224
|
+
memo[id(self)] = out
|
|
1225
|
+
return out
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
class Scope(EqualityCheckMixin):
|
|
1229
|
+
"""
|
|
1230
|
+
Attributes
|
|
1231
|
+
-----------
|
|
1232
|
+
- parent: Scope
|
|
1233
|
+
Parent scope
|
|
1234
|
+
|
|
1235
|
+
- localvars: VarMap
|
|
1236
|
+
Scope-local variable map
|
|
1237
|
+
|
|
1238
|
+
- loc: Loc
|
|
1239
|
+
Start of scope location
|
|
1240
|
+
|
|
1241
|
+
"""
|
|
1242
|
+
|
|
1243
|
+
def __init__(self, parent, loc):
|
|
1244
|
+
assert parent is None or isinstance(parent, Scope)
|
|
1245
|
+
assert isinstance(loc, Loc)
|
|
1246
|
+
self.parent = parent
|
|
1247
|
+
self.localvars = VarMap()
|
|
1248
|
+
self.loc = loc
|
|
1249
|
+
self.redefined = defaultdict(int)
|
|
1250
|
+
self.var_redefinitions = defaultdict(set)
|
|
1251
|
+
|
|
1252
|
+
def define(self, name, loc):
|
|
1253
|
+
"""
|
|
1254
|
+
Define a variable
|
|
1255
|
+
"""
|
|
1256
|
+
v = Var(scope=self, name=name, loc=loc)
|
|
1257
|
+
self.localvars.define(v.name, v)
|
|
1258
|
+
return v
|
|
1259
|
+
|
|
1260
|
+
def get(self, name):
|
|
1261
|
+
"""
|
|
1262
|
+
Refer to a variable. Returns the latest version.
|
|
1263
|
+
"""
|
|
1264
|
+
if name in self.redefined:
|
|
1265
|
+
name = "%s.%d" % (name, self.redefined[name])
|
|
1266
|
+
return self.get_exact(name)
|
|
1267
|
+
|
|
1268
|
+
def get_exact(self, name):
|
|
1269
|
+
"""
|
|
1270
|
+
Refer to a variable. The returned variable has the exact
|
|
1271
|
+
name (exact variable version).
|
|
1272
|
+
"""
|
|
1273
|
+
try:
|
|
1274
|
+
return self.localvars.get(name)
|
|
1275
|
+
except NotDefinedError:
|
|
1276
|
+
if self.has_parent:
|
|
1277
|
+
return self.parent.get(name)
|
|
1278
|
+
else:
|
|
1279
|
+
raise
|
|
1280
|
+
|
|
1281
|
+
def get_or_define(self, name, loc):
|
|
1282
|
+
if name in self.redefined:
|
|
1283
|
+
name = "%s.%d" % (name, self.redefined[name])
|
|
1284
|
+
|
|
1285
|
+
if name not in self.localvars:
|
|
1286
|
+
return self.define(name, loc)
|
|
1287
|
+
else:
|
|
1288
|
+
return self.localvars.get(name)
|
|
1289
|
+
|
|
1290
|
+
def redefine(self, name, loc, rename=True):
|
|
1291
|
+
"""
|
|
1292
|
+
Redefine if the name is already defined
|
|
1293
|
+
"""
|
|
1294
|
+
if name not in self.localvars:
|
|
1295
|
+
return self.define(name, loc)
|
|
1296
|
+
elif not rename:
|
|
1297
|
+
# Must use the same name if the variable is a cellvar, which
|
|
1298
|
+
# means it could be captured in a closure.
|
|
1299
|
+
return self.localvars.get(name)
|
|
1300
|
+
else:
|
|
1301
|
+
while True:
|
|
1302
|
+
ct = self.redefined[name]
|
|
1303
|
+
self.redefined[name] = ct + 1
|
|
1304
|
+
newname = "%s.%d" % (name, ct + 1)
|
|
1305
|
+
try:
|
|
1306
|
+
res = self.define(newname, loc)
|
|
1307
|
+
except RedefinedError:
|
|
1308
|
+
continue
|
|
1309
|
+
else:
|
|
1310
|
+
self.var_redefinitions[name].add(newname)
|
|
1311
|
+
return res
|
|
1312
|
+
|
|
1313
|
+
def get_versions_of(self, name):
|
|
1314
|
+
"""
|
|
1315
|
+
Gets all known versions of a given name
|
|
1316
|
+
"""
|
|
1317
|
+
vers = set()
|
|
1318
|
+
|
|
1319
|
+
def walk(thename):
|
|
1320
|
+
redefs = self.var_redefinitions.get(thename, None)
|
|
1321
|
+
if redefs:
|
|
1322
|
+
for v in redefs:
|
|
1323
|
+
vers.add(v)
|
|
1324
|
+
walk(v)
|
|
1325
|
+
|
|
1326
|
+
walk(name)
|
|
1327
|
+
return vers
|
|
1328
|
+
|
|
1329
|
+
def make_temp(self, loc):
|
|
1330
|
+
n = len(self.localvars)
|
|
1331
|
+
v = Var(scope=self, name="$%d" % n, loc=loc)
|
|
1332
|
+
self.localvars.define(v.name, v)
|
|
1333
|
+
return v
|
|
1334
|
+
|
|
1335
|
+
@property
|
|
1336
|
+
def has_parent(self):
|
|
1337
|
+
return self.parent is not None
|
|
1338
|
+
|
|
1339
|
+
def __repr__(self):
|
|
1340
|
+
return "Scope(has_parent=%r, num_vars=%d, %s)" % (
|
|
1341
|
+
self.has_parent,
|
|
1342
|
+
len(self.localvars),
|
|
1343
|
+
self.loc,
|
|
1344
|
+
)
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
class Block(EqualityCheckMixin):
|
|
1348
|
+
"""A code block"""
|
|
1349
|
+
|
|
1350
|
+
def __init__(self, scope, loc):
|
|
1351
|
+
if HAS_NUMBA:
|
|
1352
|
+
assert isinstance(scope, (Scope, numba.core.ir.Scope))
|
|
1353
|
+
assert isinstance(loc, (Loc, numba.core.ir.Loc))
|
|
1354
|
+
else:
|
|
1355
|
+
assert isinstance(scope, Scope)
|
|
1356
|
+
assert isinstance(loc, Loc)
|
|
1357
|
+
self.scope = scope
|
|
1358
|
+
self.body = []
|
|
1359
|
+
self.loc = loc
|
|
1360
|
+
|
|
1361
|
+
def copy(self):
|
|
1362
|
+
block = Block(self.scope, self.loc)
|
|
1363
|
+
block.body = self.body[:]
|
|
1364
|
+
return block
|
|
1365
|
+
|
|
1366
|
+
def find_exprs(self, op=None):
|
|
1367
|
+
"""
|
|
1368
|
+
Iterate over exprs of the given *op* in this block.
|
|
1369
|
+
"""
|
|
1370
|
+
for inst in self.body:
|
|
1371
|
+
if isinstance(inst, Assign):
|
|
1372
|
+
expr = inst.value
|
|
1373
|
+
if isinstance(expr, Expr):
|
|
1374
|
+
if op is None or expr.op == op:
|
|
1375
|
+
yield expr
|
|
1376
|
+
|
|
1377
|
+
def find_insts(self, cls=None):
|
|
1378
|
+
"""
|
|
1379
|
+
Iterate over insts of the given class in this block.
|
|
1380
|
+
"""
|
|
1381
|
+
for inst in self.body:
|
|
1382
|
+
if isinstance(inst, cls):
|
|
1383
|
+
yield inst
|
|
1384
|
+
|
|
1385
|
+
def find_variable_assignment(self, name):
|
|
1386
|
+
"""
|
|
1387
|
+
Returns the assignment inst associated with variable "name", None if
|
|
1388
|
+
it cannot be found.
|
|
1389
|
+
"""
|
|
1390
|
+
for x in self.find_insts(cls=Assign):
|
|
1391
|
+
if x.target.name == name:
|
|
1392
|
+
return x
|
|
1393
|
+
return None
|
|
1394
|
+
|
|
1395
|
+
def prepend(self, inst):
|
|
1396
|
+
assert isinstance(inst, Stmt)
|
|
1397
|
+
self.body.insert(0, inst)
|
|
1398
|
+
|
|
1399
|
+
def append(self, inst):
|
|
1400
|
+
assert isinstance(inst, Stmt)
|
|
1401
|
+
self.body.append(inst)
|
|
1402
|
+
|
|
1403
|
+
def remove(self, inst):
|
|
1404
|
+
assert isinstance(inst, Stmt)
|
|
1405
|
+
del self.body[self.body.index(inst)]
|
|
1406
|
+
|
|
1407
|
+
def clear(self):
|
|
1408
|
+
del self.body[:]
|
|
1409
|
+
|
|
1410
|
+
def dump(self, file=None):
|
|
1411
|
+
# Avoid early bind of sys.stdout as default value
|
|
1412
|
+
file = file or sys.stdout
|
|
1413
|
+
for inst in self.body:
|
|
1414
|
+
if hasattr(inst, "dump"):
|
|
1415
|
+
inst.dump(file)
|
|
1416
|
+
else:
|
|
1417
|
+
inst_vars = sorted(str(v) for v in inst.list_vars())
|
|
1418
|
+
print(" %-40s %s" % (inst, inst_vars), file=file)
|
|
1419
|
+
|
|
1420
|
+
@property
|
|
1421
|
+
def terminator(self):
|
|
1422
|
+
return self.body[-1]
|
|
1423
|
+
|
|
1424
|
+
@property
|
|
1425
|
+
def is_terminated(self):
|
|
1426
|
+
return self.body and self.body[-1].is_terminator
|
|
1427
|
+
|
|
1428
|
+
def verify(self):
|
|
1429
|
+
if not self.is_terminated:
|
|
1430
|
+
raise VerificationError("Missing block terminator")
|
|
1431
|
+
# Only the last instruction can be a terminator
|
|
1432
|
+
for inst in self.body[:-1]:
|
|
1433
|
+
if inst.is_terminator:
|
|
1434
|
+
raise VerificationError(
|
|
1435
|
+
"Terminator before the last instruction"
|
|
1436
|
+
)
|
|
1437
|
+
|
|
1438
|
+
def insert_after(self, stmt, other):
|
|
1439
|
+
"""
|
|
1440
|
+
Insert *stmt* after *other*.
|
|
1441
|
+
"""
|
|
1442
|
+
index = self.body.index(other)
|
|
1443
|
+
self.body.insert(index + 1, stmt)
|
|
1444
|
+
|
|
1445
|
+
def insert_before_terminator(self, stmt):
|
|
1446
|
+
assert isinstance(stmt, Stmt)
|
|
1447
|
+
assert self.is_terminated
|
|
1448
|
+
self.body.insert(-1, stmt)
|
|
1449
|
+
|
|
1450
|
+
def __repr__(self):
|
|
1451
|
+
return "<ir.Block at %s>" % (self.loc,)
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
class Loop(SlotEqualityCheckMixin):
|
|
1455
|
+
"""Describes a loop-block"""
|
|
1456
|
+
|
|
1457
|
+
__slots__ = "entry", "exit"
|
|
1458
|
+
|
|
1459
|
+
def __init__(self, entry, exit):
|
|
1460
|
+
self.entry = entry
|
|
1461
|
+
self.exit = exit
|
|
1462
|
+
|
|
1463
|
+
def __repr__(self):
|
|
1464
|
+
args = self.entry, self.exit
|
|
1465
|
+
return "Loop(entry=%s, exit=%s)" % args
|
|
1466
|
+
|
|
1467
|
+
|
|
1468
|
+
class With(SlotEqualityCheckMixin):
|
|
1469
|
+
"""Describes a with-block"""
|
|
1470
|
+
|
|
1471
|
+
__slots__ = "entry", "exit"
|
|
1472
|
+
|
|
1473
|
+
def __init__(self, entry, exit):
|
|
1474
|
+
self.entry = entry
|
|
1475
|
+
self.exit = exit
|
|
1476
|
+
|
|
1477
|
+
def __repr__(self):
|
|
1478
|
+
args = self.entry, self.exit
|
|
1479
|
+
return "With(entry=%s, exit=%s)" % args
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
class FunctionIR(object):
|
|
1483
|
+
def __init__(
|
|
1484
|
+
self,
|
|
1485
|
+
blocks,
|
|
1486
|
+
is_generator,
|
|
1487
|
+
func_id,
|
|
1488
|
+
loc,
|
|
1489
|
+
definitions,
|
|
1490
|
+
arg_count,
|
|
1491
|
+
arg_names,
|
|
1492
|
+
):
|
|
1493
|
+
self.blocks = blocks
|
|
1494
|
+
self.is_generator = is_generator
|
|
1495
|
+
self.func_id = func_id
|
|
1496
|
+
self.loc = loc
|
|
1497
|
+
self.arg_count = arg_count
|
|
1498
|
+
self.arg_names = arg_names
|
|
1499
|
+
|
|
1500
|
+
self._definitions = definitions
|
|
1501
|
+
|
|
1502
|
+
self._reset_analysis_variables()
|
|
1503
|
+
|
|
1504
|
+
def equal_ir(self, other):
|
|
1505
|
+
"""Checks that the IR contained within is equal to the IR in other.
|
|
1506
|
+
Equality is defined by being equal in fundamental structure (blocks,
|
|
1507
|
+
labels, IR node type and the order in which they are defined) and the
|
|
1508
|
+
IR nodes being equal. IR node equality essentially comes down to
|
|
1509
|
+
ensuring a node's `.__dict__` or `.__slots__` is equal, with the
|
|
1510
|
+
exception of ignoring 'loc' and 'scope' entries. The upshot is that the
|
|
1511
|
+
comparison is essentially location and scope invariant, but otherwise
|
|
1512
|
+
behaves as unsurprisingly as possible.
|
|
1513
|
+
"""
|
|
1514
|
+
if type(self) is type(other):
|
|
1515
|
+
return self.blocks == other.blocks
|
|
1516
|
+
return False
|
|
1517
|
+
|
|
1518
|
+
def diff_str(self, other):
|
|
1519
|
+
"""
|
|
1520
|
+
Compute a human readable difference in the IR, returns a formatted
|
|
1521
|
+
string ready for printing.
|
|
1522
|
+
"""
|
|
1523
|
+
msg = []
|
|
1524
|
+
for label, block in self.blocks.items():
|
|
1525
|
+
other_blk = other.blocks.get(label, None)
|
|
1526
|
+
if other_blk is not None:
|
|
1527
|
+
if block != other_blk:
|
|
1528
|
+
msg.append(("Block %s differs" % label).center(80, "-"))
|
|
1529
|
+
# see if the instructions are just a permutation
|
|
1530
|
+
block_del = [x for x in block.body if isinstance(x, Del)]
|
|
1531
|
+
oth_del = [x for x in other_blk.body if isinstance(x, Del)]
|
|
1532
|
+
if block_del != oth_del:
|
|
1533
|
+
# this is a common issue, dels are all present, but
|
|
1534
|
+
# order shuffled.
|
|
1535
|
+
if sorted(block_del) == sorted(oth_del):
|
|
1536
|
+
msg.append(
|
|
1537
|
+
(
|
|
1538
|
+
"Block %s contains the same dels but "
|
|
1539
|
+
"their order is different"
|
|
1540
|
+
)
|
|
1541
|
+
% label
|
|
1542
|
+
)
|
|
1543
|
+
if len(block.body) > len(other_blk.body):
|
|
1544
|
+
msg.append("This block contains more statements")
|
|
1545
|
+
elif len(block.body) < len(other_blk.body):
|
|
1546
|
+
msg.append("Other block contains more statements")
|
|
1547
|
+
|
|
1548
|
+
# find the indexes where they don't match
|
|
1549
|
+
tmp = []
|
|
1550
|
+
for idx, stmts in enumerate(
|
|
1551
|
+
zip(block.body, other_blk.body)
|
|
1552
|
+
):
|
|
1553
|
+
b_s, o_s = stmts
|
|
1554
|
+
if b_s != o_s:
|
|
1555
|
+
tmp.append(idx)
|
|
1556
|
+
|
|
1557
|
+
def get_pad(ablock, l):
|
|
1558
|
+
pointer = "-> "
|
|
1559
|
+
sp = len(pointer) * " "
|
|
1560
|
+
pad = []
|
|
1561
|
+
nstmt = len(ablock)
|
|
1562
|
+
for i in range(nstmt):
|
|
1563
|
+
if i in tmp:
|
|
1564
|
+
item = pointer
|
|
1565
|
+
elif i >= l:
|
|
1566
|
+
item = pointer
|
|
1567
|
+
else:
|
|
1568
|
+
item = sp
|
|
1569
|
+
pad.append(item)
|
|
1570
|
+
return pad
|
|
1571
|
+
|
|
1572
|
+
min_stmt_len = min(len(block.body), len(other_blk.body))
|
|
1573
|
+
|
|
1574
|
+
with StringIO() as buf:
|
|
1575
|
+
it = [("self", block), ("other", other_blk)]
|
|
1576
|
+
for name, _block in it:
|
|
1577
|
+
buf.truncate(0)
|
|
1578
|
+
_block.dump(file=buf)
|
|
1579
|
+
stmts = buf.getvalue().splitlines()
|
|
1580
|
+
pad = get_pad(_block.body, min_stmt_len)
|
|
1581
|
+
title = "%s: block %s" % (name, label)
|
|
1582
|
+
msg.append(title.center(80, "-"))
|
|
1583
|
+
msg.extend(
|
|
1584
|
+
[
|
|
1585
|
+
"{0}{1}".format(a, b)
|
|
1586
|
+
for a, b in zip(pad, stmts)
|
|
1587
|
+
]
|
|
1588
|
+
)
|
|
1589
|
+
if msg == []:
|
|
1590
|
+
msg.append("IR is considered equivalent.")
|
|
1591
|
+
return "\n".join(msg)
|
|
1592
|
+
|
|
1593
|
+
def _reset_analysis_variables(self):
|
|
1594
|
+
self._consts = consts.ConstantInference(self)
|
|
1595
|
+
|
|
1596
|
+
# Will be computed by PostProcessor
|
|
1597
|
+
self.generator_info = None
|
|
1598
|
+
self.variable_lifetime = None
|
|
1599
|
+
# { ir.Block: { variable names (potentially) alive at start of block } }
|
|
1600
|
+
self.block_entry_vars = {}
|
|
1601
|
+
|
|
1602
|
+
def derive(
|
|
1603
|
+
self,
|
|
1604
|
+
blocks,
|
|
1605
|
+
arg_count=None,
|
|
1606
|
+
arg_names=None,
|
|
1607
|
+
force_non_generator=False,
|
|
1608
|
+
loc=None,
|
|
1609
|
+
):
|
|
1610
|
+
"""
|
|
1611
|
+
Derive a new function IR from this one, using the given blocks,
|
|
1612
|
+
and possibly modifying the argument count and generator flag.
|
|
1613
|
+
|
|
1614
|
+
Post-processing will have to be run again on the new IR.
|
|
1615
|
+
"""
|
|
1616
|
+
firstblock = blocks[min(blocks)]
|
|
1617
|
+
|
|
1618
|
+
new_ir = copy.copy(self)
|
|
1619
|
+
new_ir.blocks = blocks
|
|
1620
|
+
new_ir.loc = firstblock.loc if loc is None else loc
|
|
1621
|
+
if force_non_generator:
|
|
1622
|
+
new_ir.is_generator = False
|
|
1623
|
+
if arg_count is not None:
|
|
1624
|
+
new_ir.arg_count = arg_count
|
|
1625
|
+
if arg_names is not None:
|
|
1626
|
+
new_ir.arg_names = arg_names
|
|
1627
|
+
new_ir._reset_analysis_variables()
|
|
1628
|
+
# Make fresh func_id
|
|
1629
|
+
new_ir.func_id = new_ir.func_id.derive()
|
|
1630
|
+
return new_ir
|
|
1631
|
+
|
|
1632
|
+
def copy(self):
|
|
1633
|
+
new_ir = copy.copy(self)
|
|
1634
|
+
blocks = {}
|
|
1635
|
+
block_entry_vars = {}
|
|
1636
|
+
for label, block in self.blocks.items():
|
|
1637
|
+
new_block = block.copy()
|
|
1638
|
+
blocks[label] = new_block
|
|
1639
|
+
if block in self.block_entry_vars:
|
|
1640
|
+
block_entry_vars[new_block] = self.block_entry_vars[block]
|
|
1641
|
+
new_ir.blocks = blocks
|
|
1642
|
+
new_ir.block_entry_vars = block_entry_vars
|
|
1643
|
+
return new_ir
|
|
1644
|
+
|
|
1645
|
+
def get_block_entry_vars(self, block):
|
|
1646
|
+
"""
|
|
1647
|
+
Return a set of variable names possibly alive at the beginning of
|
|
1648
|
+
the block.
|
|
1649
|
+
"""
|
|
1650
|
+
return self.block_entry_vars[block]
|
|
1651
|
+
|
|
1652
|
+
def infer_constant(self, name):
|
|
1653
|
+
"""
|
|
1654
|
+
Try to infer the constant value of a given variable.
|
|
1655
|
+
"""
|
|
1656
|
+
if isinstance(name, Var):
|
|
1657
|
+
name = name.name
|
|
1658
|
+
return self._consts.infer_constant(name)
|
|
1659
|
+
|
|
1660
|
+
def get_definition(self, value, lhs_only=False):
|
|
1661
|
+
"""
|
|
1662
|
+
Get the definition site for the given variable name or instance.
|
|
1663
|
+
A Expr instance is returned by default, but if lhs_only is set
|
|
1664
|
+
to True, the left-hand-side variable is returned instead.
|
|
1665
|
+
"""
|
|
1666
|
+
lhs = value
|
|
1667
|
+
while True:
|
|
1668
|
+
if isinstance(value, Var):
|
|
1669
|
+
lhs = value
|
|
1670
|
+
name = value.name
|
|
1671
|
+
elif isinstance(value, str):
|
|
1672
|
+
lhs = value
|
|
1673
|
+
name = value
|
|
1674
|
+
else:
|
|
1675
|
+
return lhs if lhs_only else value
|
|
1676
|
+
defs = self._definitions[name]
|
|
1677
|
+
if len(defs) == 0:
|
|
1678
|
+
raise KeyError("no definition for %r" % (name,))
|
|
1679
|
+
if len(defs) > 1:
|
|
1680
|
+
raise KeyError("more than one definition for %r" % (name,))
|
|
1681
|
+
value = defs[0]
|
|
1682
|
+
|
|
1683
|
+
def get_assignee(self, rhs_value, in_blocks=None):
|
|
1684
|
+
"""
|
|
1685
|
+
Finds the assignee for a given RHS value. If in_blocks is given the
|
|
1686
|
+
search will be limited to the specified blocks.
|
|
1687
|
+
"""
|
|
1688
|
+
if in_blocks is None:
|
|
1689
|
+
blocks = self.blocks.values()
|
|
1690
|
+
elif isinstance(in_blocks, int):
|
|
1691
|
+
blocks = [self.blocks[in_blocks]]
|
|
1692
|
+
else:
|
|
1693
|
+
blocks = [self.blocks[blk] for blk in list(in_blocks)]
|
|
1694
|
+
|
|
1695
|
+
assert isinstance(rhs_value, AbstractRHS)
|
|
1696
|
+
|
|
1697
|
+
for blk in blocks:
|
|
1698
|
+
for assign in blk.find_insts(Assign):
|
|
1699
|
+
if assign.value == rhs_value:
|
|
1700
|
+
return assign.target
|
|
1701
|
+
|
|
1702
|
+
raise ValueError("Could not find an assignee for %s" % rhs_value)
|
|
1703
|
+
|
|
1704
|
+
def dump(self, file=None):
|
|
1705
|
+
nofile = file is None
|
|
1706
|
+
# Avoid early bind of sys.stdout as default value
|
|
1707
|
+
file = file or StringIO()
|
|
1708
|
+
for offset, block in sorted(self.blocks.items()):
|
|
1709
|
+
print("label %s:" % (offset,), file=file)
|
|
1710
|
+
block.dump(file=file)
|
|
1711
|
+
if nofile:
|
|
1712
|
+
text = file.getvalue()
|
|
1713
|
+
if config.HIGHLIGHT_DUMPS:
|
|
1714
|
+
try:
|
|
1715
|
+
import pygments # noqa
|
|
1716
|
+
except ImportError:
|
|
1717
|
+
msg = "Please install pygments to see highlighted dumps"
|
|
1718
|
+
raise ValueError(msg)
|
|
1719
|
+
else:
|
|
1720
|
+
from pygments import highlight
|
|
1721
|
+
from numba.cuda.misc.dump_style import NumbaIRLexer as lexer
|
|
1722
|
+
from numba.cuda.misc.dump_style import by_colorscheme
|
|
1723
|
+
from pygments.formatters import Terminal256Formatter
|
|
1724
|
+
|
|
1725
|
+
print(
|
|
1726
|
+
highlight(
|
|
1727
|
+
text,
|
|
1728
|
+
lexer(),
|
|
1729
|
+
Terminal256Formatter(style=by_colorscheme()),
|
|
1730
|
+
)
|
|
1731
|
+
)
|
|
1732
|
+
else:
|
|
1733
|
+
print(text)
|
|
1734
|
+
|
|
1735
|
+
def dump_to_string(self):
|
|
1736
|
+
with StringIO() as sb:
|
|
1737
|
+
self.dump(file=sb)
|
|
1738
|
+
return sb.getvalue()
|
|
1739
|
+
|
|
1740
|
+
def dump_generator_info(self, file=None):
|
|
1741
|
+
file = file or sys.stdout
|
|
1742
|
+
gi = self.generator_info
|
|
1743
|
+
print("generator state variables:", sorted(gi.state_vars), file=file)
|
|
1744
|
+
for index, yp in sorted(gi.yield_points.items()):
|
|
1745
|
+
print(
|
|
1746
|
+
"yield point #%d: live variables = %s, weak live variables = %s"
|
|
1747
|
+
% (index, sorted(yp.live_vars), sorted(yp.weak_live_vars)),
|
|
1748
|
+
file=file,
|
|
1749
|
+
)
|
|
1750
|
+
|
|
1751
|
+
def render_dot(self, filename_prefix="numba_ir", include_ir=True):
|
|
1752
|
+
"""Render the CFG of the IR with GraphViz DOT via the
|
|
1753
|
+
``graphviz`` python binding.
|
|
1754
|
+
|
|
1755
|
+
Returns
|
|
1756
|
+
-------
|
|
1757
|
+
g : graphviz.Digraph
|
|
1758
|
+
Use `g.view()` to open the graph in the default PDF application.
|
|
1759
|
+
"""
|
|
1760
|
+
|
|
1761
|
+
try:
|
|
1762
|
+
import graphviz as gv
|
|
1763
|
+
except ImportError:
|
|
1764
|
+
raise ImportError(
|
|
1765
|
+
"The feature requires `graphviz` but it is not available. "
|
|
1766
|
+
"Please install with `pip install graphviz`"
|
|
1767
|
+
)
|
|
1768
|
+
g = gv.Digraph(
|
|
1769
|
+
filename="{}{}.dot".format(
|
|
1770
|
+
filename_prefix,
|
|
1771
|
+
self.func_id.unique_name,
|
|
1772
|
+
)
|
|
1773
|
+
)
|
|
1774
|
+
# Populate the nodes
|
|
1775
|
+
for k, blk in self.blocks.items():
|
|
1776
|
+
with StringIO() as sb:
|
|
1777
|
+
blk.dump(sb)
|
|
1778
|
+
label = sb.getvalue()
|
|
1779
|
+
if include_ir:
|
|
1780
|
+
label = "".join(
|
|
1781
|
+
[r" {}\l".format(x) for x in label.splitlines()],
|
|
1782
|
+
)
|
|
1783
|
+
label = r"block {}\l".format(k) + label
|
|
1784
|
+
g.node(str(k), label=label, shape="rect")
|
|
1785
|
+
else:
|
|
1786
|
+
label = r"{}\l".format(k)
|
|
1787
|
+
g.node(str(k), label=label, shape="circle")
|
|
1788
|
+
# Populate the edges
|
|
1789
|
+
for src, blk in self.blocks.items():
|
|
1790
|
+
for dst in blk.terminator.get_targets():
|
|
1791
|
+
g.edge(str(src), str(dst))
|
|
1792
|
+
return g
|
|
1793
|
+
|
|
1794
|
+
|
|
1795
|
+
# A stub for undefined global reference
|
|
1796
|
+
class UndefinedType(EqualityCheckMixin):
|
|
1797
|
+
_singleton = None
|
|
1798
|
+
|
|
1799
|
+
def __new__(cls):
|
|
1800
|
+
obj = cls._singleton
|
|
1801
|
+
if obj is not None:
|
|
1802
|
+
return obj
|
|
1803
|
+
else:
|
|
1804
|
+
obj = object.__new__(cls)
|
|
1805
|
+
cls._singleton = obj
|
|
1806
|
+
return obj
|
|
1807
|
+
|
|
1808
|
+
def __repr__(self):
|
|
1809
|
+
return "Undefined"
|
|
1810
|
+
|
|
1811
|
+
|
|
1812
|
+
UNDEFINED = UndefinedType()
|