numba-cuda 0.22.0__cp312-cp312-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.

Potentially problematic release.


This version of numba-cuda might be problematic. Click here for more details.

Files changed (487) hide show
  1. _numba_cuda_redirector.pth +4 -0
  2. _numba_cuda_redirector.py +89 -0
  3. numba_cuda/VERSION +1 -0
  4. numba_cuda/__init__.py +6 -0
  5. numba_cuda/_version.py +11 -0
  6. numba_cuda/numba/cuda/__init__.py +70 -0
  7. numba_cuda/numba/cuda/_internal/cuda_bf16.py +16394 -0
  8. numba_cuda/numba/cuda/_internal/cuda_fp16.py +8112 -0
  9. numba_cuda/numba/cuda/api.py +580 -0
  10. numba_cuda/numba/cuda/api_util.py +76 -0
  11. numba_cuda/numba/cuda/args.py +72 -0
  12. numba_cuda/numba/cuda/bf16.py +397 -0
  13. numba_cuda/numba/cuda/cache_hints.py +287 -0
  14. numba_cuda/numba/cuda/cext/__init__.py +2 -0
  15. numba_cuda/numba/cuda/cext/_devicearray.cpp +159 -0
  16. numba_cuda/numba/cuda/cext/_devicearray.cpython-312-aarch64-linux-gnu.so +0 -0
  17. numba_cuda/numba/cuda/cext/_devicearray.h +29 -0
  18. numba_cuda/numba/cuda/cext/_dispatcher.cpp +1098 -0
  19. numba_cuda/numba/cuda/cext/_dispatcher.cpython-312-aarch64-linux-gnu.so +0 -0
  20. numba_cuda/numba/cuda/cext/_hashtable.cpp +532 -0
  21. numba_cuda/numba/cuda/cext/_hashtable.h +135 -0
  22. numba_cuda/numba/cuda/cext/_helperlib.c +71 -0
  23. numba_cuda/numba/cuda/cext/_helperlib.cpython-312-aarch64-linux-gnu.so +0 -0
  24. numba_cuda/numba/cuda/cext/_helpermod.c +82 -0
  25. numba_cuda/numba/cuda/cext/_pymodule.h +38 -0
  26. numba_cuda/numba/cuda/cext/_typeconv.cpp +206 -0
  27. numba_cuda/numba/cuda/cext/_typeconv.cpython-312-aarch64-linux-gnu.so +0 -0
  28. numba_cuda/numba/cuda/cext/_typeof.cpp +1159 -0
  29. numba_cuda/numba/cuda/cext/_typeof.h +19 -0
  30. numba_cuda/numba/cuda/cext/capsulethunk.h +111 -0
  31. numba_cuda/numba/cuda/cext/mviewbuf.c +385 -0
  32. numba_cuda/numba/cuda/cext/mviewbuf.cpython-312-aarch64-linux-gnu.so +0 -0
  33. numba_cuda/numba/cuda/cext/typeconv.cpp +212 -0
  34. numba_cuda/numba/cuda/cext/typeconv.hpp +101 -0
  35. numba_cuda/numba/cuda/cg.py +67 -0
  36. numba_cuda/numba/cuda/cgutils.py +1294 -0
  37. numba_cuda/numba/cuda/cloudpickle/__init__.py +21 -0
  38. numba_cuda/numba/cuda/cloudpickle/cloudpickle.py +1598 -0
  39. numba_cuda/numba/cuda/cloudpickle/cloudpickle_fast.py +17 -0
  40. numba_cuda/numba/cuda/codegen.py +541 -0
  41. numba_cuda/numba/cuda/compiler.py +1396 -0
  42. numba_cuda/numba/cuda/core/analysis.py +758 -0
  43. numba_cuda/numba/cuda/core/annotations/__init__.py +0 -0
  44. numba_cuda/numba/cuda/core/annotations/pretty_annotate.py +288 -0
  45. numba_cuda/numba/cuda/core/annotations/type_annotations.py +305 -0
  46. numba_cuda/numba/cuda/core/base.py +1332 -0
  47. numba_cuda/numba/cuda/core/boxing.py +1411 -0
  48. numba_cuda/numba/cuda/core/bytecode.py +728 -0
  49. numba_cuda/numba/cuda/core/byteflow.py +2346 -0
  50. numba_cuda/numba/cuda/core/caching.py +744 -0
  51. numba_cuda/numba/cuda/core/callconv.py +392 -0
  52. numba_cuda/numba/cuda/core/codegen.py +171 -0
  53. numba_cuda/numba/cuda/core/compiler.py +199 -0
  54. numba_cuda/numba/cuda/core/compiler_lock.py +85 -0
  55. numba_cuda/numba/cuda/core/compiler_machinery.py +497 -0
  56. numba_cuda/numba/cuda/core/config.py +650 -0
  57. numba_cuda/numba/cuda/core/consts.py +124 -0
  58. numba_cuda/numba/cuda/core/controlflow.py +989 -0
  59. numba_cuda/numba/cuda/core/entrypoints.py +57 -0
  60. numba_cuda/numba/cuda/core/environment.py +66 -0
  61. numba_cuda/numba/cuda/core/errors.py +917 -0
  62. numba_cuda/numba/cuda/core/event.py +511 -0
  63. numba_cuda/numba/cuda/core/funcdesc.py +330 -0
  64. numba_cuda/numba/cuda/core/generators.py +387 -0
  65. numba_cuda/numba/cuda/core/imputils.py +509 -0
  66. numba_cuda/numba/cuda/core/inline_closurecall.py +1787 -0
  67. numba_cuda/numba/cuda/core/interpreter.py +3617 -0
  68. numba_cuda/numba/cuda/core/ir.py +1812 -0
  69. numba_cuda/numba/cuda/core/ir_utils.py +2638 -0
  70. numba_cuda/numba/cuda/core/optional.py +129 -0
  71. numba_cuda/numba/cuda/core/options.py +262 -0
  72. numba_cuda/numba/cuda/core/postproc.py +249 -0
  73. numba_cuda/numba/cuda/core/pythonapi.py +1859 -0
  74. numba_cuda/numba/cuda/core/registry.py +46 -0
  75. numba_cuda/numba/cuda/core/removerefctpass.py +123 -0
  76. numba_cuda/numba/cuda/core/rewrites/__init__.py +26 -0
  77. numba_cuda/numba/cuda/core/rewrites/ir_print.py +91 -0
  78. numba_cuda/numba/cuda/core/rewrites/registry.py +104 -0
  79. numba_cuda/numba/cuda/core/rewrites/static_binop.py +41 -0
  80. numba_cuda/numba/cuda/core/rewrites/static_getitem.py +189 -0
  81. numba_cuda/numba/cuda/core/rewrites/static_raise.py +100 -0
  82. numba_cuda/numba/cuda/core/sigutils.py +68 -0
  83. numba_cuda/numba/cuda/core/ssa.py +498 -0
  84. numba_cuda/numba/cuda/core/targetconfig.py +330 -0
  85. numba_cuda/numba/cuda/core/tracing.py +231 -0
  86. numba_cuda/numba/cuda/core/transforms.py +956 -0
  87. numba_cuda/numba/cuda/core/typed_passes.py +867 -0
  88. numba_cuda/numba/cuda/core/typeinfer.py +1950 -0
  89. numba_cuda/numba/cuda/core/unsafe/__init__.py +0 -0
  90. numba_cuda/numba/cuda/core/unsafe/bytes.py +67 -0
  91. numba_cuda/numba/cuda/core/unsafe/eh.py +67 -0
  92. numba_cuda/numba/cuda/core/unsafe/refcount.py +98 -0
  93. numba_cuda/numba/cuda/core/untyped_passes.py +1979 -0
  94. numba_cuda/numba/cuda/cpython/builtins.py +1153 -0
  95. numba_cuda/numba/cuda/cpython/charseq.py +1218 -0
  96. numba_cuda/numba/cuda/cpython/cmathimpl.py +560 -0
  97. numba_cuda/numba/cuda/cpython/enumimpl.py +103 -0
  98. numba_cuda/numba/cuda/cpython/iterators.py +167 -0
  99. numba_cuda/numba/cuda/cpython/listobj.py +1326 -0
  100. numba_cuda/numba/cuda/cpython/mathimpl.py +499 -0
  101. numba_cuda/numba/cuda/cpython/numbers.py +1475 -0
  102. numba_cuda/numba/cuda/cpython/rangeobj.py +289 -0
  103. numba_cuda/numba/cuda/cpython/slicing.py +322 -0
  104. numba_cuda/numba/cuda/cpython/tupleobj.py +456 -0
  105. numba_cuda/numba/cuda/cpython/unicode.py +2865 -0
  106. numba_cuda/numba/cuda/cpython/unicode_support.py +1597 -0
  107. numba_cuda/numba/cuda/cpython/unsafe/__init__.py +0 -0
  108. numba_cuda/numba/cuda/cpython/unsafe/numbers.py +64 -0
  109. numba_cuda/numba/cuda/cpython/unsafe/tuple.py +92 -0
  110. numba_cuda/numba/cuda/cuda_paths.py +691 -0
  111. numba_cuda/numba/cuda/cudadecl.py +543 -0
  112. numba_cuda/numba/cuda/cudadrv/__init__.py +14 -0
  113. numba_cuda/numba/cuda/cudadrv/devicearray.py +954 -0
  114. numba_cuda/numba/cuda/cudadrv/devices.py +249 -0
  115. numba_cuda/numba/cuda/cudadrv/driver.py +3238 -0
  116. numba_cuda/numba/cuda/cudadrv/drvapi.py +435 -0
  117. numba_cuda/numba/cuda/cudadrv/dummyarray.py +562 -0
  118. numba_cuda/numba/cuda/cudadrv/enums.py +613 -0
  119. numba_cuda/numba/cuda/cudadrv/error.py +48 -0
  120. numba_cuda/numba/cuda/cudadrv/libs.py +220 -0
  121. numba_cuda/numba/cuda/cudadrv/linkable_code.py +184 -0
  122. numba_cuda/numba/cuda/cudadrv/mappings.py +14 -0
  123. numba_cuda/numba/cuda/cudadrv/ndarray.py +26 -0
  124. numba_cuda/numba/cuda/cudadrv/nvrtc.py +193 -0
  125. numba_cuda/numba/cuda/cudadrv/nvvm.py +756 -0
  126. numba_cuda/numba/cuda/cudadrv/rtapi.py +13 -0
  127. numba_cuda/numba/cuda/cudadrv/runtime.py +34 -0
  128. numba_cuda/numba/cuda/cudaimpl.py +983 -0
  129. numba_cuda/numba/cuda/cudamath.py +149 -0
  130. numba_cuda/numba/cuda/datamodel/__init__.py +7 -0
  131. numba_cuda/numba/cuda/datamodel/cuda_manager.py +66 -0
  132. numba_cuda/numba/cuda/datamodel/cuda_models.py +1446 -0
  133. numba_cuda/numba/cuda/datamodel/cuda_packer.py +224 -0
  134. numba_cuda/numba/cuda/datamodel/cuda_registry.py +22 -0
  135. numba_cuda/numba/cuda/datamodel/cuda_testing.py +153 -0
  136. numba_cuda/numba/cuda/datamodel/manager.py +11 -0
  137. numba_cuda/numba/cuda/datamodel/models.py +9 -0
  138. numba_cuda/numba/cuda/datamodel/packer.py +9 -0
  139. numba_cuda/numba/cuda/datamodel/registry.py +11 -0
  140. numba_cuda/numba/cuda/datamodel/testing.py +11 -0
  141. numba_cuda/numba/cuda/debuginfo.py +997 -0
  142. numba_cuda/numba/cuda/decorators.py +294 -0
  143. numba_cuda/numba/cuda/descriptor.py +35 -0
  144. numba_cuda/numba/cuda/device_init.py +155 -0
  145. numba_cuda/numba/cuda/deviceufunc.py +1021 -0
  146. numba_cuda/numba/cuda/dispatcher.py +2463 -0
  147. numba_cuda/numba/cuda/errors.py +72 -0
  148. numba_cuda/numba/cuda/extending.py +697 -0
  149. numba_cuda/numba/cuda/flags.py +178 -0
  150. numba_cuda/numba/cuda/fp16.py +357 -0
  151. numba_cuda/numba/cuda/include/12/cuda_bf16.h +5118 -0
  152. numba_cuda/numba/cuda/include/12/cuda_bf16.hpp +3865 -0
  153. numba_cuda/numba/cuda/include/12/cuda_fp16.h +5363 -0
  154. numba_cuda/numba/cuda/include/12/cuda_fp16.hpp +3483 -0
  155. numba_cuda/numba/cuda/include/13/cuda_bf16.h +5118 -0
  156. numba_cuda/numba/cuda/include/13/cuda_bf16.hpp +3865 -0
  157. numba_cuda/numba/cuda/include/13/cuda_fp16.h +5363 -0
  158. numba_cuda/numba/cuda/include/13/cuda_fp16.hpp +3483 -0
  159. numba_cuda/numba/cuda/initialize.py +24 -0
  160. numba_cuda/numba/cuda/intrinsics.py +531 -0
  161. numba_cuda/numba/cuda/itanium_mangler.py +214 -0
  162. numba_cuda/numba/cuda/kernels/__init__.py +2 -0
  163. numba_cuda/numba/cuda/kernels/reduction.py +265 -0
  164. numba_cuda/numba/cuda/kernels/transpose.py +65 -0
  165. numba_cuda/numba/cuda/libdevice.py +3386 -0
  166. numba_cuda/numba/cuda/libdevicedecl.py +20 -0
  167. numba_cuda/numba/cuda/libdevicefuncs.py +1060 -0
  168. numba_cuda/numba/cuda/libdeviceimpl.py +88 -0
  169. numba_cuda/numba/cuda/locks.py +19 -0
  170. numba_cuda/numba/cuda/lowering.py +1980 -0
  171. numba_cuda/numba/cuda/mathimpl.py +374 -0
  172. numba_cuda/numba/cuda/memory_management/__init__.py +4 -0
  173. numba_cuda/numba/cuda/memory_management/memsys.cu +99 -0
  174. numba_cuda/numba/cuda/memory_management/memsys.cuh +22 -0
  175. numba_cuda/numba/cuda/memory_management/nrt.cu +212 -0
  176. numba_cuda/numba/cuda/memory_management/nrt.cuh +48 -0
  177. numba_cuda/numba/cuda/memory_management/nrt.py +390 -0
  178. numba_cuda/numba/cuda/memory_management/nrt_context.py +438 -0
  179. numba_cuda/numba/cuda/misc/appdirs.py +594 -0
  180. numba_cuda/numba/cuda/misc/cffiimpl.py +24 -0
  181. numba_cuda/numba/cuda/misc/coverage_support.py +43 -0
  182. numba_cuda/numba/cuda/misc/dump_style.py +41 -0
  183. numba_cuda/numba/cuda/misc/findlib.py +75 -0
  184. numba_cuda/numba/cuda/misc/firstlinefinder.py +96 -0
  185. numba_cuda/numba/cuda/misc/gdb_hook.py +240 -0
  186. numba_cuda/numba/cuda/misc/literal.py +28 -0
  187. numba_cuda/numba/cuda/misc/llvm_pass_timings.py +412 -0
  188. numba_cuda/numba/cuda/misc/special.py +94 -0
  189. numba_cuda/numba/cuda/models.py +56 -0
  190. numba_cuda/numba/cuda/np/arraymath.py +5130 -0
  191. numba_cuda/numba/cuda/np/arrayobj.py +7635 -0
  192. numba_cuda/numba/cuda/np/extensions.py +11 -0
  193. numba_cuda/numba/cuda/np/linalg.py +3087 -0
  194. numba_cuda/numba/cuda/np/math/__init__.py +0 -0
  195. numba_cuda/numba/cuda/np/math/cmathimpl.py +558 -0
  196. numba_cuda/numba/cuda/np/math/mathimpl.py +487 -0
  197. numba_cuda/numba/cuda/np/math/numbers.py +1461 -0
  198. numba_cuda/numba/cuda/np/npdatetime.py +969 -0
  199. numba_cuda/numba/cuda/np/npdatetime_helpers.py +217 -0
  200. numba_cuda/numba/cuda/np/npyfuncs.py +1808 -0
  201. numba_cuda/numba/cuda/np/npyimpl.py +1027 -0
  202. numba_cuda/numba/cuda/np/numpy_support.py +798 -0
  203. numba_cuda/numba/cuda/np/polynomial/__init__.py +4 -0
  204. numba_cuda/numba/cuda/np/polynomial/polynomial_core.py +242 -0
  205. numba_cuda/numba/cuda/np/polynomial/polynomial_functions.py +380 -0
  206. numba_cuda/numba/cuda/np/ufunc/__init__.py +4 -0
  207. numba_cuda/numba/cuda/np/ufunc/decorators.py +203 -0
  208. numba_cuda/numba/cuda/np/ufunc/sigparse.py +68 -0
  209. numba_cuda/numba/cuda/np/ufunc/ufuncbuilder.py +65 -0
  210. numba_cuda/numba/cuda/np/ufunc_db.py +1282 -0
  211. numba_cuda/numba/cuda/np/unsafe/__init__.py +0 -0
  212. numba_cuda/numba/cuda/np/unsafe/ndarray.py +84 -0
  213. numba_cuda/numba/cuda/nvvmutils.py +254 -0
  214. numba_cuda/numba/cuda/printimpl.py +126 -0
  215. numba_cuda/numba/cuda/random.py +308 -0
  216. numba_cuda/numba/cuda/reshape_funcs.cu +156 -0
  217. numba_cuda/numba/cuda/serialize.py +267 -0
  218. numba_cuda/numba/cuda/simulator/__init__.py +63 -0
  219. numba_cuda/numba/cuda/simulator/_internal/__init__.py +4 -0
  220. numba_cuda/numba/cuda/simulator/_internal/cuda_bf16.py +2 -0
  221. numba_cuda/numba/cuda/simulator/api.py +179 -0
  222. numba_cuda/numba/cuda/simulator/bf16.py +4 -0
  223. numba_cuda/numba/cuda/simulator/compiler.py +38 -0
  224. numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +11 -0
  225. numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +462 -0
  226. numba_cuda/numba/cuda/simulator/cudadrv/devices.py +122 -0
  227. numba_cuda/numba/cuda/simulator/cudadrv/driver.py +66 -0
  228. numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +7 -0
  229. numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +7 -0
  230. numba_cuda/numba/cuda/simulator/cudadrv/error.py +10 -0
  231. numba_cuda/numba/cuda/simulator/cudadrv/libs.py +10 -0
  232. numba_cuda/numba/cuda/simulator/cudadrv/linkable_code.py +61 -0
  233. numba_cuda/numba/cuda/simulator/cudadrv/nvrtc.py +11 -0
  234. numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +32 -0
  235. numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +22 -0
  236. numba_cuda/numba/cuda/simulator/dispatcher.py +11 -0
  237. numba_cuda/numba/cuda/simulator/kernel.py +320 -0
  238. numba_cuda/numba/cuda/simulator/kernelapi.py +509 -0
  239. numba_cuda/numba/cuda/simulator/memory_management/__init__.py +4 -0
  240. numba_cuda/numba/cuda/simulator/memory_management/nrt.py +21 -0
  241. numba_cuda/numba/cuda/simulator/reduction.py +19 -0
  242. numba_cuda/numba/cuda/simulator/tests/support.py +4 -0
  243. numba_cuda/numba/cuda/simulator/vector_types.py +65 -0
  244. numba_cuda/numba/cuda/simulator_init.py +18 -0
  245. numba_cuda/numba/cuda/stubs.py +624 -0
  246. numba_cuda/numba/cuda/target.py +505 -0
  247. numba_cuda/numba/cuda/testing.py +347 -0
  248. numba_cuda/numba/cuda/tests/__init__.py +62 -0
  249. numba_cuda/numba/cuda/tests/benchmarks/__init__.py +0 -0
  250. numba_cuda/numba/cuda/tests/benchmarks/test_kernel_launch.py +119 -0
  251. numba_cuda/numba/cuda/tests/cloudpickle_main_class.py +9 -0
  252. numba_cuda/numba/cuda/tests/core/serialize_usecases.py +113 -0
  253. numba_cuda/numba/cuda/tests/core/test_itanium_mangler.py +83 -0
  254. numba_cuda/numba/cuda/tests/core/test_serialize.py +371 -0
  255. numba_cuda/numba/cuda/tests/cudadrv/__init__.py +9 -0
  256. numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +147 -0
  257. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +161 -0
  258. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +397 -0
  259. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +24 -0
  260. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +180 -0
  261. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +313 -0
  262. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +191 -0
  263. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +621 -0
  264. numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +247 -0
  265. numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +100 -0
  266. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +200 -0
  267. numba_cuda/numba/cuda/tests/cudadrv/test_events.py +53 -0
  268. numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +72 -0
  269. numba_cuda/numba/cuda/tests/cudadrv/test_init.py +138 -0
  270. numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +43 -0
  271. numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +15 -0
  272. numba_cuda/numba/cuda/tests/cudadrv/test_linkable_code.py +58 -0
  273. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +348 -0
  274. numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +128 -0
  275. numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +301 -0
  276. numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +174 -0
  277. numba_cuda/numba/cuda/tests/cudadrv/test_nvrtc.py +28 -0
  278. numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +185 -0
  279. numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +39 -0
  280. numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +23 -0
  281. numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +38 -0
  282. numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +48 -0
  283. numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +44 -0
  284. numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +127 -0
  285. numba_cuda/numba/cuda/tests/cudapy/__init__.py +9 -0
  286. numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +231 -0
  287. numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +50 -0
  288. numba_cuda/numba/cuda/tests/cudapy/cg_cache_usecases.py +36 -0
  289. numba_cuda/numba/cuda/tests/cudapy/complex_usecases.py +116 -0
  290. numba_cuda/numba/cuda/tests/cudapy/enum_usecases.py +59 -0
  291. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +62 -0
  292. numba_cuda/numba/cuda/tests/cudapy/jitlink.ptx +28 -0
  293. numba_cuda/numba/cuda/tests/cudapy/overload_usecases.py +33 -0
  294. numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +104 -0
  295. numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +47 -0
  296. numba_cuda/numba/cuda/tests/cudapy/test_analysis.py +1122 -0
  297. numba_cuda/numba/cuda/tests/cudapy/test_array.py +344 -0
  298. numba_cuda/numba/cuda/tests/cudapy/test_array_alignment.py +268 -0
  299. numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +203 -0
  300. numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +63 -0
  301. numba_cuda/numba/cuda/tests/cudapy/test_array_reductions.py +360 -0
  302. numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +1815 -0
  303. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16.py +599 -0
  304. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16_bindings.py +377 -0
  305. numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +160 -0
  306. numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +27 -0
  307. numba_cuda/numba/cuda/tests/cudapy/test_byteflow.py +98 -0
  308. numba_cuda/numba/cuda/tests/cudapy/test_cache_hints.py +210 -0
  309. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +683 -0
  310. numba_cuda/numba/cuda/tests/cudapy/test_casting.py +265 -0
  311. numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +42 -0
  312. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +718 -0
  313. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +370 -0
  314. numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +23 -0
  315. numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +142 -0
  316. numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +178 -0
  317. numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +193 -0
  318. numba_cuda/numba/cuda/tests/cudapy/test_copy_propagate.py +131 -0
  319. numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +438 -0
  320. numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +94 -0
  321. numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +101 -0
  322. numba_cuda/numba/cuda/tests/cudapy/test_debug.py +105 -0
  323. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +978 -0
  324. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo_types.py +476 -0
  325. numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +500 -0
  326. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +820 -0
  327. numba_cuda/numba/cuda/tests/cudapy/test_enums.py +152 -0
  328. numba_cuda/numba/cuda/tests/cudapy/test_errors.py +111 -0
  329. numba_cuda/numba/cuda/tests/cudapy/test_exception.py +170 -0
  330. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +1088 -0
  331. numba_cuda/numba/cuda/tests/cudapy/test_extending_types.py +71 -0
  332. numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +265 -0
  333. numba_cuda/numba/cuda/tests/cudapy/test_flow_control.py +1433 -0
  334. numba_cuda/numba/cuda/tests/cudapy/test_forall.py +57 -0
  335. numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +34 -0
  336. numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +69 -0
  337. numba_cuda/numba/cuda/tests/cudapy/test_globals.py +62 -0
  338. numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +474 -0
  339. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +167 -0
  340. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +92 -0
  341. numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +39 -0
  342. numba_cuda/numba/cuda/tests/cudapy/test_inline.py +170 -0
  343. numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +255 -0
  344. numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +1219 -0
  345. numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +263 -0
  346. numba_cuda/numba/cuda/tests/cudapy/test_ir.py +598 -0
  347. numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py +276 -0
  348. numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +101 -0
  349. numba_cuda/numba/cuda/tests/cudapy/test_lang.py +68 -0
  350. numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +123 -0
  351. numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +194 -0
  352. numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +220 -0
  353. numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +173 -0
  354. numba_cuda/numba/cuda/tests/cudapy/test_make_function_to_jit_function.py +364 -0
  355. numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +47 -0
  356. numba_cuda/numba/cuda/tests/cudapy/test_math.py +842 -0
  357. numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +76 -0
  358. numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +78 -0
  359. numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +25 -0
  360. numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +145 -0
  361. numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +39 -0
  362. numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +82 -0
  363. numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +53 -0
  364. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +504 -0
  365. numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +93 -0
  366. numba_cuda/numba/cuda/tests/cudapy/test_overload.py +402 -0
  367. numba_cuda/numba/cuda/tests/cudapy/test_powi.py +128 -0
  368. numba_cuda/numba/cuda/tests/cudapy/test_print.py +193 -0
  369. numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +37 -0
  370. numba_cuda/numba/cuda/tests/cudapy/test_random.py +117 -0
  371. numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +614 -0
  372. numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +130 -0
  373. numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +94 -0
  374. numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +83 -0
  375. numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +86 -0
  376. numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +40 -0
  377. numba_cuda/numba/cuda/tests/cudapy/test_sm.py +457 -0
  378. numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +233 -0
  379. numba_cuda/numba/cuda/tests/cudapy/test_ssa.py +454 -0
  380. numba_cuda/numba/cuda/tests/cudapy/test_stream_api.py +56 -0
  381. numba_cuda/numba/cuda/tests/cudapy/test_sync.py +277 -0
  382. numba_cuda/numba/cuda/tests/cudapy/test_tracing.py +200 -0
  383. numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +90 -0
  384. numba_cuda/numba/cuda/tests/cudapy/test_typeconv.py +333 -0
  385. numba_cuda/numba/cuda/tests/cudapy/test_typeinfer.py +538 -0
  386. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +585 -0
  387. numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +42 -0
  388. numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +485 -0
  389. numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +312 -0
  390. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +23 -0
  391. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +183 -0
  392. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +40 -0
  393. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +40 -0
  394. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +206 -0
  395. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +446 -0
  396. numba_cuda/numba/cuda/tests/cudasim/__init__.py +9 -0
  397. numba_cuda/numba/cuda/tests/cudasim/support.py +9 -0
  398. numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +111 -0
  399. numba_cuda/numba/cuda/tests/data/__init__.py +2 -0
  400. numba_cuda/numba/cuda/tests/data/cta_barrier.cu +28 -0
  401. numba_cuda/numba/cuda/tests/data/cuda_include.cu +10 -0
  402. numba_cuda/numba/cuda/tests/data/error.cu +12 -0
  403. numba_cuda/numba/cuda/tests/data/include/add.cuh +8 -0
  404. numba_cuda/numba/cuda/tests/data/jitlink.cu +28 -0
  405. numba_cuda/numba/cuda/tests/data/jitlink.ptx +49 -0
  406. numba_cuda/numba/cuda/tests/data/warn.cu +12 -0
  407. numba_cuda/numba/cuda/tests/doc_examples/__init__.py +9 -0
  408. numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +2 -0
  409. numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +54 -0
  410. numba_cuda/numba/cuda/tests/doc_examples/ffi/include/mul.cuh +8 -0
  411. numba_cuda/numba/cuda/tests/doc_examples/ffi/saxpy.cu +14 -0
  412. numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +86 -0
  413. numba_cuda/numba/cuda/tests/doc_examples/test_cpointer.py +68 -0
  414. numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +81 -0
  415. numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +141 -0
  416. numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +160 -0
  417. numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +180 -0
  418. numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +119 -0
  419. numba_cuda/numba/cuda/tests/doc_examples/test_random.py +66 -0
  420. numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +80 -0
  421. numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +206 -0
  422. numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +53 -0
  423. numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +76 -0
  424. numba_cuda/numba/cuda/tests/nocuda/__init__.py +9 -0
  425. numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +452 -0
  426. numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +48 -0
  427. numba_cuda/numba/cuda/tests/nocuda/test_import.py +63 -0
  428. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +252 -0
  429. numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +59 -0
  430. numba_cuda/numba/cuda/tests/nrt/__init__.py +9 -0
  431. numba_cuda/numba/cuda/tests/nrt/test_nrt.py +387 -0
  432. numba_cuda/numba/cuda/tests/nrt/test_nrt_refct.py +124 -0
  433. numba_cuda/numba/cuda/tests/support.py +900 -0
  434. numba_cuda/numba/cuda/typeconv/__init__.py +4 -0
  435. numba_cuda/numba/cuda/typeconv/castgraph.py +137 -0
  436. numba_cuda/numba/cuda/typeconv/rules.py +63 -0
  437. numba_cuda/numba/cuda/typeconv/typeconv.py +121 -0
  438. numba_cuda/numba/cuda/types/__init__.py +233 -0
  439. numba_cuda/numba/cuda/types/__init__.pyi +167 -0
  440. numba_cuda/numba/cuda/types/abstract.py +9 -0
  441. numba_cuda/numba/cuda/types/common.py +9 -0
  442. numba_cuda/numba/cuda/types/containers.py +9 -0
  443. numba_cuda/numba/cuda/types/cuda_abstract.py +533 -0
  444. numba_cuda/numba/cuda/types/cuda_common.py +110 -0
  445. numba_cuda/numba/cuda/types/cuda_containers.py +971 -0
  446. numba_cuda/numba/cuda/types/cuda_function_type.py +230 -0
  447. numba_cuda/numba/cuda/types/cuda_functions.py +798 -0
  448. numba_cuda/numba/cuda/types/cuda_iterators.py +120 -0
  449. numba_cuda/numba/cuda/types/cuda_misc.py +569 -0
  450. numba_cuda/numba/cuda/types/cuda_npytypes.py +690 -0
  451. numba_cuda/numba/cuda/types/cuda_scalars.py +280 -0
  452. numba_cuda/numba/cuda/types/ext_types.py +101 -0
  453. numba_cuda/numba/cuda/types/function_type.py +11 -0
  454. numba_cuda/numba/cuda/types/functions.py +9 -0
  455. numba_cuda/numba/cuda/types/iterators.py +9 -0
  456. numba_cuda/numba/cuda/types/misc.py +9 -0
  457. numba_cuda/numba/cuda/types/npytypes.py +9 -0
  458. numba_cuda/numba/cuda/types/scalars.py +9 -0
  459. numba_cuda/numba/cuda/typing/__init__.py +19 -0
  460. numba_cuda/numba/cuda/typing/arraydecl.py +939 -0
  461. numba_cuda/numba/cuda/typing/asnumbatype.py +130 -0
  462. numba_cuda/numba/cuda/typing/bufproto.py +70 -0
  463. numba_cuda/numba/cuda/typing/builtins.py +1209 -0
  464. numba_cuda/numba/cuda/typing/cffi_utils.py +219 -0
  465. numba_cuda/numba/cuda/typing/cmathdecl.py +47 -0
  466. numba_cuda/numba/cuda/typing/collections.py +138 -0
  467. numba_cuda/numba/cuda/typing/context.py +782 -0
  468. numba_cuda/numba/cuda/typing/ctypes_utils.py +125 -0
  469. numba_cuda/numba/cuda/typing/dictdecl.py +63 -0
  470. numba_cuda/numba/cuda/typing/enumdecl.py +74 -0
  471. numba_cuda/numba/cuda/typing/listdecl.py +147 -0
  472. numba_cuda/numba/cuda/typing/mathdecl.py +158 -0
  473. numba_cuda/numba/cuda/typing/npdatetime.py +322 -0
  474. numba_cuda/numba/cuda/typing/npydecl.py +749 -0
  475. numba_cuda/numba/cuda/typing/setdecl.py +115 -0
  476. numba_cuda/numba/cuda/typing/templates.py +1446 -0
  477. numba_cuda/numba/cuda/typing/typeof.py +301 -0
  478. numba_cuda/numba/cuda/ufuncs.py +746 -0
  479. numba_cuda/numba/cuda/utils.py +724 -0
  480. numba_cuda/numba/cuda/vector_types.py +214 -0
  481. numba_cuda/numba/cuda/vectorizers.py +260 -0
  482. numba_cuda-0.22.0.dist-info/METADATA +109 -0
  483. numba_cuda-0.22.0.dist-info/RECORD +487 -0
  484. numba_cuda-0.22.0.dist-info/WHEEL +6 -0
  485. numba_cuda-0.22.0.dist-info/licenses/LICENSE +26 -0
  486. numba_cuda-0.22.0.dist-info/licenses/LICENSE.numba +24 -0
  487. numba_cuda-0.22.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,989 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: BSD-2-Clause
3
+
4
+ import collections
5
+ import functools
6
+ import sys
7
+
8
+ from numba.cuda.core.ir import Loc
9
+ from numba.cuda.core.errors import UnsupportedError
10
+ from numba.cuda.utils import PYVERSION
11
+
12
+ # List of bytecodes creating a new block in the control flow graph
13
+ # (in addition to explicit jump labels).
14
+ NEW_BLOCKERS = frozenset(
15
+ ["SETUP_LOOP", "FOR_ITER", "SETUP_WITH", "BEFORE_WITH"]
16
+ )
17
+
18
+
19
+ class CFBlock(object):
20
+ def __init__(self, offset):
21
+ self.offset = offset
22
+ self.body = []
23
+ # A map of jumps to outgoing blocks (successors):
24
+ # { offset of outgoing block -> number of stack pops }
25
+ self.outgoing_jumps = {}
26
+ # A map of jumps to incoming blocks (predecessors):
27
+ # { offset of incoming block -> number of stack pops }
28
+ self.incoming_jumps = {}
29
+ self.terminating = False
30
+
31
+ def __repr__(self):
32
+ args = (
33
+ self.offset,
34
+ sorted(self.outgoing_jumps),
35
+ sorted(self.incoming_jumps),
36
+ )
37
+ return "block(offset:%d, outgoing: %s, incoming: %s)" % args
38
+
39
+ def __iter__(self):
40
+ return iter(self.body)
41
+
42
+
43
+ class Loop(
44
+ collections.namedtuple("Loop", ("entries", "exits", "header", "body"))
45
+ ):
46
+ """
47
+ A control flow loop, as detected by a CFGraph object.
48
+ """
49
+
50
+ __slots__ = ()
51
+
52
+ # The loop header is enough to detect that two loops are really
53
+ # the same, assuming they belong to the same graph.
54
+ # (note: in practice, only one loop instance is created per graph
55
+ # loop, so identity would be fine)
56
+
57
+ def __eq__(self, other):
58
+ return isinstance(other, Loop) and other.header == self.header
59
+
60
+ def __hash__(self):
61
+ return hash(self.header)
62
+
63
+
64
+ class _DictOfContainers(collections.defaultdict):
65
+ """A defaultdict with customized equality checks that ignore empty values.
66
+
67
+ Non-empty value is checked by: `bool(value_item) == True`.
68
+ """
69
+
70
+ def __eq__(self, other):
71
+ if isinstance(other, _DictOfContainers):
72
+ mine = self._non_empty_items()
73
+ theirs = other._non_empty_items()
74
+ return mine == theirs
75
+
76
+ return NotImplemented
77
+
78
+ def __ne__(self, other):
79
+ ret = self.__eq__(other)
80
+ if ret is NotImplemented:
81
+ return ret
82
+ else:
83
+ return not ret
84
+
85
+ def _non_empty_items(self):
86
+ return [(k, vs) for k, vs in sorted(self.items()) if vs]
87
+
88
+
89
+ class CFGraph(object):
90
+ """
91
+ Generic (almost) implementation of a Control Flow Graph.
92
+ """
93
+
94
+ def __init__(self):
95
+ self._nodes = set()
96
+ self._preds = _DictOfContainers(set)
97
+ self._succs = _DictOfContainers(set)
98
+ self._edge_data = {}
99
+ self._entry_point = None
100
+
101
+ def add_node(self, node):
102
+ """
103
+ Add *node* to the graph. This is necessary before adding any
104
+ edges from/to the node. *node* can be any hashable object.
105
+ """
106
+ self._nodes.add(node)
107
+
108
+ def add_edge(self, src, dest, data=None):
109
+ """
110
+ Add an edge from node *src* to node *dest*, with optional
111
+ per-edge *data*.
112
+ If such an edge already exists, it is replaced (duplicate edges
113
+ are not possible).
114
+ """
115
+ if src not in self._nodes:
116
+ raise ValueError(
117
+ "Cannot add edge as src node %s not in nodes %s"
118
+ % (src, self._nodes)
119
+ )
120
+ if dest not in self._nodes:
121
+ raise ValueError(
122
+ "Cannot add edge as dest node %s not in nodes %s"
123
+ % (dest, self._nodes)
124
+ )
125
+ self._add_edge(src, dest, data)
126
+
127
+ def successors(self, src):
128
+ """
129
+ Yield (node, data) pairs representing the successors of node *src*.
130
+ (*data* will be None if no data was specified when adding the edge)
131
+ """
132
+ for dest in self._succs[src]:
133
+ yield dest, self._edge_data[src, dest]
134
+
135
+ def predecessors(self, dest):
136
+ """
137
+ Yield (node, data) pairs representing the predecessors of node *dest*.
138
+ (*data* will be None if no data was specified when adding the edge)
139
+ """
140
+ for src in self._preds[dest]:
141
+ yield src, self._edge_data[src, dest]
142
+
143
+ def set_entry_point(self, node):
144
+ """
145
+ Set the entry point of the graph to *node*.
146
+ """
147
+ assert node in self._nodes
148
+ self._entry_point = node
149
+
150
+ def process(self):
151
+ """
152
+ Compute essential properties of the control flow graph. The graph
153
+ must have been fully populated, and its entry point specified. Other
154
+ graph properties are computed on-demand.
155
+ """
156
+ if self._entry_point is None:
157
+ raise RuntimeError("no entry point defined!")
158
+ self._eliminate_dead_blocks()
159
+
160
+ def dominators(self):
161
+ """
162
+ Return a dictionary of {node -> set(nodes)} mapping each node to
163
+ the nodes dominating it.
164
+
165
+ A node D dominates a node N when any path leading to N must go through D
166
+ """
167
+ return self._doms
168
+
169
+ def post_dominators(self):
170
+ """
171
+ Return a dictionary of {node -> set(nodes)} mapping each node to
172
+ the nodes post-dominating it.
173
+
174
+ A node P post-dominates a node N when any path starting from N must go
175
+ through P.
176
+ """
177
+ return self._post_doms
178
+
179
+ def immediate_dominators(self):
180
+ """
181
+ Return a dictionary of {node -> node} mapping each node to its
182
+ immediate dominator (idom).
183
+
184
+ The idom(B) is the closest strict dominator of V
185
+ """
186
+ return self._idom
187
+
188
+ def dominance_frontier(self):
189
+ """
190
+ Return a dictionary of {node -> set(nodes)} mapping each node to
191
+ the nodes in its dominance frontier.
192
+
193
+ The dominance frontier _df(N) is the set of all nodes that are
194
+ immediate successors to blocks dominated by N but which aren't
195
+ strictly dominated by N
196
+ """
197
+ return self._df
198
+
199
+ def dominator_tree(self):
200
+ """
201
+ return a dictionary of {node -> set(nodes)} mapping each node to
202
+ the set of nodes it immediately dominates
203
+
204
+ The domtree(B) is the closest strict set of nodes that B dominates
205
+ """
206
+ return self._domtree
207
+
208
+ @functools.cached_property
209
+ def _exit_points(self):
210
+ return self._find_exit_points()
211
+
212
+ @functools.cached_property
213
+ def _doms(self):
214
+ return self._find_dominators()
215
+
216
+ @functools.cached_property
217
+ def _back_edges(self):
218
+ return self._find_back_edges()
219
+
220
+ @functools.cached_property
221
+ def _topo_order(self):
222
+ return self._find_topo_order()
223
+
224
+ @functools.cached_property
225
+ def _descs(self):
226
+ return self._find_descendents()
227
+
228
+ @functools.cached_property
229
+ def _loops(self):
230
+ return self._find_loops()
231
+
232
+ @functools.cached_property
233
+ def _in_loops(self):
234
+ return self._find_in_loops()
235
+
236
+ @functools.cached_property
237
+ def _post_doms(self):
238
+ return self._find_post_dominators()
239
+
240
+ @functools.cached_property
241
+ def _idom(self):
242
+ return self._find_immediate_dominators()
243
+
244
+ @functools.cached_property
245
+ def _df(self):
246
+ return self._find_dominance_frontier()
247
+
248
+ @functools.cached_property
249
+ def _domtree(self):
250
+ return self._find_dominator_tree()
251
+
252
+ def descendents(self, node):
253
+ """
254
+ Return the set of descendents of the given *node*, in topological
255
+ order (ignoring back edges).
256
+ """
257
+ return self._descs[node]
258
+
259
+ def entry_point(self):
260
+ """
261
+ Return the entry point node.
262
+ """
263
+ assert self._entry_point is not None
264
+ return self._entry_point
265
+
266
+ def exit_points(self):
267
+ """
268
+ Return the computed set of exit nodes (may be empty).
269
+ """
270
+ return self._exit_points
271
+
272
+ def backbone(self):
273
+ """
274
+ Return the set of nodes constituting the graph's backbone.
275
+ (i.e. the nodes that every path starting from the entry point
276
+ must go through). By construction, it is non-empty: it contains
277
+ at least the entry point.
278
+ """
279
+ return self._post_doms[self._entry_point]
280
+
281
+ def loops(self):
282
+ """
283
+ Return a dictionary of {node -> loop} mapping each loop header
284
+ to the loop (a Loop instance) starting with it.
285
+ """
286
+ return self._loops
287
+
288
+ def in_loops(self, node):
289
+ """
290
+ Return the list of Loop objects the *node* belongs to,
291
+ from innermost to outermost.
292
+ """
293
+ return [self._loops[x] for x in self._in_loops.get(node, ())]
294
+
295
+ def dead_nodes(self):
296
+ """
297
+ Return the set of dead nodes (eliminated from the graph).
298
+ """
299
+ return self._dead_nodes
300
+
301
+ def nodes(self):
302
+ """
303
+ Return the set of live nodes.
304
+ """
305
+ return self._nodes
306
+
307
+ def topo_order(self):
308
+ """
309
+ Return the sequence of nodes in topological order (ignoring back
310
+ edges).
311
+ """
312
+ return self._topo_order
313
+
314
+ def topo_sort(self, nodes, reverse=False):
315
+ """
316
+ Iterate over the *nodes* in topological order (ignoring back edges).
317
+ The sort isn't guaranteed to be stable.
318
+ """
319
+ nodes = set(nodes)
320
+ it = self._topo_order
321
+ if reverse:
322
+ it = reversed(it)
323
+ for n in it:
324
+ if n in nodes:
325
+ yield n
326
+
327
+ def dump(self, file=None):
328
+ """
329
+ Dump extensive debug information.
330
+ """
331
+ import pprint
332
+
333
+ file = file or sys.stdout
334
+ if 1:
335
+ print("CFG adjacency lists:", file=file)
336
+ self._dump_adj_lists(file)
337
+ print("CFG dominators:", file=file)
338
+ pprint.pprint(self._doms, stream=file)
339
+ print("CFG post-dominators:", file=file)
340
+ pprint.pprint(self._post_doms, stream=file)
341
+ print("CFG back edges:", sorted(self._back_edges), file=file)
342
+ print("CFG loops:", file=file)
343
+ pprint.pprint(self._loops, stream=file)
344
+ print("CFG node-to-loops:", file=file)
345
+ pprint.pprint(self._in_loops, stream=file)
346
+ print("CFG backbone:", file=file)
347
+ pprint.pprint(self.backbone(), stream=file)
348
+
349
+ def render_dot(self, filename="numba_cfg.dot"):
350
+ """Render the controlflow graph with GraphViz DOT via the
351
+ ``graphviz`` python binding.
352
+
353
+ Returns
354
+ -------
355
+ g : graphviz.Digraph
356
+ Use `g.view()` to open the graph in the default PDF application.
357
+ """
358
+
359
+ try:
360
+ import graphviz as gv
361
+ except ImportError:
362
+ raise ImportError(
363
+ "The feature requires `graphviz` but it is not available. "
364
+ "Please install with `pip install graphviz`"
365
+ )
366
+ g = gv.Digraph(filename=filename)
367
+ # Populate the nodes
368
+ for n in self._nodes:
369
+ g.node(str(n))
370
+ # Populate the edges
371
+ for n in self._nodes:
372
+ for edge in self._succs[n]:
373
+ g.edge(str(n), str(edge))
374
+ return g
375
+
376
+ # Internal APIs
377
+
378
+ def _add_edge(self, from_, to, data=None):
379
+ # This internal version allows adding edges to/from unregistered
380
+ # (ghost) nodes.
381
+ self._preds[to].add(from_)
382
+ self._succs[from_].add(to)
383
+ self._edge_data[from_, to] = data
384
+
385
+ def _remove_node_edges(self, node):
386
+ for succ in self._succs.pop(node, ()):
387
+ self._preds[succ].remove(node)
388
+ del self._edge_data[node, succ]
389
+ for pred in self._preds.pop(node, ()):
390
+ self._succs[pred].remove(node)
391
+ del self._edge_data[pred, node]
392
+
393
+ def _dfs(self, entries=None):
394
+ if entries is None:
395
+ entries = (self._entry_point,)
396
+ seen = set()
397
+ stack = list(entries)
398
+ while stack:
399
+ node = stack.pop()
400
+ if node not in seen:
401
+ yield node
402
+ seen.add(node)
403
+ for succ in self._succs[node]:
404
+ stack.append(succ)
405
+
406
+ def _eliminate_dead_blocks(self):
407
+ """
408
+ Eliminate all blocks not reachable from the entry point, and
409
+ stash them into self._dead_nodes.
410
+ """
411
+ live = set()
412
+ for node in self._dfs():
413
+ live.add(node)
414
+ self._dead_nodes = self._nodes - live
415
+ self._nodes = live
416
+ # Remove all edges leading from dead nodes
417
+ for dead in self._dead_nodes:
418
+ self._remove_node_edges(dead)
419
+
420
+ def _find_exit_points(self):
421
+ """
422
+ Compute the graph's exit points.
423
+ """
424
+ exit_points = set()
425
+ for n in self._nodes:
426
+ if not self._succs.get(n):
427
+ exit_points.add(n)
428
+ return exit_points
429
+
430
+ def _find_postorder(self):
431
+ succs = self._succs
432
+ back_edges = self._back_edges
433
+ post_order = []
434
+ seen = set()
435
+
436
+ post_order = []
437
+
438
+ # DFS
439
+ def dfs_rec(node):
440
+ if node not in seen:
441
+ seen.add(node)
442
+ stack.append((post_order.append, node))
443
+ for dest in succs[node]:
444
+ if (node, dest) not in back_edges:
445
+ stack.append((dfs_rec, dest))
446
+
447
+ stack = [(dfs_rec, self._entry_point)]
448
+ while stack:
449
+ cb, data = stack.pop()
450
+ cb(data)
451
+
452
+ return post_order
453
+
454
+ def _find_immediate_dominators(self):
455
+ # The algorithm implemented computes the immediate dominator
456
+ # for each node in the CFG which is equivalent to build a dominator tree
457
+ # Based on the implementation from NetworkX
458
+ # library - nx.immediate_dominators
459
+ # https://github.com/networkx/networkx/blob/858e7cb183541a78969fed0cbcd02346f5866c02/networkx/algorithms/dominance.py # noqa: E501
460
+ # References:
461
+ # Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
462
+ # A Simple, Fast Dominance Algorithm
463
+ # https://www.cs.rice.edu/~keith/EMBED/dom.pdf
464
+ def intersect(u, v):
465
+ while u != v:
466
+ while idx[u] < idx[v]:
467
+ u = idom[u]
468
+ while idx[u] > idx[v]:
469
+ v = idom[v]
470
+ return u
471
+
472
+ entry = self._entry_point
473
+ preds_table = self._preds
474
+
475
+ order = self._find_postorder()
476
+ idx = {e: i for i, e in enumerate(order)} # index of each node
477
+ idom = {entry: entry}
478
+ order.pop()
479
+ order.reverse()
480
+
481
+ changed = True
482
+ while changed:
483
+ changed = False
484
+ for u in order:
485
+ new_idom = functools.reduce(
486
+ intersect, (v for v in preds_table[u] if v in idom)
487
+ )
488
+ if u not in idom or idom[u] != new_idom:
489
+ idom[u] = new_idom
490
+ changed = True
491
+
492
+ return idom
493
+
494
+ def _find_dominator_tree(self):
495
+ idom = self._idom
496
+ domtree = _DictOfContainers(set)
497
+
498
+ for u, v in idom.items():
499
+ # v dominates u
500
+ if u not in domtree:
501
+ domtree[u] = set()
502
+ if u != v:
503
+ domtree[v].add(u)
504
+
505
+ return domtree
506
+
507
+ def _find_dominance_frontier(self):
508
+ idom = self._idom
509
+ preds_table = self._preds
510
+ df = {u: set() for u in idom}
511
+
512
+ for u in idom:
513
+ if len(preds_table[u]) < 2:
514
+ continue
515
+ for v in preds_table[u]:
516
+ while v != idom[u]:
517
+ df[v].add(u)
518
+ v = idom[v]
519
+
520
+ return df
521
+
522
+ def _find_dominators_internal(self, post=False):
523
+ # See theoretical description in
524
+ # http://en.wikipedia.org/wiki/Dominator_%28graph_theory%29
525
+ # The algorithm implemented here uses a todo-list as described
526
+ # in http://pages.cs.wisc.edu/~fischer/cs701.f08/finding.loops.html
527
+ if post:
528
+ entries = set(self._exit_points)
529
+ preds_table = self._succs
530
+ succs_table = self._preds
531
+ else:
532
+ entries = set([self._entry_point])
533
+ preds_table = self._preds
534
+ succs_table = self._succs
535
+
536
+ if not entries:
537
+ raise RuntimeError(
538
+ "no entry points: dominator algorithm cannot be seeded"
539
+ )
540
+
541
+ doms = {}
542
+ for e in entries:
543
+ doms[e] = set([e])
544
+
545
+ todo = []
546
+ for n in self._nodes:
547
+ if n not in entries:
548
+ doms[n] = set(self._nodes)
549
+ todo.append(n)
550
+
551
+ while todo:
552
+ n = todo.pop()
553
+ if n in entries:
554
+ continue
555
+ new_doms = set([n])
556
+ preds = preds_table[n]
557
+ if preds:
558
+ new_doms |= functools.reduce(
559
+ set.intersection, [doms[p] for p in preds]
560
+ )
561
+ if new_doms != doms[n]:
562
+ assert len(new_doms) < len(doms[n])
563
+ doms[n] = new_doms
564
+ todo.extend(succs_table[n])
565
+ return doms
566
+
567
+ def _find_dominators(self):
568
+ return self._find_dominators_internal(post=False)
569
+
570
+ def _find_post_dominators(self):
571
+ # To handle infinite loops correctly, we need to add a dummy
572
+ # exit point, and link members of infinite loops to it.
573
+ dummy_exit = object()
574
+ self._exit_points.add(dummy_exit)
575
+ for loop in self._loops.values():
576
+ if not loop.exits:
577
+ for b in loop.body:
578
+ self._add_edge(b, dummy_exit)
579
+ pdoms = self._find_dominators_internal(post=True)
580
+ # Fix the _post_doms table to make no reference to the dummy exit
581
+ del pdoms[dummy_exit]
582
+ for doms in pdoms.values():
583
+ doms.discard(dummy_exit)
584
+ self._remove_node_edges(dummy_exit)
585
+ self._exit_points.remove(dummy_exit)
586
+ return pdoms
587
+
588
+ # Finding loops and back edges: see
589
+ # http://pages.cs.wisc.edu/~fischer/cs701.f08/finding.loops.html
590
+
591
+ def _find_back_edges(self, stats=None):
592
+ """
593
+ Find back edges. An edge (src, dest) is a back edge if and
594
+ only if *dest* dominates *src*.
595
+ """
596
+ # Prepare stats to capture execution information
597
+ if stats is not None:
598
+ if not isinstance(stats, dict):
599
+ raise TypeError(f"*stats* must be a dict; got {type(stats)}")
600
+ stats.setdefault("iteration_count", 0)
601
+
602
+ # Uses a simple DFS to find back-edges.
603
+ # The new algorithm is faster than the the previous dominator based
604
+ # algorithm.
605
+ back_edges = set()
606
+ # stack: keeps track of the traversal path
607
+ stack = []
608
+ # succs_state: keep track of unvisited successors of a node
609
+ succs_state = {}
610
+ entry_point = self.entry_point()
611
+
612
+ checked = set()
613
+
614
+ def push_state(node):
615
+ stack.append(node)
616
+ succs_state[node] = [dest for dest in self._succs[node]]
617
+
618
+ push_state(entry_point)
619
+
620
+ # Keep track for iteration count for debugging
621
+ iter_ct = 0
622
+ while stack:
623
+ iter_ct += 1
624
+ tos = stack[-1]
625
+ tos_succs = succs_state[tos]
626
+ # Are there successors not checked?
627
+ if tos_succs:
628
+ # Check the next successor
629
+ cur_node = tos_succs.pop()
630
+ # Is it in our traversal path?
631
+ if cur_node in stack:
632
+ # Yes, it's a backedge
633
+ back_edges.add((tos, cur_node))
634
+ elif cur_node not in checked:
635
+ # Push
636
+ push_state(cur_node)
637
+ else:
638
+ # Checked all successors. Pop
639
+ stack.pop()
640
+ checked.add(tos)
641
+
642
+ if stats is not None:
643
+ stats["iteration_count"] += iter_ct
644
+ return back_edges
645
+
646
+ def _find_topo_order(self):
647
+ succs = self._succs
648
+ back_edges = self._back_edges
649
+ post_order = []
650
+ seen = set()
651
+
652
+ def _dfs_rec(node):
653
+ if node not in seen:
654
+ seen.add(node)
655
+ for dest in succs[node]:
656
+ if (node, dest) not in back_edges:
657
+ _dfs_rec(dest)
658
+ post_order.append(node)
659
+
660
+ _dfs_rec(self._entry_point)
661
+ post_order.reverse()
662
+ return post_order
663
+
664
+ def _find_descendents(self):
665
+ descs = {}
666
+ for node in reversed(self._topo_order):
667
+ descs[node] = node_descs = set()
668
+ for succ in self._succs[node]:
669
+ if (node, succ) not in self._back_edges:
670
+ node_descs.add(succ)
671
+ node_descs.update(descs[succ])
672
+ return descs
673
+
674
+ def _find_loops(self):
675
+ """
676
+ Find the loops defined by the graph's back edges.
677
+ """
678
+ bodies = {}
679
+ for src, dest in self._back_edges:
680
+ # The destination of the back edge is the loop header
681
+ header = dest
682
+ # Build up the loop body from the back edge's source node,
683
+ # up to the source header.
684
+ body = set([header])
685
+ queue = [src]
686
+ while queue:
687
+ n = queue.pop()
688
+ if n not in body:
689
+ body.add(n)
690
+ queue.extend(self._preds[n])
691
+ # There can be several back edges to a given loop header;
692
+ # if so, merge the resulting body fragments.
693
+ if header in bodies:
694
+ bodies[header].update(body)
695
+ else:
696
+ bodies[header] = body
697
+
698
+ # Create a Loop object for each header.
699
+ loops = {}
700
+ for header, body in bodies.items():
701
+ entries = set()
702
+ exits = set()
703
+ for n in body:
704
+ entries.update(self._preds[n] - body)
705
+ exits.update(self._succs[n] - body)
706
+ loop = Loop(header=header, body=body, entries=entries, exits=exits)
707
+ loops[header] = loop
708
+ return loops
709
+
710
+ def _find_in_loops(self):
711
+ loops = self._loops
712
+ # Compute the loops to which each node belongs.
713
+ in_loops = dict((n, []) for n in self._nodes)
714
+ # Sort loops from longest to shortest
715
+ # This ensures that outer loops will come before inner loops
716
+ for loop in sorted(loops.values(), key=lambda loop: len(loop.body)):
717
+ for n in loop.body:
718
+ in_loops[n].append(loop.header)
719
+ return in_loops
720
+
721
+ def _dump_adj_lists(self, file):
722
+ adj_lists = dict(
723
+ (src, sorted(list(dests))) for src, dests in self._succs.items()
724
+ )
725
+ import pprint
726
+
727
+ pprint.pprint(adj_lists, stream=file)
728
+
729
+ def __eq__(self, other):
730
+ if not isinstance(other, CFGraph):
731
+ return NotImplemented
732
+
733
+ for x in ["_nodes", "_edge_data", "_entry_point", "_preds", "_succs"]:
734
+ this = getattr(self, x, None)
735
+ that = getattr(other, x, None)
736
+ if this != that:
737
+ return False
738
+ return True
739
+
740
+ def __ne__(self, other):
741
+ return not self.__eq__(other)
742
+
743
+
744
+ class ControlFlowAnalysis(object):
745
+ """
746
+ Attributes
747
+ ----------
748
+ - bytecode
749
+
750
+ - blocks
751
+
752
+ - blockseq
753
+
754
+ - doms: dict of set
755
+ Dominators
756
+
757
+ - backbone: set of block offsets
758
+ The set of block that is common to all possible code path.
759
+
760
+ """
761
+
762
+ def __init__(self, bytecode):
763
+ self.bytecode = bytecode
764
+ self.blocks = {}
765
+ self.liveblocks = {}
766
+ self.blockseq = []
767
+ self.doms = None
768
+ self.backbone = None
769
+ # Internal temp states
770
+ self._force_new_block = True
771
+ self._curblock = None
772
+ self._blockstack = []
773
+ self._loops = []
774
+ self._withs = []
775
+
776
+ def iterblocks(self):
777
+ """
778
+ Return all blocks in sequence of occurrence
779
+ """
780
+ for i in self.blockseq:
781
+ yield self.blocks[i]
782
+
783
+ def iterliveblocks(self):
784
+ """
785
+ Return all live blocks in sequence of occurrence
786
+ """
787
+ for i in self.blockseq:
788
+ if i in self.liveblocks:
789
+ yield self.blocks[i]
790
+
791
+ def incoming_blocks(self, block):
792
+ """
793
+ Yield (incoming block, number of stack pops) pairs for *block*.
794
+ """
795
+ for i, pops in block.incoming_jumps.items():
796
+ if i in self.liveblocks:
797
+ yield self.blocks[i], pops
798
+
799
+ def dump(self, file=None):
800
+ self.graph.dump(file=None)
801
+
802
+ def run(self):
803
+ for inst in self._iter_inst():
804
+ fname = "op_%s" % inst.opname
805
+ fn = getattr(self, fname, None)
806
+ if fn is not None:
807
+ fn(inst)
808
+ elif inst.is_jump:
809
+ # this catches e.g. try... except
810
+ l = Loc(self.bytecode.func_id.filename, inst.lineno)
811
+ if inst.opname in {"SETUP_FINALLY"}:
812
+ msg = "'try' block not supported until python3.7 or later"
813
+ else:
814
+ msg = "Use of unsupported opcode (%s) found" % inst.opname
815
+ raise UnsupportedError(msg, loc=l)
816
+ else:
817
+ # Non-jump instructions are ignored
818
+ pass # intentionally
819
+
820
+ # Close all blocks
821
+ for cur, nxt in zip(self.blockseq, self.blockseq[1:]):
822
+ blk = self.blocks[cur]
823
+ if not blk.outgoing_jumps and not blk.terminating:
824
+ blk.outgoing_jumps[nxt] = 0
825
+
826
+ graph = CFGraph()
827
+ for b in self.blocks:
828
+ graph.add_node(b)
829
+ for b in self.blocks.values():
830
+ for out, pops in b.outgoing_jumps.items():
831
+ graph.add_edge(b.offset, out, pops)
832
+ graph.set_entry_point(min(self.blocks))
833
+ graph.process()
834
+ self.graph = graph
835
+
836
+ # Fill incoming
837
+ for b in self.blocks.values():
838
+ for out, pops in b.outgoing_jumps.items():
839
+ self.blocks[out].incoming_jumps[b.offset] = pops
840
+
841
+ # Find liveblocks
842
+ self.liveblocks = dict((i, self.blocks[i]) for i in self.graph.nodes())
843
+
844
+ for lastblk in reversed(self.blockseq):
845
+ if lastblk in self.liveblocks:
846
+ break
847
+ else:
848
+ raise AssertionError("No live block that exits!?")
849
+
850
+ # Find backbone
851
+ backbone = self.graph.backbone()
852
+ # Filter out in loop blocks (Assuming no other cyclic control blocks)
853
+ # This is to unavoid variable defined in loops to be considered as
854
+ # function scope.
855
+ inloopblocks = set()
856
+
857
+ for b in self.blocks.keys():
858
+ if self.graph.in_loops(b):
859
+ inloopblocks.add(b)
860
+
861
+ self.backbone = backbone - inloopblocks
862
+
863
+ def jump(self, target, pops=0):
864
+ """
865
+ Register a jump (conditional or not) to *target* offset.
866
+ *pops* is the number of stack pops implied by the jump (default 0).
867
+ """
868
+ self._curblock.outgoing_jumps[target] = pops
869
+
870
+ def _iter_inst(self):
871
+ for inst in self.bytecode:
872
+ if self._use_new_block(inst):
873
+ self._guard_with_as(inst)
874
+ self._start_new_block(inst)
875
+ self._curblock.body.append(inst.offset)
876
+ yield inst
877
+
878
+ def _use_new_block(self, inst):
879
+ if inst.offset in self.bytecode.labels:
880
+ res = True
881
+ elif inst.opname in NEW_BLOCKERS:
882
+ res = True
883
+ else:
884
+ res = self._force_new_block
885
+
886
+ self._force_new_block = False
887
+ return res
888
+
889
+ def _start_new_block(self, inst):
890
+ self._curblock = CFBlock(inst.offset)
891
+ self.blocks[inst.offset] = self._curblock
892
+ self.blockseq.append(inst.offset)
893
+
894
+ def _guard_with_as(self, current_inst):
895
+ """Checks if the next instruction after a SETUP_WITH is something other
896
+ than a POP_TOP, if it is something else it'll be some sort of store
897
+ which is not supported (this corresponds to `with CTXMGR as VAR(S)`)."""
898
+ if current_inst.opname == "SETUP_WITH":
899
+ next_op = self.bytecode[current_inst.next].opname
900
+ if next_op != "POP_TOP":
901
+ msg = (
902
+ "The 'with (context manager) as "
903
+ "(variable):' construct is not "
904
+ "supported."
905
+ )
906
+ raise UnsupportedError(msg)
907
+
908
+ def op_SETUP_LOOP(self, inst):
909
+ end = inst.get_jump_target()
910
+ self._blockstack.append(end)
911
+ self._loops.append((inst.offset, end))
912
+ # TODO: Looplifting requires the loop entry be its own block.
913
+ # Forcing a new block here is the simplest solution for now.
914
+ # But, we should consider other less ad-hoc ways.
915
+ self.jump(inst.next)
916
+ self._force_new_block = True
917
+
918
+ def op_SETUP_WITH(self, inst):
919
+ end = inst.get_jump_target()
920
+ self._blockstack.append(end)
921
+ self._withs.append((inst.offset, end))
922
+ # TODO: WithLifting requires the loop entry be its own block.
923
+ # Forcing a new block here is the simplest solution for now.
924
+ # But, we should consider other less ad-hoc ways.
925
+ self.jump(inst.next)
926
+ self._force_new_block = True
927
+
928
+ def op_POP_BLOCK(self, inst):
929
+ self._blockstack.pop()
930
+
931
+ def op_FOR_ITER(self, inst):
932
+ self.jump(inst.get_jump_target())
933
+ self.jump(inst.next)
934
+ self._force_new_block = True
935
+
936
+ def _op_ABSOLUTE_JUMP_IF(self, inst):
937
+ self.jump(inst.get_jump_target())
938
+ self.jump(inst.next)
939
+ self._force_new_block = True
940
+
941
+ op_POP_JUMP_IF_FALSE = _op_ABSOLUTE_JUMP_IF
942
+ op_POP_JUMP_IF_TRUE = _op_ABSOLUTE_JUMP_IF
943
+ op_JUMP_IF_FALSE = _op_ABSOLUTE_JUMP_IF
944
+ op_JUMP_IF_TRUE = _op_ABSOLUTE_JUMP_IF
945
+
946
+ op_POP_JUMP_FORWARD_IF_FALSE = _op_ABSOLUTE_JUMP_IF
947
+ op_POP_JUMP_BACKWARD_IF_FALSE = _op_ABSOLUTE_JUMP_IF
948
+ op_POP_JUMP_FORWARD_IF_TRUE = _op_ABSOLUTE_JUMP_IF
949
+ op_POP_JUMP_BACKWARD_IF_TRUE = _op_ABSOLUTE_JUMP_IF
950
+
951
+ def _op_ABSOLUTE_JUMP_OR_POP(self, inst):
952
+ self.jump(inst.get_jump_target())
953
+ self.jump(inst.next, pops=1)
954
+ self._force_new_block = True
955
+
956
+ op_JUMP_IF_FALSE_OR_POP = _op_ABSOLUTE_JUMP_OR_POP
957
+ op_JUMP_IF_TRUE_OR_POP = _op_ABSOLUTE_JUMP_OR_POP
958
+
959
+ def op_JUMP_ABSOLUTE(self, inst):
960
+ self.jump(inst.get_jump_target())
961
+ self._force_new_block = True
962
+
963
+ def op_JUMP_FORWARD(self, inst):
964
+ self.jump(inst.get_jump_target())
965
+ self._force_new_block = True
966
+
967
+ op_JUMP_BACKWARD = op_JUMP_FORWARD
968
+
969
+ def op_RETURN_VALUE(self, inst):
970
+ self._curblock.terminating = True
971
+ self._force_new_block = True
972
+
973
+ if PYVERSION in ((3, 12), (3, 13)):
974
+
975
+ def op_RETURN_CONST(self, inst):
976
+ self._curblock.terminating = True
977
+ self._force_new_block = True
978
+ elif PYVERSION in ((3, 9), (3, 10), (3, 11)):
979
+ pass
980
+ else:
981
+ raise NotImplementedError(PYVERSION)
982
+
983
+ def op_RAISE_VARARGS(self, inst):
984
+ self._curblock.terminating = True
985
+ self._force_new_block = True
986
+
987
+ def op_BREAK_LOOP(self, inst):
988
+ self.jump(self._blockstack[-1])
989
+ self._force_new_block = True