662f462e0f601fcce9aec0bf0aceeab3e0c0e219783432fa02431d37567ec282
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +1 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/ffi.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/initfini.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/linker.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/module.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/object_file.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/options.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/orcjit.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/passmanagers.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/targets.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/transforms.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/__pycache__/value.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/binding/analysis.py +69 -0
- lib/python3.11/site-packages/llvmlite/binding/common.py +34 -0
- lib/python3.11/site-packages/llvmlite/binding/context.py +29 -0
- lib/python3.11/site-packages/llvmlite/binding/dylib.py +45 -0
- lib/python3.11/site-packages/llvmlite/binding/executionengine.py +322 -0
- lib/python3.11/site-packages/llvmlite/binding/ffi.py +388 -0
- lib/python3.11/site-packages/llvmlite/binding/initfini.py +73 -0
- lib/python3.11/site-packages/llvmlite/binding/libllvmlite.dylib +3 -0
- lib/python3.11/site-packages/llvmlite/binding/linker.py +20 -0
- lib/python3.11/site-packages/llvmlite/binding/module.py +349 -0
- lib/python3.11/site-packages/llvmlite/binding/object_file.py +82 -0
- lib/python3.11/site-packages/llvmlite/binding/options.py +17 -0
- lib/python3.11/site-packages/llvmlite/binding/orcjit.py +342 -0
- lib/python3.11/site-packages/llvmlite/binding/passmanagers.py +923 -0
- lib/python3.11/site-packages/llvmlite/binding/targets.py +450 -0
- lib/python3.11/site-packages/llvmlite/binding/transforms.py +151 -0
- lib/python3.11/site-packages/llvmlite/binding/value.py +624 -0
- lib/python3.11/site-packages/llvmlite/ir/__init__.py +11 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/__init__.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/_utils.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/builder.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/context.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/instructions.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/module.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/transforms.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/types.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/__pycache__/values.cpython-311.pyc +0 -0
- lib/python3.11/site-packages/llvmlite/ir/_utils.py +80 -0
- lib/python3.11/site-packages/llvmlite/ir/builder.py +1119 -0
- lib/python3.11/site-packages/llvmlite/ir/context.py +20 -0
- lib/python3.11/site-packages/llvmlite/ir/instructions.py +893 -0
- lib/python3.11/site-packages/llvmlite/ir/module.py +246 -0
- lib/python3.11/site-packages/llvmlite/ir/transforms.py +64 -0
- lib/python3.11/site-packages/llvmlite/ir/types.py +614 -0
- lib/python3.11/site-packages/llvmlite/ir/values.py +1217 -0
- lib/python3.11/site-packages/llvmlite/tests/__init__.py +57 -0
- lib/python3.11/site-packages/llvmlite/tests/__main__.py +3 -0
- lib/python3.11/site-packages/llvmlite/tests/__pycache__/__init__.cpython-311.pyc +0 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
lib/python3.11/site-packages/llvmlite/binding/libllvmlite.dylib filter=lfs diff=lfs merge=lfs -text
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/ffi.cpython-311.pyc
ADDED
|
Binary file (20.4 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/initfini.cpython-311.pyc
ADDED
|
Binary file (3.43 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/linker.cpython-311.pyc
ADDED
|
Binary file (1.27 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/module.cpython-311.pyc
ADDED
|
Binary file (19.9 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/object_file.cpython-311.pyc
ADDED
|
Binary file (6.11 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/options.cpython-311.pyc
ADDED
|
Binary file (1.01 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/orcjit.cpython-311.pyc
ADDED
|
Binary file (18.3 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/passmanagers.cpython-311.pyc
ADDED
|
Binary file (49.6 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/targets.cpython-311.pyc
ADDED
|
Binary file (22.3 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/transforms.cpython-311.pyc
ADDED
|
Binary file (8.33 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/__pycache__/value.cpython-311.pyc
ADDED
|
Binary file (32.1 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/binding/analysis.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
A collection of analysis utilities
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from ctypes import POINTER, c_char_p, c_int
|
| 6 |
+
|
| 7 |
+
from llvmlite.binding import ffi
|
| 8 |
+
from llvmlite.binding.module import parse_assembly
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def get_function_cfg(func, show_inst=True):
|
| 12 |
+
"""Return a string of the control-flow graph of the function in DOT
|
| 13 |
+
format. If the input `func` is not a materialized function, the module
|
| 14 |
+
containing the function is parsed to create an actual LLVM module.
|
| 15 |
+
The `show_inst` flag controls whether the instructions of each block
|
| 16 |
+
are printed.
|
| 17 |
+
"""
|
| 18 |
+
assert func is not None
|
| 19 |
+
from llvmlite import ir
|
| 20 |
+
if isinstance(func, ir.Function):
|
| 21 |
+
mod = parse_assembly(str(func.module))
|
| 22 |
+
func = mod.get_function(func.name)
|
| 23 |
+
|
| 24 |
+
# Assume func is a materialized function
|
| 25 |
+
with ffi.OutputString() as dotstr:
|
| 26 |
+
ffi.lib.LLVMPY_WriteCFG(func, dotstr, show_inst)
|
| 27 |
+
return str(dotstr)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def view_dot_graph(graph, filename=None, view=False):
|
| 31 |
+
"""
|
| 32 |
+
View the given DOT source. If view is True, the image is rendered
|
| 33 |
+
and viewed by the default application in the system. The file path of
|
| 34 |
+
the output is returned. If view is False, a graphviz.Source object is
|
| 35 |
+
returned. If view is False and the environment is in a IPython session,
|
| 36 |
+
an IPython image object is returned and can be displayed inline in the
|
| 37 |
+
notebook.
|
| 38 |
+
|
| 39 |
+
This function requires the graphviz package.
|
| 40 |
+
|
| 41 |
+
Args
|
| 42 |
+
----
|
| 43 |
+
- graph [str]: a DOT source code
|
| 44 |
+
- filename [str]: optional. if given and view is True, this specifies
|
| 45 |
+
the file path for the rendered output to write to.
|
| 46 |
+
- view [bool]: if True, opens the rendered output file.
|
| 47 |
+
|
| 48 |
+
"""
|
| 49 |
+
# Optionally depends on graphviz package
|
| 50 |
+
import graphviz as gv
|
| 51 |
+
|
| 52 |
+
src = gv.Source(graph)
|
| 53 |
+
if view:
|
| 54 |
+
# Returns the output file path
|
| 55 |
+
return src.render(filename, view=view)
|
| 56 |
+
else:
|
| 57 |
+
# Attempts to show the graph in IPython notebook
|
| 58 |
+
try:
|
| 59 |
+
__IPYTHON__
|
| 60 |
+
except NameError:
|
| 61 |
+
return src
|
| 62 |
+
else:
|
| 63 |
+
import IPython.display as display
|
| 64 |
+
format = 'svg'
|
| 65 |
+
return display.SVG(data=src.pipe(format))
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
# Ctypes binding
|
| 69 |
+
ffi.lib.LLVMPY_WriteCFG.argtypes = [ffi.LLVMValueRef, POINTER(c_char_p), c_int]
|
lib/python3.11/site-packages/llvmlite/binding/common.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import atexit
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def _encode_string(s):
|
| 5 |
+
encoded = s.encode('utf-8')
|
| 6 |
+
return encoded
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def _decode_string(b):
|
| 10 |
+
return b.decode('utf-8')
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
_encode_string.__doc__ = """Encode a string for use by LLVM."""
|
| 14 |
+
_decode_string.__doc__ = """Decode a LLVM character (byte)string."""
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
_shutting_down = [False]
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def _at_shutdown():
|
| 21 |
+
_shutting_down[0] = True
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
atexit.register(_at_shutdown)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _is_shutting_down(_shutting_down=_shutting_down):
|
| 28 |
+
"""
|
| 29 |
+
Whether the interpreter is currently shutting down.
|
| 30 |
+
For use in finalizers, __del__ methods, and similar; it is advised
|
| 31 |
+
to early bind this function rather than look it up when calling it,
|
| 32 |
+
since at shutdown module globals may be cleared.
|
| 33 |
+
"""
|
| 34 |
+
return _shutting_down[0]
|
lib/python3.11/site-packages/llvmlite/binding/context.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.binding import ffi
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def create_context():
|
| 5 |
+
return ContextRef(ffi.lib.LLVMPY_ContextCreate())
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def get_global_context():
|
| 9 |
+
return GlobalContextRef(ffi.lib.LLVMPY_GetGlobalContext())
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class ContextRef(ffi.ObjectRef):
|
| 13 |
+
def __init__(self, context_ptr):
|
| 14 |
+
super(ContextRef, self).__init__(context_ptr)
|
| 15 |
+
|
| 16 |
+
def _dispose(self):
|
| 17 |
+
ffi.lib.LLVMPY_ContextDispose(self)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class GlobalContextRef(ContextRef):
|
| 21 |
+
def _dispose(self):
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
ffi.lib.LLVMPY_GetGlobalContext.restype = ffi.LLVMContextRef
|
| 26 |
+
|
| 27 |
+
ffi.lib.LLVMPY_ContextCreate.restype = ffi.LLVMContextRef
|
| 28 |
+
|
| 29 |
+
ffi.lib.LLVMPY_ContextDispose.argtypes = [ffi.LLVMContextRef]
|
lib/python3.11/site-packages/llvmlite/binding/dylib.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import c_void_p, c_char_p, c_bool, POINTER
|
| 2 |
+
|
| 3 |
+
from llvmlite.binding import ffi
|
| 4 |
+
from llvmlite.binding.common import _encode_string
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def address_of_symbol(name):
|
| 8 |
+
"""
|
| 9 |
+
Get the in-process address of symbol named *name*.
|
| 10 |
+
An integer is returned, or None if the symbol isn't found.
|
| 11 |
+
"""
|
| 12 |
+
return ffi.lib.LLVMPY_SearchAddressOfSymbol(_encode_string(name))
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def add_symbol(name, address):
|
| 16 |
+
"""
|
| 17 |
+
Register the *address* of global symbol *name*. This will make
|
| 18 |
+
it usable (e.g. callable) from LLVM-compiled functions.
|
| 19 |
+
"""
|
| 20 |
+
ffi.lib.LLVMPY_AddSymbol(_encode_string(name), c_void_p(address))
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def load_library_permanently(filename):
|
| 24 |
+
"""
|
| 25 |
+
Load an external library
|
| 26 |
+
"""
|
| 27 |
+
with ffi.OutputString() as outerr:
|
| 28 |
+
if ffi.lib.LLVMPY_LoadLibraryPermanently(
|
| 29 |
+
_encode_string(filename), outerr):
|
| 30 |
+
raise RuntimeError(str(outerr))
|
| 31 |
+
|
| 32 |
+
# ============================================================================
|
| 33 |
+
# FFI
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
ffi.lib.LLVMPY_AddSymbol.argtypes = [
|
| 37 |
+
c_char_p,
|
| 38 |
+
c_void_p,
|
| 39 |
+
]
|
| 40 |
+
|
| 41 |
+
ffi.lib.LLVMPY_SearchAddressOfSymbol.argtypes = [c_char_p]
|
| 42 |
+
ffi.lib.LLVMPY_SearchAddressOfSymbol.restype = c_void_p
|
| 43 |
+
|
| 44 |
+
ffi.lib.LLVMPY_LoadLibraryPermanently.argtypes = [c_char_p, POINTER(c_char_p)]
|
| 45 |
+
ffi.lib.LLVMPY_LoadLibraryPermanently.restype = c_bool
|
lib/python3.11/site-packages/llvmlite/binding/executionengine.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import (POINTER, c_char_p, c_bool, c_void_p,
|
| 2 |
+
c_int, c_uint64, c_size_t, CFUNCTYPE, string_at, cast,
|
| 3 |
+
py_object, Structure)
|
| 4 |
+
|
| 5 |
+
from llvmlite.binding import ffi, targets, object_file
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
# Just check these weren't optimized out of the DLL.
|
| 9 |
+
ffi.lib.LLVMPY_LinkInMCJIT
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def create_mcjit_compiler(module, target_machine):
|
| 13 |
+
"""
|
| 14 |
+
Create a MCJIT ExecutionEngine from the given *module* and
|
| 15 |
+
*target_machine*.
|
| 16 |
+
"""
|
| 17 |
+
with ffi.OutputString() as outerr:
|
| 18 |
+
engine = ffi.lib.LLVMPY_CreateMCJITCompiler(
|
| 19 |
+
module, target_machine, outerr)
|
| 20 |
+
if not engine:
|
| 21 |
+
raise RuntimeError(str(outerr))
|
| 22 |
+
|
| 23 |
+
target_machine._owned = True
|
| 24 |
+
return ExecutionEngine(engine, module=module)
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def check_jit_execution():
|
| 28 |
+
"""
|
| 29 |
+
Check the system allows execution of in-memory JITted functions.
|
| 30 |
+
An exception is raised otherwise.
|
| 31 |
+
"""
|
| 32 |
+
errno = ffi.lib.LLVMPY_TryAllocateExecutableMemory()
|
| 33 |
+
if errno != 0:
|
| 34 |
+
raise OSError(errno,
|
| 35 |
+
"cannot allocate executable memory. "
|
| 36 |
+
"This may be due to security restrictions on your "
|
| 37 |
+
"system, such as SELinux or similar mechanisms."
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
class ExecutionEngine(ffi.ObjectRef):
|
| 42 |
+
"""An ExecutionEngine owns all Modules associated with it.
|
| 43 |
+
Deleting the engine will remove all associated modules.
|
| 44 |
+
It is an error to delete the associated modules.
|
| 45 |
+
"""
|
| 46 |
+
_object_cache = None
|
| 47 |
+
|
| 48 |
+
def __init__(self, ptr, module):
|
| 49 |
+
"""
|
| 50 |
+
Module ownership is transferred to the EE
|
| 51 |
+
"""
|
| 52 |
+
self._modules = set([module])
|
| 53 |
+
self._td = None
|
| 54 |
+
module._owned = True
|
| 55 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 56 |
+
|
| 57 |
+
def get_function_address(self, name):
|
| 58 |
+
"""
|
| 59 |
+
Return the address of the function named *name* as an integer.
|
| 60 |
+
|
| 61 |
+
It's a fatal error in LLVM if the symbol of *name* doesn't exist.
|
| 62 |
+
"""
|
| 63 |
+
return ffi.lib.LLVMPY_GetFunctionAddress(self, name.encode("ascii"))
|
| 64 |
+
|
| 65 |
+
def get_global_value_address(self, name):
|
| 66 |
+
"""
|
| 67 |
+
Return the address of the global value named *name* as an integer.
|
| 68 |
+
|
| 69 |
+
It's a fatal error in LLVM if the symbol of *name* doesn't exist.
|
| 70 |
+
"""
|
| 71 |
+
return ffi.lib.LLVMPY_GetGlobalValueAddress(self, name.encode("ascii"))
|
| 72 |
+
|
| 73 |
+
def add_global_mapping(self, gv, addr):
|
| 74 |
+
# XXX unused?
|
| 75 |
+
ffi.lib.LLVMPY_AddGlobalMapping(self, gv, addr)
|
| 76 |
+
|
| 77 |
+
def add_module(self, module):
|
| 78 |
+
"""
|
| 79 |
+
Ownership of module is transferred to the execution engine
|
| 80 |
+
"""
|
| 81 |
+
if module in self._modules:
|
| 82 |
+
raise KeyError("module already added to this engine")
|
| 83 |
+
ffi.lib.LLVMPY_AddModule(self, module)
|
| 84 |
+
module._owned = True
|
| 85 |
+
self._modules.add(module)
|
| 86 |
+
|
| 87 |
+
def finalize_object(self):
|
| 88 |
+
"""
|
| 89 |
+
Make sure all modules owned by the execution engine are fully processed
|
| 90 |
+
and "usable" for execution.
|
| 91 |
+
"""
|
| 92 |
+
ffi.lib.LLVMPY_FinalizeObject(self)
|
| 93 |
+
|
| 94 |
+
def run_static_constructors(self):
|
| 95 |
+
"""
|
| 96 |
+
Run static constructors which initialize module-level static objects.
|
| 97 |
+
"""
|
| 98 |
+
ffi.lib.LLVMPY_RunStaticConstructors(self)
|
| 99 |
+
|
| 100 |
+
def run_static_destructors(self):
|
| 101 |
+
"""
|
| 102 |
+
Run static destructors which perform module-level cleanup of static
|
| 103 |
+
resources.
|
| 104 |
+
"""
|
| 105 |
+
ffi.lib.LLVMPY_RunStaticDestructors(self)
|
| 106 |
+
|
| 107 |
+
def remove_module(self, module):
|
| 108 |
+
"""
|
| 109 |
+
Ownership of module is returned
|
| 110 |
+
"""
|
| 111 |
+
with ffi.OutputString() as outerr:
|
| 112 |
+
if ffi.lib.LLVMPY_RemoveModule(self, module, outerr):
|
| 113 |
+
raise RuntimeError(str(outerr))
|
| 114 |
+
self._modules.remove(module)
|
| 115 |
+
module._owned = False
|
| 116 |
+
|
| 117 |
+
@property
|
| 118 |
+
def target_data(self):
|
| 119 |
+
"""
|
| 120 |
+
The TargetData for this execution engine.
|
| 121 |
+
"""
|
| 122 |
+
if self._td is not None:
|
| 123 |
+
return self._td
|
| 124 |
+
ptr = ffi.lib.LLVMPY_GetExecutionEngineTargetData(self)
|
| 125 |
+
self._td = targets.TargetData(ptr)
|
| 126 |
+
self._td._owned = True
|
| 127 |
+
return self._td
|
| 128 |
+
|
| 129 |
+
def enable_jit_events(self):
|
| 130 |
+
"""
|
| 131 |
+
Enable JIT events for profiling of generated code.
|
| 132 |
+
Return value indicates whether connection to profiling tool
|
| 133 |
+
was successful.
|
| 134 |
+
"""
|
| 135 |
+
ret = ffi.lib.LLVMPY_EnableJITEvents(self)
|
| 136 |
+
return ret
|
| 137 |
+
|
| 138 |
+
def _find_module_ptr(self, module_ptr):
|
| 139 |
+
"""
|
| 140 |
+
Find the ModuleRef corresponding to the given pointer.
|
| 141 |
+
"""
|
| 142 |
+
ptr = cast(module_ptr, c_void_p).value
|
| 143 |
+
for module in self._modules:
|
| 144 |
+
if cast(module._ptr, c_void_p).value == ptr:
|
| 145 |
+
return module
|
| 146 |
+
return None
|
| 147 |
+
|
| 148 |
+
def add_object_file(self, obj_file):
|
| 149 |
+
"""
|
| 150 |
+
Add object file to the jit. object_file can be instance of
|
| 151 |
+
:class:ObjectFile or a string representing file system path
|
| 152 |
+
"""
|
| 153 |
+
if isinstance(obj_file, str):
|
| 154 |
+
obj_file = object_file.ObjectFileRef.from_path(obj_file)
|
| 155 |
+
|
| 156 |
+
ffi.lib.LLVMPY_MCJITAddObjectFile(self, obj_file)
|
| 157 |
+
|
| 158 |
+
def set_object_cache(self, notify_func=None, getbuffer_func=None):
|
| 159 |
+
"""
|
| 160 |
+
Set the object cache "notifyObjectCompiled" and "getBuffer"
|
| 161 |
+
callbacks to the given Python functions.
|
| 162 |
+
"""
|
| 163 |
+
self._object_cache_notify = notify_func
|
| 164 |
+
self._object_cache_getbuffer = getbuffer_func
|
| 165 |
+
# Lifetime of the object cache is managed by us.
|
| 166 |
+
self._object_cache = _ObjectCacheRef(self)
|
| 167 |
+
# Note this doesn't keep a reference to self, to avoid reference
|
| 168 |
+
# cycles.
|
| 169 |
+
ffi.lib.LLVMPY_SetObjectCache(self, self._object_cache)
|
| 170 |
+
|
| 171 |
+
def _raw_object_cache_notify(self, data):
|
| 172 |
+
"""
|
| 173 |
+
Low-level notify hook.
|
| 174 |
+
"""
|
| 175 |
+
if self._object_cache_notify is None:
|
| 176 |
+
return
|
| 177 |
+
module_ptr = data.contents.module_ptr
|
| 178 |
+
buf_ptr = data.contents.buf_ptr
|
| 179 |
+
buf_len = data.contents.buf_len
|
| 180 |
+
buf = string_at(buf_ptr, buf_len)
|
| 181 |
+
module = self._find_module_ptr(module_ptr)
|
| 182 |
+
if module is None:
|
| 183 |
+
# The LLVM EE should only give notifications for modules
|
| 184 |
+
# known by us.
|
| 185 |
+
raise RuntimeError("object compilation notification "
|
| 186 |
+
"for unknown module %s" % (module_ptr,))
|
| 187 |
+
self._object_cache_notify(module, buf)
|
| 188 |
+
|
| 189 |
+
def _raw_object_cache_getbuffer(self, data):
|
| 190 |
+
"""
|
| 191 |
+
Low-level getbuffer hook.
|
| 192 |
+
"""
|
| 193 |
+
if self._object_cache_getbuffer is None:
|
| 194 |
+
return
|
| 195 |
+
module_ptr = data.contents.module_ptr
|
| 196 |
+
module = self._find_module_ptr(module_ptr)
|
| 197 |
+
if module is None:
|
| 198 |
+
# The LLVM EE should only give notifications for modules
|
| 199 |
+
# known by us.
|
| 200 |
+
raise RuntimeError("object compilation notification "
|
| 201 |
+
"for unknown module %s" % (module_ptr,))
|
| 202 |
+
|
| 203 |
+
buf = self._object_cache_getbuffer(module)
|
| 204 |
+
if buf is not None:
|
| 205 |
+
# Create a copy, which will be freed by the caller
|
| 206 |
+
data[0].buf_ptr = ffi.lib.LLVMPY_CreateByteString(buf, len(buf))
|
| 207 |
+
data[0].buf_len = len(buf)
|
| 208 |
+
|
| 209 |
+
def _dispose(self):
|
| 210 |
+
# The modules will be cleaned up by the EE
|
| 211 |
+
for mod in self._modules:
|
| 212 |
+
mod.detach()
|
| 213 |
+
if self._td is not None:
|
| 214 |
+
self._td.detach()
|
| 215 |
+
self._modules.clear()
|
| 216 |
+
self._object_cache = None
|
| 217 |
+
self._capi.LLVMPY_DisposeExecutionEngine(self)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
class _ObjectCacheRef(ffi.ObjectRef):
|
| 221 |
+
"""
|
| 222 |
+
Internal: an ObjectCache instance for use within an ExecutionEngine.
|
| 223 |
+
"""
|
| 224 |
+
|
| 225 |
+
def __init__(self, obj):
|
| 226 |
+
ptr = ffi.lib.LLVMPY_CreateObjectCache(_notify_c_hook,
|
| 227 |
+
_getbuffer_c_hook,
|
| 228 |
+
obj)
|
| 229 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 230 |
+
|
| 231 |
+
def _dispose(self):
|
| 232 |
+
self._capi.LLVMPY_DisposeObjectCache(self)
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
# ============================================================================
|
| 236 |
+
# FFI
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
ffi.lib.LLVMPY_CreateMCJITCompiler.argtypes = [
|
| 240 |
+
ffi.LLVMModuleRef,
|
| 241 |
+
ffi.LLVMTargetMachineRef,
|
| 242 |
+
POINTER(c_char_p),
|
| 243 |
+
]
|
| 244 |
+
ffi.lib.LLVMPY_CreateMCJITCompiler.restype = ffi.LLVMExecutionEngineRef
|
| 245 |
+
|
| 246 |
+
ffi.lib.LLVMPY_RemoveModule.argtypes = [
|
| 247 |
+
ffi.LLVMExecutionEngineRef,
|
| 248 |
+
ffi.LLVMModuleRef,
|
| 249 |
+
POINTER(c_char_p),
|
| 250 |
+
]
|
| 251 |
+
ffi.lib.LLVMPY_RemoveModule.restype = c_bool
|
| 252 |
+
|
| 253 |
+
ffi.lib.LLVMPY_AddModule.argtypes = [
|
| 254 |
+
ffi.LLVMExecutionEngineRef,
|
| 255 |
+
ffi.LLVMModuleRef
|
| 256 |
+
]
|
| 257 |
+
|
| 258 |
+
ffi.lib.LLVMPY_AddGlobalMapping.argtypes = [ffi.LLVMExecutionEngineRef,
|
| 259 |
+
ffi.LLVMValueRef,
|
| 260 |
+
c_void_p]
|
| 261 |
+
|
| 262 |
+
ffi.lib.LLVMPY_FinalizeObject.argtypes = [ffi.LLVMExecutionEngineRef]
|
| 263 |
+
|
| 264 |
+
ffi.lib.LLVMPY_GetExecutionEngineTargetData.argtypes = [
|
| 265 |
+
ffi.LLVMExecutionEngineRef
|
| 266 |
+
]
|
| 267 |
+
ffi.lib.LLVMPY_GetExecutionEngineTargetData.restype = ffi.LLVMTargetDataRef
|
| 268 |
+
|
| 269 |
+
ffi.lib.LLVMPY_TryAllocateExecutableMemory.argtypes = []
|
| 270 |
+
ffi.lib.LLVMPY_TryAllocateExecutableMemory.restype = c_int
|
| 271 |
+
|
| 272 |
+
ffi.lib.LLVMPY_GetFunctionAddress.argtypes = [
|
| 273 |
+
ffi.LLVMExecutionEngineRef,
|
| 274 |
+
c_char_p
|
| 275 |
+
]
|
| 276 |
+
ffi.lib.LLVMPY_GetFunctionAddress.restype = c_uint64
|
| 277 |
+
|
| 278 |
+
ffi.lib.LLVMPY_GetGlobalValueAddress.argtypes = [
|
| 279 |
+
ffi.LLVMExecutionEngineRef,
|
| 280 |
+
c_char_p
|
| 281 |
+
]
|
| 282 |
+
ffi.lib.LLVMPY_GetGlobalValueAddress.restype = c_uint64
|
| 283 |
+
|
| 284 |
+
ffi.lib.LLVMPY_MCJITAddObjectFile.argtypes = [
|
| 285 |
+
ffi.LLVMExecutionEngineRef,
|
| 286 |
+
ffi.LLVMObjectFileRef
|
| 287 |
+
]
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
class _ObjectCacheData(Structure):
|
| 291 |
+
_fields_ = [
|
| 292 |
+
('module_ptr', ffi.LLVMModuleRef),
|
| 293 |
+
('buf_ptr', c_void_p),
|
| 294 |
+
('buf_len', c_size_t),
|
| 295 |
+
]
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
_ObjectCacheNotifyFunc = CFUNCTYPE(None, py_object,
|
| 299 |
+
POINTER(_ObjectCacheData))
|
| 300 |
+
_ObjectCacheGetBufferFunc = CFUNCTYPE(None, py_object,
|
| 301 |
+
POINTER(_ObjectCacheData))
|
| 302 |
+
|
| 303 |
+
# XXX The ctypes function wrappers are created at the top-level, otherwise
|
| 304 |
+
# there are issues when creating CFUNCTYPEs in child processes on CentOS 5
|
| 305 |
+
# 32 bits.
|
| 306 |
+
_notify_c_hook = _ObjectCacheNotifyFunc(
|
| 307 |
+
ExecutionEngine._raw_object_cache_notify)
|
| 308 |
+
_getbuffer_c_hook = _ObjectCacheGetBufferFunc(
|
| 309 |
+
ExecutionEngine._raw_object_cache_getbuffer)
|
| 310 |
+
|
| 311 |
+
ffi.lib.LLVMPY_CreateObjectCache.argtypes = [_ObjectCacheNotifyFunc,
|
| 312 |
+
_ObjectCacheGetBufferFunc,
|
| 313 |
+
py_object]
|
| 314 |
+
ffi.lib.LLVMPY_CreateObjectCache.restype = ffi.LLVMObjectCacheRef
|
| 315 |
+
|
| 316 |
+
ffi.lib.LLVMPY_DisposeObjectCache.argtypes = [ffi.LLVMObjectCacheRef]
|
| 317 |
+
|
| 318 |
+
ffi.lib.LLVMPY_SetObjectCache.argtypes = [ffi.LLVMExecutionEngineRef,
|
| 319 |
+
ffi.LLVMObjectCacheRef]
|
| 320 |
+
|
| 321 |
+
ffi.lib.LLVMPY_CreateByteString.restype = c_void_p
|
| 322 |
+
ffi.lib.LLVMPY_CreateByteString.argtypes = [c_void_p, c_size_t]
|
lib/python3.11/site-packages/llvmlite/binding/ffi.py
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
import ctypes
|
| 3 |
+
import threading
|
| 4 |
+
import importlib.resources as _impres
|
| 5 |
+
|
| 6 |
+
from llvmlite.binding.common import _decode_string, _is_shutting_down
|
| 7 |
+
from llvmlite.utils import get_library_name
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def _make_opaque_ref(name):
|
| 11 |
+
newcls = type(name, (ctypes.Structure,), {})
|
| 12 |
+
return ctypes.POINTER(newcls)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
LLVMContextRef = _make_opaque_ref("LLVMContext")
|
| 16 |
+
LLVMModuleRef = _make_opaque_ref("LLVMModule")
|
| 17 |
+
LLVMValueRef = _make_opaque_ref("LLVMValue")
|
| 18 |
+
LLVMTypeRef = _make_opaque_ref("LLVMType")
|
| 19 |
+
LLVMExecutionEngineRef = _make_opaque_ref("LLVMExecutionEngine")
|
| 20 |
+
LLVMPassManagerBuilderRef = _make_opaque_ref("LLVMPassManagerBuilder")
|
| 21 |
+
LLVMPassManagerRef = _make_opaque_ref("LLVMPassManager")
|
| 22 |
+
LLVMTargetDataRef = _make_opaque_ref("LLVMTargetData")
|
| 23 |
+
LLVMTargetLibraryInfoRef = _make_opaque_ref("LLVMTargetLibraryInfo")
|
| 24 |
+
LLVMTargetRef = _make_opaque_ref("LLVMTarget")
|
| 25 |
+
LLVMTargetMachineRef = _make_opaque_ref("LLVMTargetMachine")
|
| 26 |
+
LLVMMemoryBufferRef = _make_opaque_ref("LLVMMemoryBuffer")
|
| 27 |
+
LLVMAttributeListIterator = _make_opaque_ref("LLVMAttributeListIterator")
|
| 28 |
+
LLVMAttributeSetIterator = _make_opaque_ref("LLVMAttributeSetIterator")
|
| 29 |
+
LLVMGlobalsIterator = _make_opaque_ref("LLVMGlobalsIterator")
|
| 30 |
+
LLVMFunctionsIterator = _make_opaque_ref("LLVMFunctionsIterator")
|
| 31 |
+
LLVMBlocksIterator = _make_opaque_ref("LLVMBlocksIterator")
|
| 32 |
+
LLVMArgumentsIterator = _make_opaque_ref("LLVMArgumentsIterator")
|
| 33 |
+
LLVMInstructionsIterator = _make_opaque_ref("LLVMInstructionsIterator")
|
| 34 |
+
LLVMOperandsIterator = _make_opaque_ref("LLVMOperandsIterator")
|
| 35 |
+
LLVMTypesIterator = _make_opaque_ref("LLVMTypesIterator")
|
| 36 |
+
LLVMObjectCacheRef = _make_opaque_ref("LLVMObjectCache")
|
| 37 |
+
LLVMObjectFileRef = _make_opaque_ref("LLVMObjectFile")
|
| 38 |
+
LLVMSectionIteratorRef = _make_opaque_ref("LLVMSectionIterator")
|
| 39 |
+
LLVMOrcLLJITRef = _make_opaque_ref("LLVMOrcLLJITRef")
|
| 40 |
+
LLVMOrcDylibTrackerRef = _make_opaque_ref("LLVMOrcDylibTrackerRef")
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class _LLVMLock:
|
| 44 |
+
"""A Lock to guarantee thread-safety for the LLVM C-API.
|
| 45 |
+
|
| 46 |
+
This class implements __enter__ and __exit__ for acquiring and releasing
|
| 47 |
+
the lock as a context manager.
|
| 48 |
+
|
| 49 |
+
Also, callbacks can be attached so that every time the lock is acquired
|
| 50 |
+
and released the corresponding callbacks will be invoked.
|
| 51 |
+
"""
|
| 52 |
+
def __init__(self):
|
| 53 |
+
# The reentrant lock is needed for callbacks that re-enter
|
| 54 |
+
# the Python interpreter.
|
| 55 |
+
self._lock = threading.RLock()
|
| 56 |
+
self._cblist = []
|
| 57 |
+
|
| 58 |
+
def register(self, acq_fn, rel_fn):
|
| 59 |
+
"""Register callbacks that are invoked immediately after the lock is
|
| 60 |
+
acquired (``acq_fn()``) and immediately before the lock is released
|
| 61 |
+
(``rel_fn()``).
|
| 62 |
+
"""
|
| 63 |
+
self._cblist.append((acq_fn, rel_fn))
|
| 64 |
+
|
| 65 |
+
def unregister(self, acq_fn, rel_fn):
|
| 66 |
+
"""Remove the registered callbacks.
|
| 67 |
+
"""
|
| 68 |
+
self._cblist.remove((acq_fn, rel_fn))
|
| 69 |
+
|
| 70 |
+
def __enter__(self):
|
| 71 |
+
self._lock.acquire()
|
| 72 |
+
# Invoke all callbacks
|
| 73 |
+
for acq_fn, rel_fn in self._cblist:
|
| 74 |
+
acq_fn()
|
| 75 |
+
|
| 76 |
+
def __exit__(self, *exc_details):
|
| 77 |
+
# Invoke all callbacks
|
| 78 |
+
for acq_fn, rel_fn in self._cblist:
|
| 79 |
+
rel_fn()
|
| 80 |
+
self._lock.release()
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class _suppress_cleanup_errors:
|
| 84 |
+
def __init__(self, context):
|
| 85 |
+
self._context = context
|
| 86 |
+
|
| 87 |
+
def __enter__(self):
|
| 88 |
+
return self._context.__enter__()
|
| 89 |
+
|
| 90 |
+
def __exit__(self, exc_type, exc_value, traceback):
|
| 91 |
+
try:
|
| 92 |
+
return self._context.__exit__(exc_type, exc_value, traceback)
|
| 93 |
+
except PermissionError:
|
| 94 |
+
pass # Resource dylibs can't be deleted on Windows.
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
class _lib_wrapper(object):
|
| 98 |
+
"""Wrap libllvmlite with a lock such that only one thread may access it at
|
| 99 |
+
a time.
|
| 100 |
+
|
| 101 |
+
This class duck-types a CDLL.
|
| 102 |
+
"""
|
| 103 |
+
__slots__ = ['_lib_handle', '_fntab', '_lock']
|
| 104 |
+
|
| 105 |
+
def __init__(self):
|
| 106 |
+
self._lib_handle = None
|
| 107 |
+
self._fntab = {}
|
| 108 |
+
self._lock = _LLVMLock()
|
| 109 |
+
|
| 110 |
+
def _load_lib(self):
|
| 111 |
+
try:
|
| 112 |
+
with _suppress_cleanup_errors(_importlib_resources_path(
|
| 113 |
+
__name__.rpartition(".")[0],
|
| 114 |
+
get_library_name())) as lib_path:
|
| 115 |
+
self._lib_handle = ctypes.CDLL(str(lib_path))
|
| 116 |
+
# Check that we can look up expected symbols.
|
| 117 |
+
_ = self._lib_handle.LLVMPY_GetVersionInfo()
|
| 118 |
+
except (OSError, AttributeError) as e:
|
| 119 |
+
# OSError may be raised if the file cannot be opened, or is not
|
| 120 |
+
# a shared library.
|
| 121 |
+
# AttributeError is raised if LLVMPY_GetVersionInfo does not
|
| 122 |
+
# exist.
|
| 123 |
+
raise OSError("Could not find/load shared object file") from e
|
| 124 |
+
|
| 125 |
+
@property
|
| 126 |
+
def _lib(self):
|
| 127 |
+
# Not threadsafe.
|
| 128 |
+
if not self._lib_handle:
|
| 129 |
+
self._load_lib()
|
| 130 |
+
return self._lib_handle
|
| 131 |
+
|
| 132 |
+
def __getattr__(self, name):
|
| 133 |
+
try:
|
| 134 |
+
return self._fntab[name]
|
| 135 |
+
except KeyError:
|
| 136 |
+
# Lazily wraps new functions as they are requested
|
| 137 |
+
cfn = getattr(self._lib, name)
|
| 138 |
+
wrapped = _lib_fn_wrapper(self._lock, cfn)
|
| 139 |
+
self._fntab[name] = wrapped
|
| 140 |
+
return wrapped
|
| 141 |
+
|
| 142 |
+
@property
|
| 143 |
+
def _name(self):
|
| 144 |
+
"""The name of the library passed in the CDLL constructor.
|
| 145 |
+
|
| 146 |
+
For duck-typing a ctypes.CDLL
|
| 147 |
+
"""
|
| 148 |
+
return self._lib._name
|
| 149 |
+
|
| 150 |
+
@property
|
| 151 |
+
def _handle(self):
|
| 152 |
+
"""The system handle used to access the library.
|
| 153 |
+
|
| 154 |
+
For duck-typing a ctypes.CDLL
|
| 155 |
+
"""
|
| 156 |
+
return self._lib._handle
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
class _lib_fn_wrapper(object):
|
| 160 |
+
"""Wraps and duck-types a ctypes.CFUNCTYPE to provide
|
| 161 |
+
automatic locking when the wrapped function is called.
|
| 162 |
+
|
| 163 |
+
TODO: we can add methods to mark the function as threadsafe
|
| 164 |
+
and remove the locking-step on call when marked.
|
| 165 |
+
"""
|
| 166 |
+
__slots__ = ['_lock', '_cfn']
|
| 167 |
+
|
| 168 |
+
def __init__(self, lock, cfn):
|
| 169 |
+
self._lock = lock
|
| 170 |
+
self._cfn = cfn
|
| 171 |
+
|
| 172 |
+
@property
|
| 173 |
+
def argtypes(self):
|
| 174 |
+
return self._cfn.argtypes
|
| 175 |
+
|
| 176 |
+
@argtypes.setter
|
| 177 |
+
def argtypes(self, argtypes):
|
| 178 |
+
self._cfn.argtypes = argtypes
|
| 179 |
+
|
| 180 |
+
@property
|
| 181 |
+
def restype(self):
|
| 182 |
+
return self._cfn.restype
|
| 183 |
+
|
| 184 |
+
@restype.setter
|
| 185 |
+
def restype(self, restype):
|
| 186 |
+
self._cfn.restype = restype
|
| 187 |
+
|
| 188 |
+
def __call__(self, *args, **kwargs):
|
| 189 |
+
with self._lock:
|
| 190 |
+
return self._cfn(*args, **kwargs)
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
def _importlib_resources_path_repl(package, resource):
|
| 194 |
+
"""Replacement implementation of `import.resources.path` to avoid
|
| 195 |
+
deprecation warning following code at importlib_resources/_legacy.py
|
| 196 |
+
as suggested by https://importlib-resources.readthedocs.io/en/latest/using.html#migrating-from-legacy
|
| 197 |
+
|
| 198 |
+
Notes on differences from importlib.resources implementation:
|
| 199 |
+
|
| 200 |
+
The `_common.normalize_path(resource)` call is skipped because it is an
|
| 201 |
+
internal API and it is unnecessary for the use here. What it does is
|
| 202 |
+
ensuring `resource` is a str and that it does not contain path separators.
|
| 203 |
+
""" # noqa E501
|
| 204 |
+
return _impres.as_file(_impres.files(package) / resource)
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
_importlib_resources_path = (_importlib_resources_path_repl
|
| 208 |
+
if sys.version_info[:2] >= (3, 9)
|
| 209 |
+
else _impres.path)
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
lib = _lib_wrapper()
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
def register_lock_callback(acq_fn, rel_fn):
|
| 216 |
+
"""Register callback functions for lock acquire and release.
|
| 217 |
+
*acq_fn* and *rel_fn* are callables that take no arguments.
|
| 218 |
+
"""
|
| 219 |
+
lib._lock.register(acq_fn, rel_fn)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def unregister_lock_callback(acq_fn, rel_fn):
|
| 223 |
+
"""Remove the registered callback functions for lock acquire and release.
|
| 224 |
+
The arguments are the same as used in `register_lock_callback()`.
|
| 225 |
+
"""
|
| 226 |
+
lib._lock.unregister(acq_fn, rel_fn)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
class _DeadPointer(object):
|
| 230 |
+
"""
|
| 231 |
+
Dummy class to make error messages more helpful.
|
| 232 |
+
"""
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
class OutputString(object):
|
| 236 |
+
"""
|
| 237 |
+
Object for managing the char* output of LLVM APIs.
|
| 238 |
+
"""
|
| 239 |
+
_as_parameter_ = _DeadPointer()
|
| 240 |
+
|
| 241 |
+
@classmethod
|
| 242 |
+
def from_return(cls, ptr):
|
| 243 |
+
"""Constructing from a pointer returned from the C-API.
|
| 244 |
+
The pointer must be allocated with LLVMPY_CreateString.
|
| 245 |
+
|
| 246 |
+
Note
|
| 247 |
+
----
|
| 248 |
+
Because ctypes auto-converts *restype* of *c_char_p* into a python
|
| 249 |
+
string, we must use *c_void_p* to obtain the raw pointer.
|
| 250 |
+
"""
|
| 251 |
+
return cls(init=ctypes.cast(ptr, ctypes.c_char_p))
|
| 252 |
+
|
| 253 |
+
def __init__(self, owned=True, init=None):
|
| 254 |
+
self._ptr = init if init is not None else ctypes.c_char_p(None)
|
| 255 |
+
self._as_parameter_ = ctypes.byref(self._ptr)
|
| 256 |
+
self._owned = owned
|
| 257 |
+
|
| 258 |
+
def close(self):
|
| 259 |
+
if self._ptr is not None:
|
| 260 |
+
if self._owned:
|
| 261 |
+
lib.LLVMPY_DisposeString(self._ptr)
|
| 262 |
+
self._ptr = None
|
| 263 |
+
del self._as_parameter_
|
| 264 |
+
|
| 265 |
+
def __enter__(self):
|
| 266 |
+
return self
|
| 267 |
+
|
| 268 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 269 |
+
self.close()
|
| 270 |
+
|
| 271 |
+
def __del__(self, _is_shutting_down=_is_shutting_down):
|
| 272 |
+
# Avoid errors trying to rely on globals and modules at interpreter
|
| 273 |
+
# shutdown.
|
| 274 |
+
if not _is_shutting_down():
|
| 275 |
+
if self.close is not None:
|
| 276 |
+
self.close()
|
| 277 |
+
|
| 278 |
+
def __str__(self):
|
| 279 |
+
if self._ptr is None:
|
| 280 |
+
return "<dead OutputString>"
|
| 281 |
+
s = self._ptr.value
|
| 282 |
+
assert s is not None
|
| 283 |
+
return _decode_string(s)
|
| 284 |
+
|
| 285 |
+
def __bool__(self):
|
| 286 |
+
return bool(self._ptr)
|
| 287 |
+
|
| 288 |
+
__nonzero__ = __bool__
|
| 289 |
+
|
| 290 |
+
@property
|
| 291 |
+
def bytes(self):
|
| 292 |
+
"""Get the raw bytes of content of the char pointer.
|
| 293 |
+
"""
|
| 294 |
+
return self._ptr.value
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
def ret_string(ptr):
|
| 298 |
+
"""To wrap string return-value from C-API.
|
| 299 |
+
"""
|
| 300 |
+
if ptr is not None:
|
| 301 |
+
return str(OutputString.from_return(ptr))
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def ret_bytes(ptr):
|
| 305 |
+
"""To wrap bytes return-value from C-API.
|
| 306 |
+
"""
|
| 307 |
+
if ptr is not None:
|
| 308 |
+
return OutputString.from_return(ptr).bytes
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
class ObjectRef(object):
|
| 312 |
+
"""
|
| 313 |
+
A wrapper around a ctypes pointer to a LLVM object ("resource").
|
| 314 |
+
"""
|
| 315 |
+
_closed = False
|
| 316 |
+
_as_parameter_ = _DeadPointer()
|
| 317 |
+
# Whether this object pointer is owned by another one.
|
| 318 |
+
_owned = False
|
| 319 |
+
|
| 320 |
+
def __init__(self, ptr):
|
| 321 |
+
if ptr is None:
|
| 322 |
+
raise ValueError("NULL pointer")
|
| 323 |
+
self._ptr = ptr
|
| 324 |
+
self._as_parameter_ = ptr
|
| 325 |
+
self._capi = lib
|
| 326 |
+
|
| 327 |
+
def close(self):
|
| 328 |
+
"""
|
| 329 |
+
Close this object and do any required clean-up actions.
|
| 330 |
+
"""
|
| 331 |
+
try:
|
| 332 |
+
if not self._closed and not self._owned:
|
| 333 |
+
self._dispose()
|
| 334 |
+
finally:
|
| 335 |
+
self.detach()
|
| 336 |
+
|
| 337 |
+
def detach(self):
|
| 338 |
+
"""
|
| 339 |
+
Detach the underlying LLVM resource without disposing of it.
|
| 340 |
+
"""
|
| 341 |
+
if not self._closed:
|
| 342 |
+
del self._as_parameter_
|
| 343 |
+
self._closed = True
|
| 344 |
+
self._ptr = None
|
| 345 |
+
|
| 346 |
+
def _dispose(self):
|
| 347 |
+
"""
|
| 348 |
+
Dispose of the underlying LLVM resource. Should be overriden
|
| 349 |
+
by subclasses. Automatically called by close(), __del__() and
|
| 350 |
+
__exit__() (unless the resource has been detached).
|
| 351 |
+
"""
|
| 352 |
+
|
| 353 |
+
@property
|
| 354 |
+
def closed(self):
|
| 355 |
+
"""
|
| 356 |
+
Whether this object has been closed. A closed object can't
|
| 357 |
+
be used anymore.
|
| 358 |
+
"""
|
| 359 |
+
return self._closed
|
| 360 |
+
|
| 361 |
+
def __enter__(self):
|
| 362 |
+
assert hasattr(self, "close")
|
| 363 |
+
if self._closed:
|
| 364 |
+
raise RuntimeError("%s instance already closed" % (self.__class__,))
|
| 365 |
+
return self
|
| 366 |
+
|
| 367 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 368 |
+
self.close()
|
| 369 |
+
|
| 370 |
+
def __del__(self, _is_shutting_down=_is_shutting_down):
|
| 371 |
+
if not _is_shutting_down():
|
| 372 |
+
if self.close is not None:
|
| 373 |
+
self.close()
|
| 374 |
+
|
| 375 |
+
def __bool__(self):
|
| 376 |
+
return bool(self._ptr)
|
| 377 |
+
|
| 378 |
+
def __eq__(self, other):
|
| 379 |
+
if not hasattr(other, "_ptr"):
|
| 380 |
+
return False
|
| 381 |
+
return ctypes.addressof(self._ptr[0]) == \
|
| 382 |
+
ctypes.addressof(other._ptr[0])
|
| 383 |
+
|
| 384 |
+
__nonzero__ = __bool__
|
| 385 |
+
|
| 386 |
+
# XXX useful?
|
| 387 |
+
def __hash__(self):
|
| 388 |
+
return hash(ctypes.cast(self._ptr, ctypes.c_void_p).value)
|
lib/python3.11/site-packages/llvmlite/binding/initfini.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import c_uint
|
| 2 |
+
|
| 3 |
+
from llvmlite.binding import ffi
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def initialize():
|
| 7 |
+
"""
|
| 8 |
+
Initialize the LLVM core.
|
| 9 |
+
"""
|
| 10 |
+
ffi.lib.LLVMPY_InitializeCore()
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def initialize_all_targets():
|
| 14 |
+
"""
|
| 15 |
+
Initialize all targets. Necessary before targets can be looked up
|
| 16 |
+
via the :class:`Target` class.
|
| 17 |
+
"""
|
| 18 |
+
ffi.lib.LLVMPY_InitializeAllTargetInfos()
|
| 19 |
+
ffi.lib.LLVMPY_InitializeAllTargets()
|
| 20 |
+
ffi.lib.LLVMPY_InitializeAllTargetMCs()
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def initialize_all_asmprinters():
|
| 24 |
+
"""
|
| 25 |
+
Initialize all code generators. Necessary before generating
|
| 26 |
+
any assembly or machine code via the :meth:`TargetMachine.emit_object`
|
| 27 |
+
and :meth:`TargetMachine.emit_assembly` methods.
|
| 28 |
+
"""
|
| 29 |
+
ffi.lib.LLVMPY_InitializeAllAsmPrinters()
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def initialize_native_target():
|
| 33 |
+
"""
|
| 34 |
+
Initialize the native (host) target. Necessary before doing any
|
| 35 |
+
code generation.
|
| 36 |
+
"""
|
| 37 |
+
ffi.lib.LLVMPY_InitializeNativeTarget()
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def initialize_native_asmprinter():
|
| 41 |
+
"""
|
| 42 |
+
Initialize the native ASM printer.
|
| 43 |
+
"""
|
| 44 |
+
ffi.lib.LLVMPY_InitializeNativeAsmPrinter()
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def initialize_native_asmparser():
|
| 48 |
+
"""
|
| 49 |
+
Initialize the native ASM parser.
|
| 50 |
+
"""
|
| 51 |
+
ffi.lib.LLVMPY_InitializeNativeAsmParser()
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def shutdown():
|
| 55 |
+
ffi.lib.LLVMPY_Shutdown()
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
# =============================================================================
|
| 59 |
+
# Set function FFI
|
| 60 |
+
|
| 61 |
+
ffi.lib.LLVMPY_GetVersionInfo.restype = c_uint
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _version_info():
|
| 65 |
+
v = []
|
| 66 |
+
x = ffi.lib.LLVMPY_GetVersionInfo()
|
| 67 |
+
while x:
|
| 68 |
+
v.append(x & 0xff)
|
| 69 |
+
x >>= 8
|
| 70 |
+
return tuple(reversed(v))
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
llvm_version_info = _version_info()
|
lib/python3.11/site-packages/llvmlite/binding/libllvmlite.dylib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3357cc66e6582cf25850ce9b1f710cbe4160f871a90c8bbe96cfd87fe857ea30
|
| 3 |
+
size 91363294
|
lib/python3.11/site-packages/llvmlite/binding/linker.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import c_int, c_char_p, POINTER
|
| 2 |
+
from llvmlite.binding import ffi
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def link_modules(dst, src):
|
| 6 |
+
with ffi.OutputString() as outerr:
|
| 7 |
+
err = ffi.lib.LLVMPY_LinkModules(dst, src, outerr)
|
| 8 |
+
# The underlying module was destroyed
|
| 9 |
+
src.detach()
|
| 10 |
+
if err:
|
| 11 |
+
raise RuntimeError(str(outerr))
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
ffi.lib.LLVMPY_LinkModules.argtypes = [
|
| 15 |
+
ffi.LLVMModuleRef,
|
| 16 |
+
ffi.LLVMModuleRef,
|
| 17 |
+
POINTER(c_char_p),
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
ffi.lib.LLVMPY_LinkModules.restype = c_int
|
lib/python3.11/site-packages/llvmlite/binding/module.py
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import (c_char_p, byref, POINTER, c_bool, create_string_buffer,
|
| 2 |
+
c_size_t, string_at)
|
| 3 |
+
|
| 4 |
+
from llvmlite.binding import ffi
|
| 5 |
+
from llvmlite.binding.linker import link_modules
|
| 6 |
+
from llvmlite.binding.common import _decode_string, _encode_string
|
| 7 |
+
from llvmlite.binding.value import ValueRef, TypeRef
|
| 8 |
+
from llvmlite.binding.context import get_global_context
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def parse_assembly(llvmir, context=None):
|
| 12 |
+
"""
|
| 13 |
+
Create Module from a LLVM IR string
|
| 14 |
+
"""
|
| 15 |
+
if context is None:
|
| 16 |
+
context = get_global_context()
|
| 17 |
+
llvmir = _encode_string(llvmir)
|
| 18 |
+
strbuf = c_char_p(llvmir)
|
| 19 |
+
with ffi.OutputString() as errmsg:
|
| 20 |
+
mod = ModuleRef(
|
| 21 |
+
ffi.lib.LLVMPY_ParseAssembly(context, strbuf, errmsg),
|
| 22 |
+
context)
|
| 23 |
+
if errmsg:
|
| 24 |
+
mod.close()
|
| 25 |
+
raise RuntimeError("LLVM IR parsing error\n{0}".format(errmsg))
|
| 26 |
+
return mod
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def parse_bitcode(bitcode, context=None):
|
| 30 |
+
"""
|
| 31 |
+
Create Module from a LLVM *bitcode* (a bytes object).
|
| 32 |
+
"""
|
| 33 |
+
if context is None:
|
| 34 |
+
context = get_global_context()
|
| 35 |
+
buf = c_char_p(bitcode)
|
| 36 |
+
bufsize = len(bitcode)
|
| 37 |
+
with ffi.OutputString() as errmsg:
|
| 38 |
+
mod = ModuleRef(ffi.lib.LLVMPY_ParseBitcode(
|
| 39 |
+
context, buf, bufsize, errmsg), context)
|
| 40 |
+
if errmsg:
|
| 41 |
+
mod.close()
|
| 42 |
+
raise RuntimeError(
|
| 43 |
+
"LLVM bitcode parsing error\n{0}".format(errmsg))
|
| 44 |
+
return mod
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
class ModuleRef(ffi.ObjectRef):
|
| 48 |
+
"""
|
| 49 |
+
A reference to a LLVM module.
|
| 50 |
+
"""
|
| 51 |
+
|
| 52 |
+
def __init__(self, module_ptr, context):
|
| 53 |
+
super(ModuleRef, self).__init__(module_ptr)
|
| 54 |
+
self._context = context
|
| 55 |
+
|
| 56 |
+
def __str__(self):
|
| 57 |
+
with ffi.OutputString() as outstr:
|
| 58 |
+
ffi.lib.LLVMPY_PrintModuleToString(self, outstr)
|
| 59 |
+
return str(outstr)
|
| 60 |
+
|
| 61 |
+
def as_bitcode(self):
|
| 62 |
+
"""
|
| 63 |
+
Return the module's LLVM bitcode, as a bytes object.
|
| 64 |
+
"""
|
| 65 |
+
ptr = c_char_p(None)
|
| 66 |
+
size = c_size_t(-1)
|
| 67 |
+
ffi.lib.LLVMPY_WriteBitcodeToString(self, byref(ptr), byref(size))
|
| 68 |
+
if not ptr:
|
| 69 |
+
raise MemoryError
|
| 70 |
+
try:
|
| 71 |
+
assert size.value >= 0
|
| 72 |
+
return string_at(ptr, size.value)
|
| 73 |
+
finally:
|
| 74 |
+
ffi.lib.LLVMPY_DisposeString(ptr)
|
| 75 |
+
|
| 76 |
+
def _dispose(self):
|
| 77 |
+
self._capi.LLVMPY_DisposeModule(self)
|
| 78 |
+
|
| 79 |
+
def get_function(self, name):
|
| 80 |
+
"""
|
| 81 |
+
Get a ValueRef pointing to the function named *name*.
|
| 82 |
+
NameError is raised if the symbol isn't found.
|
| 83 |
+
"""
|
| 84 |
+
p = ffi.lib.LLVMPY_GetNamedFunction(self, _encode_string(name))
|
| 85 |
+
if not p:
|
| 86 |
+
raise NameError(name)
|
| 87 |
+
return ValueRef(p, 'function', dict(module=self))
|
| 88 |
+
|
| 89 |
+
def get_global_variable(self, name):
|
| 90 |
+
"""
|
| 91 |
+
Get a ValueRef pointing to the global variable named *name*.
|
| 92 |
+
NameError is raised if the symbol isn't found.
|
| 93 |
+
"""
|
| 94 |
+
p = ffi.lib.LLVMPY_GetNamedGlobalVariable(self, _encode_string(name))
|
| 95 |
+
if not p:
|
| 96 |
+
raise NameError(name)
|
| 97 |
+
return ValueRef(p, 'global', dict(module=self))
|
| 98 |
+
|
| 99 |
+
def get_struct_type(self, name):
|
| 100 |
+
"""
|
| 101 |
+
Get a TypeRef pointing to a structure type named *name*.
|
| 102 |
+
NameError is raised if the struct type isn't found.
|
| 103 |
+
"""
|
| 104 |
+
p = ffi.lib.LLVMPY_GetNamedStructType(self, _encode_string(name))
|
| 105 |
+
if not p:
|
| 106 |
+
raise NameError(name)
|
| 107 |
+
return TypeRef(p)
|
| 108 |
+
|
| 109 |
+
def verify(self):
|
| 110 |
+
"""
|
| 111 |
+
Verify the module IR's correctness. RuntimeError is raised on error.
|
| 112 |
+
"""
|
| 113 |
+
with ffi.OutputString() as outmsg:
|
| 114 |
+
if ffi.lib.LLVMPY_VerifyModule(self, outmsg):
|
| 115 |
+
raise RuntimeError(str(outmsg))
|
| 116 |
+
|
| 117 |
+
@property
|
| 118 |
+
def name(self):
|
| 119 |
+
"""
|
| 120 |
+
The module's identifier.
|
| 121 |
+
"""
|
| 122 |
+
return _decode_string(ffi.lib.LLVMPY_GetModuleName(self))
|
| 123 |
+
|
| 124 |
+
@name.setter
|
| 125 |
+
def name(self, value):
|
| 126 |
+
ffi.lib.LLVMPY_SetModuleName(self, _encode_string(value))
|
| 127 |
+
|
| 128 |
+
@property
|
| 129 |
+
def source_file(self):
|
| 130 |
+
"""
|
| 131 |
+
The module's original source file name
|
| 132 |
+
"""
|
| 133 |
+
return _decode_string(ffi.lib.LLVMPY_GetModuleSourceFileName(self))
|
| 134 |
+
|
| 135 |
+
@property
|
| 136 |
+
def data_layout(self):
|
| 137 |
+
"""
|
| 138 |
+
This module's data layout specification, as a string.
|
| 139 |
+
"""
|
| 140 |
+
# LLVMGetDataLayout() points inside a std::string managed by LLVM.
|
| 141 |
+
with ffi.OutputString(owned=False) as outmsg:
|
| 142 |
+
ffi.lib.LLVMPY_GetDataLayout(self, outmsg)
|
| 143 |
+
return str(outmsg)
|
| 144 |
+
|
| 145 |
+
@data_layout.setter
|
| 146 |
+
def data_layout(self, strrep):
|
| 147 |
+
ffi.lib.LLVMPY_SetDataLayout(self,
|
| 148 |
+
create_string_buffer(
|
| 149 |
+
strrep.encode('utf8')))
|
| 150 |
+
|
| 151 |
+
@property
|
| 152 |
+
def triple(self):
|
| 153 |
+
"""
|
| 154 |
+
This module's target "triple" specification, as a string.
|
| 155 |
+
"""
|
| 156 |
+
# LLVMGetTarget() points inside a std::string managed by LLVM.
|
| 157 |
+
with ffi.OutputString(owned=False) as outmsg:
|
| 158 |
+
ffi.lib.LLVMPY_GetTarget(self, outmsg)
|
| 159 |
+
return str(outmsg)
|
| 160 |
+
|
| 161 |
+
@triple.setter
|
| 162 |
+
def triple(self, strrep):
|
| 163 |
+
ffi.lib.LLVMPY_SetTarget(self,
|
| 164 |
+
create_string_buffer(
|
| 165 |
+
strrep.encode('utf8')))
|
| 166 |
+
|
| 167 |
+
def link_in(self, other, preserve=False):
|
| 168 |
+
"""
|
| 169 |
+
Link the *other* module into this one. The *other* module will
|
| 170 |
+
be destroyed unless *preserve* is true.
|
| 171 |
+
"""
|
| 172 |
+
if preserve:
|
| 173 |
+
other = other.clone()
|
| 174 |
+
link_modules(self, other)
|
| 175 |
+
|
| 176 |
+
@property
|
| 177 |
+
def global_variables(self):
|
| 178 |
+
"""
|
| 179 |
+
Return an iterator over this module's global variables.
|
| 180 |
+
The iterator will yield a ValueRef for each global variable.
|
| 181 |
+
|
| 182 |
+
Note that global variables don't include functions
|
| 183 |
+
(a function is a "global value" but not a "global variable" in
|
| 184 |
+
LLVM parlance)
|
| 185 |
+
"""
|
| 186 |
+
it = ffi.lib.LLVMPY_ModuleGlobalsIter(self)
|
| 187 |
+
return _GlobalsIterator(it, dict(module=self))
|
| 188 |
+
|
| 189 |
+
@property
|
| 190 |
+
def functions(self):
|
| 191 |
+
"""
|
| 192 |
+
Return an iterator over this module's functions.
|
| 193 |
+
The iterator will yield a ValueRef for each function.
|
| 194 |
+
"""
|
| 195 |
+
it = ffi.lib.LLVMPY_ModuleFunctionsIter(self)
|
| 196 |
+
return _FunctionsIterator(it, dict(module=self))
|
| 197 |
+
|
| 198 |
+
@property
|
| 199 |
+
def struct_types(self):
|
| 200 |
+
"""
|
| 201 |
+
Return an iterator over the struct types defined in
|
| 202 |
+
the module. The iterator will yield a TypeRef.
|
| 203 |
+
"""
|
| 204 |
+
it = ffi.lib.LLVMPY_ModuleTypesIter(self)
|
| 205 |
+
return _TypesIterator(it, dict(module=self))
|
| 206 |
+
|
| 207 |
+
def clone(self):
|
| 208 |
+
return ModuleRef(ffi.lib.LLVMPY_CloneModule(self), self._context)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
class _Iterator(ffi.ObjectRef):
|
| 212 |
+
|
| 213 |
+
kind = None
|
| 214 |
+
|
| 215 |
+
def __init__(self, ptr, parents):
|
| 216 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 217 |
+
self._parents = parents
|
| 218 |
+
assert self.kind is not None
|
| 219 |
+
|
| 220 |
+
def __next__(self):
|
| 221 |
+
vp = self._next()
|
| 222 |
+
if vp:
|
| 223 |
+
return ValueRef(vp, self.kind, self._parents)
|
| 224 |
+
else:
|
| 225 |
+
raise StopIteration
|
| 226 |
+
|
| 227 |
+
next = __next__
|
| 228 |
+
|
| 229 |
+
def __iter__(self):
|
| 230 |
+
return self
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
class _GlobalsIterator(_Iterator):
|
| 234 |
+
|
| 235 |
+
kind = 'global'
|
| 236 |
+
|
| 237 |
+
def _dispose(self):
|
| 238 |
+
self._capi.LLVMPY_DisposeGlobalsIter(self)
|
| 239 |
+
|
| 240 |
+
def _next(self):
|
| 241 |
+
return ffi.lib.LLVMPY_GlobalsIterNext(self)
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
class _FunctionsIterator(_Iterator):
|
| 245 |
+
|
| 246 |
+
kind = 'function'
|
| 247 |
+
|
| 248 |
+
def _dispose(self):
|
| 249 |
+
self._capi.LLVMPY_DisposeFunctionsIter(self)
|
| 250 |
+
|
| 251 |
+
def _next(self):
|
| 252 |
+
return ffi.lib.LLVMPY_FunctionsIterNext(self)
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
class _TypesIterator(_Iterator):
|
| 256 |
+
|
| 257 |
+
kind = 'type'
|
| 258 |
+
|
| 259 |
+
def _dispose(self):
|
| 260 |
+
self._capi.LLVMPY_DisposeTypesIter(self)
|
| 261 |
+
|
| 262 |
+
def __next__(self):
|
| 263 |
+
vp = self._next()
|
| 264 |
+
if vp:
|
| 265 |
+
return TypeRef(vp)
|
| 266 |
+
else:
|
| 267 |
+
raise StopIteration
|
| 268 |
+
|
| 269 |
+
def _next(self):
|
| 270 |
+
return ffi.lib.LLVMPY_TypesIterNext(self)
|
| 271 |
+
|
| 272 |
+
next = __next__
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
# =============================================================================
|
| 276 |
+
# Set function FFI
|
| 277 |
+
|
| 278 |
+
ffi.lib.LLVMPY_ParseAssembly.argtypes = [ffi.LLVMContextRef,
|
| 279 |
+
c_char_p,
|
| 280 |
+
POINTER(c_char_p)]
|
| 281 |
+
ffi.lib.LLVMPY_ParseAssembly.restype = ffi.LLVMModuleRef
|
| 282 |
+
|
| 283 |
+
ffi.lib.LLVMPY_ParseBitcode.argtypes = [ffi.LLVMContextRef,
|
| 284 |
+
c_char_p, c_size_t,
|
| 285 |
+
POINTER(c_char_p)]
|
| 286 |
+
ffi.lib.LLVMPY_ParseBitcode.restype = ffi.LLVMModuleRef
|
| 287 |
+
|
| 288 |
+
ffi.lib.LLVMPY_DisposeModule.argtypes = [ffi.LLVMModuleRef]
|
| 289 |
+
|
| 290 |
+
ffi.lib.LLVMPY_PrintModuleToString.argtypes = [ffi.LLVMModuleRef,
|
| 291 |
+
POINTER(c_char_p)]
|
| 292 |
+
ffi.lib.LLVMPY_WriteBitcodeToString.argtypes = [ffi.LLVMModuleRef,
|
| 293 |
+
POINTER(c_char_p),
|
| 294 |
+
POINTER(c_size_t)]
|
| 295 |
+
|
| 296 |
+
ffi.lib.LLVMPY_GetNamedFunction.argtypes = [ffi.LLVMModuleRef,
|
| 297 |
+
c_char_p]
|
| 298 |
+
ffi.lib.LLVMPY_GetNamedFunction.restype = ffi.LLVMValueRef
|
| 299 |
+
|
| 300 |
+
ffi.lib.LLVMPY_VerifyModule.argtypes = [ffi.LLVMModuleRef,
|
| 301 |
+
POINTER(c_char_p)]
|
| 302 |
+
ffi.lib.LLVMPY_VerifyModule.restype = c_bool
|
| 303 |
+
|
| 304 |
+
ffi.lib.LLVMPY_GetDataLayout.argtypes = [ffi.LLVMModuleRef, POINTER(c_char_p)]
|
| 305 |
+
ffi.lib.LLVMPY_SetDataLayout.argtypes = [ffi.LLVMModuleRef, c_char_p]
|
| 306 |
+
|
| 307 |
+
ffi.lib.LLVMPY_GetTarget.argtypes = [ffi.LLVMModuleRef, POINTER(c_char_p)]
|
| 308 |
+
ffi.lib.LLVMPY_SetTarget.argtypes = [ffi.LLVMModuleRef, c_char_p]
|
| 309 |
+
|
| 310 |
+
ffi.lib.LLVMPY_GetNamedGlobalVariable.argtypes = [ffi.LLVMModuleRef, c_char_p]
|
| 311 |
+
ffi.lib.LLVMPY_GetNamedGlobalVariable.restype = ffi.LLVMValueRef
|
| 312 |
+
|
| 313 |
+
ffi.lib.LLVMPY_GetNamedStructType.argtypes = [ffi.LLVMModuleRef, c_char_p]
|
| 314 |
+
ffi.lib.LLVMPY_GetNamedStructType.restype = ffi.LLVMTypeRef
|
| 315 |
+
|
| 316 |
+
ffi.lib.LLVMPY_ModuleGlobalsIter.argtypes = [ffi.LLVMModuleRef]
|
| 317 |
+
ffi.lib.LLVMPY_ModuleGlobalsIter.restype = ffi.LLVMGlobalsIterator
|
| 318 |
+
|
| 319 |
+
ffi.lib.LLVMPY_DisposeGlobalsIter.argtypes = [ffi.LLVMGlobalsIterator]
|
| 320 |
+
|
| 321 |
+
ffi.lib.LLVMPY_GlobalsIterNext.argtypes = [ffi.LLVMGlobalsIterator]
|
| 322 |
+
ffi.lib.LLVMPY_GlobalsIterNext.restype = ffi.LLVMValueRef
|
| 323 |
+
|
| 324 |
+
ffi.lib.LLVMPY_ModuleFunctionsIter.argtypes = [ffi.LLVMModuleRef]
|
| 325 |
+
ffi.lib.LLVMPY_ModuleFunctionsIter.restype = ffi.LLVMFunctionsIterator
|
| 326 |
+
|
| 327 |
+
ffi.lib.LLVMPY_ModuleTypesIter.argtypes = [ffi.LLVMModuleRef]
|
| 328 |
+
ffi.lib.LLVMPY_ModuleTypesIter.restype = ffi.LLVMTypesIterator
|
| 329 |
+
|
| 330 |
+
ffi.lib.LLVMPY_DisposeFunctionsIter.argtypes = [ffi.LLVMFunctionsIterator]
|
| 331 |
+
|
| 332 |
+
ffi.lib.LLVMPY_DisposeTypesIter.argtypes = [ffi.LLVMTypesIterator]
|
| 333 |
+
|
| 334 |
+
ffi.lib.LLVMPY_FunctionsIterNext.argtypes = [ffi.LLVMFunctionsIterator]
|
| 335 |
+
ffi.lib.LLVMPY_FunctionsIterNext.restype = ffi.LLVMValueRef
|
| 336 |
+
|
| 337 |
+
ffi.lib.LLVMPY_TypesIterNext.argtypes = [ffi.LLVMTypesIterator]
|
| 338 |
+
ffi.lib.LLVMPY_TypesIterNext.restype = ffi.LLVMTypeRef
|
| 339 |
+
|
| 340 |
+
ffi.lib.LLVMPY_CloneModule.argtypes = [ffi.LLVMModuleRef]
|
| 341 |
+
ffi.lib.LLVMPY_CloneModule.restype = ffi.LLVMModuleRef
|
| 342 |
+
|
| 343 |
+
ffi.lib.LLVMPY_GetModuleName.argtypes = [ffi.LLVMModuleRef]
|
| 344 |
+
ffi.lib.LLVMPY_GetModuleName.restype = c_char_p
|
| 345 |
+
|
| 346 |
+
ffi.lib.LLVMPY_SetModuleName.argtypes = [ffi.LLVMModuleRef, c_char_p]
|
| 347 |
+
|
| 348 |
+
ffi.lib.LLVMPY_GetModuleSourceFileName.argtypes = [ffi.LLVMModuleRef]
|
| 349 |
+
ffi.lib.LLVMPY_GetModuleSourceFileName.restype = c_char_p
|
lib/python3.11/site-packages/llvmlite/binding/object_file.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.binding import ffi
|
| 2 |
+
from ctypes import (c_bool, c_char_p, c_char, c_size_t, string_at, c_uint64,
|
| 3 |
+
POINTER)
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class SectionIteratorRef(ffi.ObjectRef):
|
| 7 |
+
def name(self):
|
| 8 |
+
return ffi.lib.LLVMPY_GetSectionName(self)
|
| 9 |
+
|
| 10 |
+
def is_text(self):
|
| 11 |
+
return ffi.lib.LLVMPY_IsSectionText(self)
|
| 12 |
+
|
| 13 |
+
def size(self):
|
| 14 |
+
return ffi.lib.LLVMPY_GetSectionSize(self)
|
| 15 |
+
|
| 16 |
+
def address(self):
|
| 17 |
+
return ffi.lib.LLVMPY_GetSectionAddress(self)
|
| 18 |
+
|
| 19 |
+
def data(self):
|
| 20 |
+
return string_at(ffi.lib.LLVMPY_GetSectionContents(self), self.size())
|
| 21 |
+
|
| 22 |
+
def is_end(self, object_file):
|
| 23 |
+
return ffi.lib.LLVMPY_IsSectionIteratorAtEnd(object_file, self)
|
| 24 |
+
|
| 25 |
+
def next(self):
|
| 26 |
+
ffi.lib.LLVMPY_MoveToNextSection(self)
|
| 27 |
+
|
| 28 |
+
def _dispose(self):
|
| 29 |
+
ffi.lib.LLVMPY_DisposeSectionIterator(self)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class ObjectFileRef(ffi.ObjectRef):
|
| 33 |
+
@classmethod
|
| 34 |
+
def from_data(cls, data):
|
| 35 |
+
return cls(ffi.lib.LLVMPY_CreateObjectFile(data, len(data)))
|
| 36 |
+
|
| 37 |
+
@classmethod
|
| 38 |
+
def from_path(cls, path):
|
| 39 |
+
with open(path, 'rb') as f:
|
| 40 |
+
data = f.read()
|
| 41 |
+
return cls(ffi.lib.LLVMPY_CreateObjectFile(data, len(data)))
|
| 42 |
+
|
| 43 |
+
def sections(self):
|
| 44 |
+
it = SectionIteratorRef(ffi.lib.LLVMPY_GetSections(self))
|
| 45 |
+
while not it.is_end(self):
|
| 46 |
+
yield it
|
| 47 |
+
it.next()
|
| 48 |
+
|
| 49 |
+
def _dispose(self):
|
| 50 |
+
ffi.lib.LLVMPY_DisposeObjectFile(self)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
ffi.lib.LLVMPY_CreateObjectFile.argtypes = [c_char_p, c_size_t]
|
| 54 |
+
ffi.lib.LLVMPY_CreateObjectFile.restype = ffi.LLVMObjectFileRef
|
| 55 |
+
|
| 56 |
+
ffi.lib.LLVMPY_DisposeObjectFile.argtypes = [ffi.LLVMObjectFileRef]
|
| 57 |
+
|
| 58 |
+
ffi.lib.LLVMPY_GetSections.argtypes = [ffi.LLVMObjectFileRef]
|
| 59 |
+
ffi.lib.LLVMPY_GetSections.restype = ffi.LLVMSectionIteratorRef
|
| 60 |
+
|
| 61 |
+
ffi.lib.LLVMPY_DisposeSectionIterator.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 62 |
+
|
| 63 |
+
ffi.lib.LLVMPY_MoveToNextSection.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 64 |
+
|
| 65 |
+
ffi.lib.LLVMPY_IsSectionIteratorAtEnd.argtypes = [
|
| 66 |
+
ffi.LLVMObjectFileRef, ffi.LLVMSectionIteratorRef]
|
| 67 |
+
ffi.lib.LLVMPY_IsSectionIteratorAtEnd.restype = c_bool
|
| 68 |
+
|
| 69 |
+
ffi.lib.LLVMPY_GetSectionName.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 70 |
+
ffi.lib.LLVMPY_GetSectionName.restype = c_char_p
|
| 71 |
+
|
| 72 |
+
ffi.lib.LLVMPY_GetSectionSize.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 73 |
+
ffi.lib.LLVMPY_GetSectionSize.restype = c_uint64
|
| 74 |
+
|
| 75 |
+
ffi.lib.LLVMPY_GetSectionAddress.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 76 |
+
ffi.lib.LLVMPY_GetSectionAddress.restype = c_uint64
|
| 77 |
+
|
| 78 |
+
ffi.lib.LLVMPY_GetSectionContents.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 79 |
+
ffi.lib.LLVMPY_GetSectionContents.restype = POINTER(c_char)
|
| 80 |
+
|
| 81 |
+
ffi.lib.LLVMPY_IsSectionText.argtypes = [ffi.LLVMSectionIteratorRef]
|
| 82 |
+
ffi.lib.LLVMPY_IsSectionText.restype = c_bool
|
lib/python3.11/site-packages/llvmlite/binding/options.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.binding import ffi
|
| 2 |
+
from llvmlite.binding.common import _encode_string
|
| 3 |
+
from ctypes import c_char_p
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def set_option(name, option):
|
| 7 |
+
"""
|
| 8 |
+
Set the given LLVM "command-line" option.
|
| 9 |
+
|
| 10 |
+
For example set_option("test", "-debug-pass=Structure") would display
|
| 11 |
+
all optimization passes when generating code.
|
| 12 |
+
"""
|
| 13 |
+
ffi.lib.LLVMPY_SetCommandLine(_encode_string(name),
|
| 14 |
+
_encode_string(option))
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
ffi.lib.LLVMPY_SetCommandLine.argtypes = [c_char_p, c_char_p]
|
lib/python3.11/site-packages/llvmlite/binding/orcjit.py
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes
|
| 2 |
+
from ctypes import POINTER, c_bool, c_char_p, c_uint8, c_uint64, c_size_t
|
| 3 |
+
|
| 4 |
+
from llvmlite.binding import ffi, targets
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class _LinkElement(ctypes.Structure):
|
| 8 |
+
_fields_ = [("element_kind", c_uint8),
|
| 9 |
+
("value", c_char_p),
|
| 10 |
+
("value_len", c_size_t)]
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class _SymbolAddress(ctypes.Structure):
|
| 14 |
+
_fields_ = [("name", c_char_p), ("address", c_uint64)]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class JITLibraryBuilder:
|
| 18 |
+
"""
|
| 19 |
+
Create a library for linking by OrcJIT
|
| 20 |
+
|
| 21 |
+
OrcJIT operates like a linker: a number of compilation units and
|
| 22 |
+
dependencies are collected together and linked into a single dynamic library
|
| 23 |
+
that can export functions to other libraries or to be consumed directly as
|
| 24 |
+
entry points into JITted code. The native OrcJIT has a lot of memory
|
| 25 |
+
management complications so this API is designed to work well with Python's
|
| 26 |
+
garbage collection.
|
| 27 |
+
|
| 28 |
+
The creation of a new library is a bit like a linker command line where
|
| 29 |
+
compilation units, mostly as LLVM IR, and previously constructed libraries
|
| 30 |
+
are linked together, then loaded into memory, and the addresses of exported
|
| 31 |
+
symbols are extracted. Any static initializers are run and the exported
|
| 32 |
+
addresses and a resource tracker is produced. As long as the resource
|
| 33 |
+
tracker is referenced somewhere in Python, the exported addresses will be
|
| 34 |
+
valid. Once the resource tracker is garbage collected, the static
|
| 35 |
+
destructors will run and library will be unloaded from memory.
|
| 36 |
+
"""
|
| 37 |
+
def __init__(self):
|
| 38 |
+
self.__entries = []
|
| 39 |
+
self.__exports = set()
|
| 40 |
+
self.__imports = {}
|
| 41 |
+
|
| 42 |
+
def add_ir(self, llvmir):
|
| 43 |
+
"""
|
| 44 |
+
Adds a compilation unit to the library using LLVM IR as the input
|
| 45 |
+
format.
|
| 46 |
+
|
| 47 |
+
This takes a string or an object that can be converted to a string,
|
| 48 |
+
including IRBuilder, that contains LLVM IR.
|
| 49 |
+
"""
|
| 50 |
+
self.__entries.append((0, str(llvmir).encode('utf-8')))
|
| 51 |
+
return self
|
| 52 |
+
|
| 53 |
+
def add_native_assembly(self, asm):
|
| 54 |
+
"""
|
| 55 |
+
Adds a compilation unit to the library using native assembly as the
|
| 56 |
+
input format.
|
| 57 |
+
|
| 58 |
+
This takes a string or an object that can be converted to a string that
|
| 59 |
+
contains native assembly, which will be
|
| 60 |
+
parsed by LLVM.
|
| 61 |
+
"""
|
| 62 |
+
self.__entries.append((1, str(asm).encode('utf-8')))
|
| 63 |
+
return self
|
| 64 |
+
|
| 65 |
+
def add_object_img(self, data):
|
| 66 |
+
"""
|
| 67 |
+
Adds a compilation unit to the library using pre-compiled object code.
|
| 68 |
+
|
| 69 |
+
This takes the bytes of the contents of an object artifact which will be
|
| 70 |
+
loaded by LLVM.
|
| 71 |
+
"""
|
| 72 |
+
self.__entries.append((2, bytes(data)))
|
| 73 |
+
return self
|
| 74 |
+
|
| 75 |
+
def add_object_file(self, file_path):
|
| 76 |
+
"""
|
| 77 |
+
Adds a compilation unit to the library using pre-compiled object file.
|
| 78 |
+
|
| 79 |
+
This takes a string or path-like object that references an object file
|
| 80 |
+
which will be loaded by LLVM.
|
| 81 |
+
"""
|
| 82 |
+
with open(file_path, "rb") as f:
|
| 83 |
+
self.__entries.append((2, f.read()))
|
| 84 |
+
return self
|
| 85 |
+
|
| 86 |
+
def add_jit_library(self, name):
|
| 87 |
+
"""
|
| 88 |
+
Adds an existing JIT library as prerequisite.
|
| 89 |
+
|
| 90 |
+
The name of the library must match the one provided in a previous link
|
| 91 |
+
command.
|
| 92 |
+
"""
|
| 93 |
+
self.__entries.append((3, str(name).encode('utf-8')))
|
| 94 |
+
return self
|
| 95 |
+
|
| 96 |
+
def add_current_process(self):
|
| 97 |
+
"""
|
| 98 |
+
Allows the JITted library to access symbols in the current binary.
|
| 99 |
+
|
| 100 |
+
That is, it allows exporting the current binary's symbols, including
|
| 101 |
+
loaded libraries, as imports to the JITted
|
| 102 |
+
library.
|
| 103 |
+
"""
|
| 104 |
+
self.__entries.append((3, b''))
|
| 105 |
+
return self
|
| 106 |
+
|
| 107 |
+
def import_symbol(self, name, address):
|
| 108 |
+
"""
|
| 109 |
+
Register the *address* of global symbol *name*. This will make
|
| 110 |
+
it usable (e.g. callable) from LLVM-compiled functions.
|
| 111 |
+
"""
|
| 112 |
+
self.__imports[str(name)] = c_uint64(address)
|
| 113 |
+
return self
|
| 114 |
+
|
| 115 |
+
def export_symbol(self, name):
|
| 116 |
+
"""
|
| 117 |
+
During linking, extract the address of a symbol that was defined in one
|
| 118 |
+
of the compilation units.
|
| 119 |
+
|
| 120 |
+
This allows getting symbols, functions or global variables, out of the
|
| 121 |
+
JIT linked library. The addresses will be
|
| 122 |
+
available when the link method is called.
|
| 123 |
+
"""
|
| 124 |
+
self.__exports.add(str(name))
|
| 125 |
+
return self
|
| 126 |
+
|
| 127 |
+
def link(self, lljit, library_name):
|
| 128 |
+
"""
|
| 129 |
+
Link all the current compilation units into a JITted library and extract
|
| 130 |
+
the address of exported symbols.
|
| 131 |
+
|
| 132 |
+
An instance of the OrcJIT instance must be provided and this will be the
|
| 133 |
+
scope that is used to find other JITted libraries that are dependencies
|
| 134 |
+
and also be the place where this library will be defined.
|
| 135 |
+
|
| 136 |
+
After linking, the method will return a resource tracker that keeps the
|
| 137 |
+
library alive. This tracker also knows the addresses of any exported
|
| 138 |
+
symbols that were requested.
|
| 139 |
+
|
| 140 |
+
The addresses will be valid as long as the resource tracker is
|
| 141 |
+
referenced.
|
| 142 |
+
|
| 143 |
+
When the resource tracker is destroyed, the library will be cleaned up,
|
| 144 |
+
however, the name of the library cannot be reused.
|
| 145 |
+
"""
|
| 146 |
+
assert not lljit.closed, "Cannot add to closed JIT"
|
| 147 |
+
encoded_library_name = str(library_name).encode('utf-8')
|
| 148 |
+
assert len(encoded_library_name) > 0, "Library cannot be empty"
|
| 149 |
+
elements = (_LinkElement * len(self.__entries))()
|
| 150 |
+
for idx, (kind, value) in enumerate(self.__entries):
|
| 151 |
+
elements[idx].element_kind = c_uint8(kind)
|
| 152 |
+
elements[idx].value = c_char_p(value)
|
| 153 |
+
elements[idx].value_len = c_size_t(len(value))
|
| 154 |
+
exports = (_SymbolAddress * len(self.__exports))()
|
| 155 |
+
for idx, name in enumerate(self.__exports):
|
| 156 |
+
exports[idx].name = name.encode('utf-8')
|
| 157 |
+
|
| 158 |
+
imports = (_SymbolAddress * len(self.__imports))()
|
| 159 |
+
for idx, (name, addr) in enumerate(self.__imports.items()):
|
| 160 |
+
imports[idx].name = name.encode('utf-8')
|
| 161 |
+
imports[idx].address = addr
|
| 162 |
+
|
| 163 |
+
with ffi.OutputString() as outerr:
|
| 164 |
+
tracker = lljit._capi.LLVMPY_LLJIT_Link(
|
| 165 |
+
lljit._ptr,
|
| 166 |
+
encoded_library_name,
|
| 167 |
+
elements,
|
| 168 |
+
len(self.__entries),
|
| 169 |
+
imports,
|
| 170 |
+
len(self.__imports),
|
| 171 |
+
exports,
|
| 172 |
+
len(self.__exports),
|
| 173 |
+
outerr)
|
| 174 |
+
if not tracker:
|
| 175 |
+
raise RuntimeError(str(outerr))
|
| 176 |
+
return ResourceTracker(tracker,
|
| 177 |
+
library_name,
|
| 178 |
+
{name: exports[idx].address
|
| 179 |
+
for idx, name in enumerate(self.__exports)})
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
class ResourceTracker(ffi.ObjectRef):
|
| 183 |
+
"""
|
| 184 |
+
A resource tracker is created for each loaded JIT library and keeps the
|
| 185 |
+
module alive.
|
| 186 |
+
|
| 187 |
+
OrcJIT supports unloading libraries that are no longer used. This resource
|
| 188 |
+
tracker should be stored in any object that reference functions or constants
|
| 189 |
+
for a JITted library. When all references to the resource tracker are
|
| 190 |
+
dropped, this will trigger LLVM to unload the library and destroy any
|
| 191 |
+
functions.
|
| 192 |
+
|
| 193 |
+
Failure to keep resource trackers while calling a function or accessing a
|
| 194 |
+
symbol can result in crashes or memory corruption.
|
| 195 |
+
|
| 196 |
+
LLVM internally tracks references between different libraries, so only
|
| 197 |
+
"leaf" libraries need to be tracked.
|
| 198 |
+
"""
|
| 199 |
+
def __init__(self, ptr, name, addresses):
|
| 200 |
+
self.__addresses = addresses
|
| 201 |
+
self.__name = name
|
| 202 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 203 |
+
|
| 204 |
+
def __getitem__(self, item):
|
| 205 |
+
"""
|
| 206 |
+
Get the address of an exported symbol as an integer
|
| 207 |
+
"""
|
| 208 |
+
return self.__addresses[item]
|
| 209 |
+
|
| 210 |
+
@property
|
| 211 |
+
def name(self):
|
| 212 |
+
return self.__name
|
| 213 |
+
|
| 214 |
+
def _dispose(self):
|
| 215 |
+
with ffi.OutputString() as outerr:
|
| 216 |
+
if self._capi.LLVMPY_LLJIT_Dylib_Tracker_Dispose(self, outerr):
|
| 217 |
+
raise RuntimeError(str(outerr))
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
class LLJIT(ffi.ObjectRef):
|
| 221 |
+
"""
|
| 222 |
+
A OrcJIT-based LLVM JIT engine that can compile and run LLVM IR as a
|
| 223 |
+
collection of JITted dynamic libraries
|
| 224 |
+
|
| 225 |
+
The C++ OrcJIT API has a lot of memory ownership patterns that do not work
|
| 226 |
+
with Python. This API attempts to provide ones that are safe at the expense
|
| 227 |
+
of some features. Each LLJIT instance is a collection of JIT-compiled
|
| 228 |
+
libraries. In the C++ API, there is a "main" library; this API does not
|
| 229 |
+
provide access to the main library. Use the JITLibraryBuilder to create a
|
| 230 |
+
new named library instead.
|
| 231 |
+
"""
|
| 232 |
+
def __init__(self, ptr):
|
| 233 |
+
self._td = None
|
| 234 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 235 |
+
|
| 236 |
+
def lookup(self, dylib, fn):
|
| 237 |
+
"""
|
| 238 |
+
Find a function in this dynamic library and construct a new tracking
|
| 239 |
+
object for it
|
| 240 |
+
|
| 241 |
+
If the library or function do not exist, an exception will occur.
|
| 242 |
+
|
| 243 |
+
Parameters
|
| 244 |
+
----------
|
| 245 |
+
dylib : str or None
|
| 246 |
+
the name of the library containing the symbol
|
| 247 |
+
fn : str
|
| 248 |
+
the name of the function to get
|
| 249 |
+
"""
|
| 250 |
+
assert not self.closed, "Cannot lookup in closed JIT"
|
| 251 |
+
address = ctypes.c_uint64()
|
| 252 |
+
with ffi.OutputString() as outerr:
|
| 253 |
+
tracker = ffi.lib.LLVMPY_LLJITLookup(self,
|
| 254 |
+
dylib.encode("utf-8"),
|
| 255 |
+
fn.encode("utf-8"),
|
| 256 |
+
ctypes.byref(address),
|
| 257 |
+
outerr)
|
| 258 |
+
if not tracker:
|
| 259 |
+
raise RuntimeError(str(outerr))
|
| 260 |
+
|
| 261 |
+
return ResourceTracker(tracker, dylib, {fn: address.value})
|
| 262 |
+
|
| 263 |
+
@property
|
| 264 |
+
def target_data(self):
|
| 265 |
+
"""
|
| 266 |
+
The TargetData for this LLJIT instance.
|
| 267 |
+
"""
|
| 268 |
+
if self._td is not None:
|
| 269 |
+
return self._td
|
| 270 |
+
ptr = ffi.lib.LLVMPY_LLJITGetDataLayout(self)
|
| 271 |
+
self._td = targets.TargetData(ptr)
|
| 272 |
+
self._td._owned = True
|
| 273 |
+
return self._td
|
| 274 |
+
|
| 275 |
+
def _dispose(self):
|
| 276 |
+
if self._td is not None:
|
| 277 |
+
self._td.detach()
|
| 278 |
+
self._capi.LLVMPY_LLJITDispose(self)
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
def create_lljit_compiler(target_machine=None, *,
|
| 282 |
+
use_jit_link=False,
|
| 283 |
+
suppress_errors=False):
|
| 284 |
+
"""
|
| 285 |
+
Create an LLJIT instance
|
| 286 |
+
"""
|
| 287 |
+
with ffi.OutputString() as outerr:
|
| 288 |
+
lljit = ffi.lib.LLVMPY_CreateLLJITCompiler(target_machine,
|
| 289 |
+
suppress_errors,
|
| 290 |
+
use_jit_link,
|
| 291 |
+
outerr)
|
| 292 |
+
if not lljit:
|
| 293 |
+
raise RuntimeError(str(outerr))
|
| 294 |
+
|
| 295 |
+
return LLJIT(lljit)
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
ffi.lib.LLVMPY_LLJITLookup.argtypes = [
|
| 299 |
+
ffi.LLVMOrcLLJITRef,
|
| 300 |
+
c_char_p,
|
| 301 |
+
c_char_p,
|
| 302 |
+
POINTER(c_uint64),
|
| 303 |
+
POINTER(c_char_p),
|
| 304 |
+
]
|
| 305 |
+
ffi.lib.LLVMPY_LLJITLookup.restype = ffi.LLVMOrcDylibTrackerRef
|
| 306 |
+
|
| 307 |
+
ffi.lib.LLVMPY_LLJITGetDataLayout.argtypes = [
|
| 308 |
+
ffi.LLVMOrcLLJITRef,
|
| 309 |
+
]
|
| 310 |
+
ffi.lib.LLVMPY_LLJITGetDataLayout.restype = ffi.LLVMTargetDataRef
|
| 311 |
+
|
| 312 |
+
ffi.lib.LLVMPY_CreateLLJITCompiler.argtypes = [
|
| 313 |
+
ffi.LLVMTargetMachineRef,
|
| 314 |
+
c_bool,
|
| 315 |
+
c_bool,
|
| 316 |
+
POINTER(c_char_p),
|
| 317 |
+
]
|
| 318 |
+
ffi.lib.LLVMPY_CreateLLJITCompiler.restype = ffi.LLVMOrcLLJITRef
|
| 319 |
+
|
| 320 |
+
ffi.lib.LLVMPY_LLJITDispose.argtypes = [
|
| 321 |
+
ffi.LLVMOrcLLJITRef,
|
| 322 |
+
]
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
ffi.lib.LLVMPY_LLJIT_Link.argtypes = [
|
| 326 |
+
ffi.LLVMOrcLLJITRef,
|
| 327 |
+
c_char_p,
|
| 328 |
+
POINTER(_LinkElement),
|
| 329 |
+
c_size_t,
|
| 330 |
+
POINTER(_SymbolAddress),
|
| 331 |
+
c_size_t,
|
| 332 |
+
POINTER(_SymbolAddress),
|
| 333 |
+
c_size_t,
|
| 334 |
+
POINTER(c_char_p)
|
| 335 |
+
]
|
| 336 |
+
ffi.lib.LLVMPY_LLJIT_Link.restype = ffi.LLVMOrcDylibTrackerRef
|
| 337 |
+
|
| 338 |
+
ffi.lib.LLVMPY_LLJIT_Dylib_Tracker_Dispose.argtypes = [
|
| 339 |
+
ffi.LLVMOrcDylibTrackerRef,
|
| 340 |
+
POINTER(c_char_p)
|
| 341 |
+
]
|
| 342 |
+
ffi.lib.LLVMPY_LLJIT_Dylib_Tracker_Dispose.restype = c_bool
|
lib/python3.11/site-packages/llvmlite/binding/passmanagers.py
ADDED
|
@@ -0,0 +1,923 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import (c_bool, c_char_p, c_int, c_size_t, c_uint, Structure, byref,
|
| 2 |
+
POINTER)
|
| 3 |
+
from collections import namedtuple
|
| 4 |
+
from enum import IntFlag
|
| 5 |
+
from llvmlite.binding import ffi
|
| 6 |
+
import os
|
| 7 |
+
from tempfile import mkstemp
|
| 8 |
+
from llvmlite.binding.common import _encode_string
|
| 9 |
+
|
| 10 |
+
_prunestats = namedtuple('PruneStats',
|
| 11 |
+
('basicblock diamond fanout fanout_raise'))
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class PruneStats(_prunestats):
|
| 15 |
+
""" Holds statistics from reference count pruning.
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
def __add__(self, other):
|
| 19 |
+
if not isinstance(other, PruneStats):
|
| 20 |
+
msg = 'PruneStats can only be added to another PruneStats, got {}.'
|
| 21 |
+
raise TypeError(msg.format(type(other)))
|
| 22 |
+
return PruneStats(self.basicblock + other.basicblock,
|
| 23 |
+
self.diamond + other.diamond,
|
| 24 |
+
self.fanout + other.fanout,
|
| 25 |
+
self.fanout_raise + other.fanout_raise)
|
| 26 |
+
|
| 27 |
+
def __sub__(self, other):
|
| 28 |
+
if not isinstance(other, PruneStats):
|
| 29 |
+
msg = ('PruneStats can only be subtracted from another PruneStats, '
|
| 30 |
+
'got {}.')
|
| 31 |
+
raise TypeError(msg.format(type(other)))
|
| 32 |
+
return PruneStats(self.basicblock - other.basicblock,
|
| 33 |
+
self.diamond - other.diamond,
|
| 34 |
+
self.fanout - other.fanout,
|
| 35 |
+
self.fanout_raise - other.fanout_raise)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class _c_PruneStats(Structure):
|
| 39 |
+
_fields_ = [
|
| 40 |
+
('basicblock', c_size_t),
|
| 41 |
+
('diamond', c_size_t),
|
| 42 |
+
('fanout', c_size_t),
|
| 43 |
+
('fanout_raise', c_size_t)]
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def dump_refprune_stats(printout=False):
|
| 47 |
+
""" Returns a namedtuple containing the current values for the refop pruning
|
| 48 |
+
statistics. If kwarg `printout` is True the stats are printed to stderr,
|
| 49 |
+
default is False.
|
| 50 |
+
"""
|
| 51 |
+
|
| 52 |
+
stats = _c_PruneStats(0, 0, 0, 0)
|
| 53 |
+
do_print = c_bool(printout)
|
| 54 |
+
|
| 55 |
+
ffi.lib.LLVMPY_DumpRefPruneStats(byref(stats), do_print)
|
| 56 |
+
return PruneStats(stats.basicblock, stats.diamond, stats.fanout,
|
| 57 |
+
stats.fanout_raise)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def set_time_passes(enable):
|
| 61 |
+
"""Enable or disable the pass timers.
|
| 62 |
+
|
| 63 |
+
Parameters
|
| 64 |
+
----------
|
| 65 |
+
enable : bool
|
| 66 |
+
Set to True to enable the pass timers.
|
| 67 |
+
Set to False to disable the pass timers.
|
| 68 |
+
"""
|
| 69 |
+
ffi.lib.LLVMPY_SetTimePasses(c_bool(enable))
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
def report_and_reset_timings():
|
| 73 |
+
"""Returns the pass timings report and resets the LLVM internal timers.
|
| 74 |
+
|
| 75 |
+
Pass timers are enabled by ``set_time_passes()``. If the timers are not
|
| 76 |
+
enabled, this function will return an empty string.
|
| 77 |
+
|
| 78 |
+
Returns
|
| 79 |
+
-------
|
| 80 |
+
res : str
|
| 81 |
+
LLVM generated timing report.
|
| 82 |
+
"""
|
| 83 |
+
with ffi.OutputString() as buf:
|
| 84 |
+
ffi.lib.LLVMPY_ReportAndResetTimings(buf)
|
| 85 |
+
return str(buf)
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def create_module_pass_manager():
|
| 89 |
+
return ModulePassManager()
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def create_function_pass_manager(module):
|
| 93 |
+
return FunctionPassManager(module)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class RefPruneSubpasses(IntFlag):
|
| 97 |
+
PER_BB = 0b0001 # noqa: E221
|
| 98 |
+
DIAMOND = 0b0010 # noqa: E221
|
| 99 |
+
FANOUT = 0b0100 # noqa: E221
|
| 100 |
+
FANOUT_RAISE = 0b1000
|
| 101 |
+
ALL = PER_BB | DIAMOND | FANOUT | FANOUT_RAISE
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
class PassManager(ffi.ObjectRef):
|
| 105 |
+
"""PassManager
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
def _dispose(self):
|
| 109 |
+
self._capi.LLVMPY_DisposePassManager(self)
|
| 110 |
+
|
| 111 |
+
def add_aa_eval_pass(self):
|
| 112 |
+
"""
|
| 113 |
+
See https://llvm.org/docs/Passes.html#aa-eval-exhaustive-alias-analysis-precision-evaluator
|
| 114 |
+
|
| 115 |
+
LLVM 14: `llvm::createAAEvalPass`
|
| 116 |
+
""" # noqa E501
|
| 117 |
+
ffi.lib.LLVMPY_AddAAEvalPass(self)
|
| 118 |
+
|
| 119 |
+
def add_basic_aa_pass(self):
|
| 120 |
+
"""
|
| 121 |
+
See https://llvm.org/docs/Passes.html#basic-aa-basic-alias-analysis-stateless-aa-impl
|
| 122 |
+
|
| 123 |
+
LLVM 14: `llvm::createBasicAAWrapperPass`
|
| 124 |
+
""" # noqa E501
|
| 125 |
+
ffi.lib.LLVMPY_AddBasicAAWrapperPass(self)
|
| 126 |
+
|
| 127 |
+
def add_constant_merge_pass(self):
|
| 128 |
+
"""
|
| 129 |
+
See http://llvm.org/docs/Passes.html#constmerge-merge-duplicate-global-constants
|
| 130 |
+
|
| 131 |
+
LLVM 14: `LLVMAddConstantMergePass`
|
| 132 |
+
""" # noqa E501
|
| 133 |
+
ffi.lib.LLVMPY_AddConstantMergePass(self)
|
| 134 |
+
|
| 135 |
+
def add_dead_arg_elimination_pass(self):
|
| 136 |
+
"""
|
| 137 |
+
See http://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination
|
| 138 |
+
|
| 139 |
+
LLVM 14: `LLVMAddDeadArgEliminationPass`
|
| 140 |
+
""" # noqa E501
|
| 141 |
+
ffi.lib.LLVMPY_AddDeadArgEliminationPass(self)
|
| 142 |
+
|
| 143 |
+
def add_dependence_analysis_pass(self):
|
| 144 |
+
"""
|
| 145 |
+
See https://llvm.org/docs/Passes.html#da-dependence-analysis
|
| 146 |
+
|
| 147 |
+
LLVM 14: `llvm::createDependenceAnalysisWrapperPass`
|
| 148 |
+
""" # noqa E501
|
| 149 |
+
ffi.lib.LLVMPY_AddDependenceAnalysisPass(self)
|
| 150 |
+
|
| 151 |
+
def add_dot_call_graph_pass(self):
|
| 152 |
+
"""
|
| 153 |
+
See https://llvm.org/docs/Passes.html#dot-callgraph-print-call-graph-to-dot-file
|
| 154 |
+
|
| 155 |
+
LLVM 14: `llvm::createCallGraphDOTPrinterPass`
|
| 156 |
+
""" # noqa E501
|
| 157 |
+
ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass(self)
|
| 158 |
+
|
| 159 |
+
def add_dot_cfg_printer_pass(self):
|
| 160 |
+
"""
|
| 161 |
+
See https://llvm.org/docs/Passes.html#dot-cfg-print-cfg-of-function-to-dot-file
|
| 162 |
+
|
| 163 |
+
LLVM 14: `llvm::createCFGPrinterLegacyPassPass`
|
| 164 |
+
""" # noqa E501
|
| 165 |
+
ffi.lib.LLVMPY_AddCFGPrinterPass(self)
|
| 166 |
+
|
| 167 |
+
def add_dot_dom_printer_pass(self, show_body=False):
|
| 168 |
+
"""
|
| 169 |
+
See https://llvm.org/docs/Passes.html#dot-dom-print-dominance-tree-of-function-to-dot-file
|
| 170 |
+
|
| 171 |
+
LLVM 14: `llvm::createDomPrinterPass` and `llvm::createDomOnlyPrinterPass`
|
| 172 |
+
""" # noqa E501
|
| 173 |
+
ffi.lib.LLVMPY_AddDotDomPrinterPass(self, show_body)
|
| 174 |
+
|
| 175 |
+
def add_dot_postdom_printer_pass(self, show_body=False):
|
| 176 |
+
"""
|
| 177 |
+
See https://llvm.org/docs/Passes.html#dot-postdom-print-postdominance-tree-of-function-to-dot-file
|
| 178 |
+
|
| 179 |
+
LLVM 14: `llvm::createPostDomPrinterPass` and `llvm::createPostDomOnlyPrinterPass`
|
| 180 |
+
""" # noqa E501
|
| 181 |
+
ffi.lib.LLVMPY_AddDotPostDomPrinterPass(self, show_body)
|
| 182 |
+
|
| 183 |
+
def add_globals_mod_ref_aa_pass(self):
|
| 184 |
+
"""
|
| 185 |
+
See https://llvm.org/docs/Passes.html#globalsmodref-aa-simple-mod-ref-analysis-for-globals
|
| 186 |
+
|
| 187 |
+
LLVM 14: `llvm::createGlobalsAAWrapperPass`
|
| 188 |
+
""" # noqa E501
|
| 189 |
+
ffi.lib.LLVMPY_AddGlobalsModRefAAPass(self)
|
| 190 |
+
|
| 191 |
+
def add_iv_users_pass(self):
|
| 192 |
+
"""
|
| 193 |
+
See https://llvm.org/docs/Passes.html#iv-users-induction-variable-users
|
| 194 |
+
|
| 195 |
+
LLVM 14: `llvm::createIVUsersPass`
|
| 196 |
+
""" # noqa E501
|
| 197 |
+
ffi.lib.LLVMPY_AddIVUsersPass(self)
|
| 198 |
+
|
| 199 |
+
def add_lint_pass(self):
|
| 200 |
+
"""
|
| 201 |
+
See https://llvm.org/docs/Passes.html#lint-statically-lint-checks-llvm-ir
|
| 202 |
+
|
| 203 |
+
LLVM 14: `llvm::createLintLegacyPassPass`
|
| 204 |
+
""" # noqa E501
|
| 205 |
+
ffi.lib.LLVMPY_AddLintPass(self)
|
| 206 |
+
|
| 207 |
+
def add_lazy_value_info_pass(self):
|
| 208 |
+
"""
|
| 209 |
+
See https://llvm.org/docs/Passes.html#lazy-value-info-lazy-value-information-analysis
|
| 210 |
+
|
| 211 |
+
LLVM 14: `llvm::createLazyValueInfoPass`
|
| 212 |
+
""" # noqa E501
|
| 213 |
+
ffi.lib.LLVMPY_AddLazyValueInfoPass(self)
|
| 214 |
+
|
| 215 |
+
def add_module_debug_info_pass(self):
|
| 216 |
+
"""
|
| 217 |
+
See https://llvm.org/docs/Passes.html#module-debuginfo-decodes-module-level-debug-info
|
| 218 |
+
|
| 219 |
+
LLVM 14: `llvm::createModuleDebugInfoPrinterPass`
|
| 220 |
+
""" # noqa E501
|
| 221 |
+
ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass(self)
|
| 222 |
+
|
| 223 |
+
def add_region_info_pass(self):
|
| 224 |
+
"""
|
| 225 |
+
See https://llvm.org/docs/Passes.html#regions-detect-single-entry-single-exit-regions
|
| 226 |
+
|
| 227 |
+
LLVM 14: `llvm::createRegionInfoPass`
|
| 228 |
+
""" # noqa E501
|
| 229 |
+
ffi.lib.LLVMPY_AddRegionInfoPass(self)
|
| 230 |
+
|
| 231 |
+
def add_scalar_evolution_aa_pass(self):
|
| 232 |
+
"""
|
| 233 |
+
See https://llvm.org/docs/Passes.html#scev-aa-scalarevolution-based-alias-analysis
|
| 234 |
+
|
| 235 |
+
LLVM 14: `llvm::createSCEVAAWrapperPass`
|
| 236 |
+
""" # noqa E501
|
| 237 |
+
ffi.lib.LLVMPY_AddScalarEvolutionAAPass(self)
|
| 238 |
+
|
| 239 |
+
def add_aggressive_dead_code_elimination_pass(self):
|
| 240 |
+
"""
|
| 241 |
+
See https://llvm.org/docs/Passes.html#adce-aggressive-dead-code-elimination
|
| 242 |
+
|
| 243 |
+
LLVM 14: `llvm::createAggressiveDCEPass`
|
| 244 |
+
""" # noqa E501
|
| 245 |
+
ffi.lib.LLVMPY_AddAggressiveDCEPass(self)
|
| 246 |
+
|
| 247 |
+
def add_always_inliner_pass(self, insert_lifetime=True):
|
| 248 |
+
"""
|
| 249 |
+
See https://llvm.org/docs/Passes.html#always-inline-inliner-for-always-inline-functions
|
| 250 |
+
|
| 251 |
+
LLVM 14: `llvm::createAlwaysInlinerLegacyPass`
|
| 252 |
+
""" # noqa E501
|
| 253 |
+
ffi.lib.LLVMPY_AddAlwaysInlinerPass(self, insert_lifetime)
|
| 254 |
+
|
| 255 |
+
def add_arg_promotion_pass(self, max_elements=3):
|
| 256 |
+
"""
|
| 257 |
+
See https://llvm.org/docs/Passes.html#argpromotion-promote-by-reference-arguments-to-scalars
|
| 258 |
+
|
| 259 |
+
LLVM 14: `llvm::createArgumentPromotionPass`
|
| 260 |
+
""" # noqa E501
|
| 261 |
+
ffi.lib.LLVMPY_AddArgPromotionPass(self, max_elements)
|
| 262 |
+
|
| 263 |
+
def add_break_critical_edges_pass(self):
|
| 264 |
+
"""
|
| 265 |
+
See https://llvm.org/docs/Passes.html#break-crit-edges-break-critical-edges-in-cfg
|
| 266 |
+
|
| 267 |
+
LLVM 14: `llvm::createBreakCriticalEdgesPass`
|
| 268 |
+
""" # noqa E501
|
| 269 |
+
ffi.lib.LLVMPY_AddBreakCriticalEdgesPass(self)
|
| 270 |
+
|
| 271 |
+
def add_dead_store_elimination_pass(self):
|
| 272 |
+
"""
|
| 273 |
+
See https://llvm.org/docs/Passes.html#dse-dead-store-elimination
|
| 274 |
+
|
| 275 |
+
LLVM 14: `llvm::createDeadStoreEliminationPass`
|
| 276 |
+
""" # noqa E501
|
| 277 |
+
ffi.lib.LLVMPY_AddDeadStoreEliminationPass(self)
|
| 278 |
+
|
| 279 |
+
def add_reverse_post_order_function_attrs_pass(self):
|
| 280 |
+
"""
|
| 281 |
+
See https://llvm.org/docs/Passes.html#function-attrs-deduce-function-attributes
|
| 282 |
+
|
| 283 |
+
LLVM 14: `llvm::createReversePostOrderFunctionAttrsPass`
|
| 284 |
+
""" # noqa E501
|
| 285 |
+
ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass(self)
|
| 286 |
+
|
| 287 |
+
def add_function_attrs_pass(self):
|
| 288 |
+
"""
|
| 289 |
+
See http://llvm.org/docs/Passes.html#functionattrs-deduce-function-attributes
|
| 290 |
+
|
| 291 |
+
LLVM 14: `LLVMAddFunctionAttrsPass`
|
| 292 |
+
""" # noqa E501
|
| 293 |
+
ffi.lib.LLVMPY_AddFunctionAttrsPass(self)
|
| 294 |
+
|
| 295 |
+
def add_function_inlining_pass(self, threshold):
|
| 296 |
+
"""
|
| 297 |
+
See http://llvm.org/docs/Passes.html#inline-function-integration-inlining
|
| 298 |
+
|
| 299 |
+
LLVM 14: `createFunctionInliningPass`
|
| 300 |
+
""" # noqa E501
|
| 301 |
+
ffi.lib.LLVMPY_AddFunctionInliningPass(self, threshold)
|
| 302 |
+
|
| 303 |
+
def add_global_dce_pass(self):
|
| 304 |
+
"""
|
| 305 |
+
See http://llvm.org/docs/Passes.html#globaldce-dead-global-elimination
|
| 306 |
+
|
| 307 |
+
LLVM 14: `LLVMAddGlobalDCEPass`
|
| 308 |
+
""" # noqa E501
|
| 309 |
+
ffi.lib.LLVMPY_AddGlobalDCEPass(self)
|
| 310 |
+
|
| 311 |
+
def add_global_optimizer_pass(self):
|
| 312 |
+
"""
|
| 313 |
+
See http://llvm.org/docs/Passes.html#globalopt-global-variable-optimizer
|
| 314 |
+
|
| 315 |
+
LLVM 14: `LLVMAddGlobalOptimizerPass`
|
| 316 |
+
""" # noqa E501
|
| 317 |
+
ffi.lib.LLVMPY_AddGlobalOptimizerPass(self)
|
| 318 |
+
|
| 319 |
+
def add_ipsccp_pass(self):
|
| 320 |
+
"""
|
| 321 |
+
See http://llvm.org/docs/Passes.html#ipsccp-interprocedural-sparse-conditional-constant-propagation
|
| 322 |
+
|
| 323 |
+
LLVM 14: `LLVMAddIPSCCPPass`
|
| 324 |
+
""" # noqa E501
|
| 325 |
+
ffi.lib.LLVMPY_AddIPSCCPPass(self)
|
| 326 |
+
|
| 327 |
+
def add_dead_code_elimination_pass(self):
|
| 328 |
+
"""
|
| 329 |
+
See http://llvm.org/docs/Passes.html#dce-dead-code-elimination
|
| 330 |
+
LLVM 14: `llvm::createDeadCodeEliminationPass`
|
| 331 |
+
"""
|
| 332 |
+
ffi.lib.LLVMPY_AddDeadCodeEliminationPass(self)
|
| 333 |
+
|
| 334 |
+
def add_aggressive_instruction_combining_pass(self):
|
| 335 |
+
"""
|
| 336 |
+
See https://llvm.org/docs/Passes.html#aggressive-instcombine-combine-expression-patterns
|
| 337 |
+
|
| 338 |
+
LLVM 14: `llvm::createAggressiveInstCombinerPass`
|
| 339 |
+
""" # noqa E501
|
| 340 |
+
ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass(self)
|
| 341 |
+
|
| 342 |
+
def add_internalize_pass(self):
|
| 343 |
+
"""
|
| 344 |
+
See https://llvm.org/docs/Passes.html#internalize-internalize-global-symbols
|
| 345 |
+
|
| 346 |
+
LLVM 14: `llvm::createInternalizePass`
|
| 347 |
+
""" # noqa E501
|
| 348 |
+
ffi.lib.LLVMPY_AddInternalizePass(self)
|
| 349 |
+
|
| 350 |
+
def add_cfg_simplification_pass(self):
|
| 351 |
+
"""
|
| 352 |
+
See http://llvm.org/docs/Passes.html#simplifycfg-simplify-the-cfg
|
| 353 |
+
|
| 354 |
+
LLVM 14: `LLVMAddCFGSimplificationPass`
|
| 355 |
+
"""
|
| 356 |
+
ffi.lib.LLVMPY_AddCFGSimplificationPass(self)
|
| 357 |
+
|
| 358 |
+
def add_jump_threading_pass(self, threshold=-1):
|
| 359 |
+
"""
|
| 360 |
+
See https://llvm.org/docs/Passes.html#jump-threading-jump-threading
|
| 361 |
+
|
| 362 |
+
LLVM 14: `llvm::createJumpThreadingPass`
|
| 363 |
+
""" # noqa E501
|
| 364 |
+
ffi.lib.LLVMPY_AddJumpThreadingPass(self, threshold)
|
| 365 |
+
|
| 366 |
+
def add_lcssa_pass(self):
|
| 367 |
+
"""
|
| 368 |
+
See https://llvm.org/docs/Passes.html#lcssa-loop-closed-ssa-form-pass
|
| 369 |
+
|
| 370 |
+
LLVM 14: `llvm::createLCSSAPass`
|
| 371 |
+
""" # noqa E501
|
| 372 |
+
ffi.lib.LLVMPY_AddLCSSAPass(self)
|
| 373 |
+
|
| 374 |
+
def add_gvn_pass(self):
|
| 375 |
+
"""
|
| 376 |
+
See http://llvm.org/docs/Passes.html#gvn-global-value-numbering
|
| 377 |
+
|
| 378 |
+
LLVM 14: `LLVMAddGVNPass`
|
| 379 |
+
"""
|
| 380 |
+
ffi.lib.LLVMPY_AddGVNPass(self)
|
| 381 |
+
|
| 382 |
+
def add_instruction_combining_pass(self):
|
| 383 |
+
"""
|
| 384 |
+
See http://llvm.org/docs/Passes.html#passes-instcombine
|
| 385 |
+
|
| 386 |
+
LLVM 14: `LLVMAddInstructionCombiningPass`
|
| 387 |
+
"""
|
| 388 |
+
ffi.lib.LLVMPY_AddInstructionCombiningPass(self)
|
| 389 |
+
|
| 390 |
+
def add_licm_pass(self):
|
| 391 |
+
"""
|
| 392 |
+
See http://llvm.org/docs/Passes.html#licm-loop-invariant-code-motion
|
| 393 |
+
|
| 394 |
+
LLVM 14: `LLVMAddLICMPass`
|
| 395 |
+
""" # noqa E501
|
| 396 |
+
ffi.lib.LLVMPY_AddLICMPass(self)
|
| 397 |
+
|
| 398 |
+
def add_loop_deletion_pass(self):
|
| 399 |
+
"""
|
| 400 |
+
See https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops
|
| 401 |
+
|
| 402 |
+
LLVM 14: `llvm::createLoopDeletionPass`
|
| 403 |
+
""" # noqa E501
|
| 404 |
+
ffi.lib.LLVMPY_AddLoopDeletionPass(self)
|
| 405 |
+
|
| 406 |
+
def add_loop_extractor_pass(self):
|
| 407 |
+
"""
|
| 408 |
+
See https://llvm.org/docs/Passes.html#loop-extract-extract-loops-into-new-functions
|
| 409 |
+
|
| 410 |
+
LLVM 14: `llvm::createLoopExtractorPass`
|
| 411 |
+
""" # noqa E501
|
| 412 |
+
ffi.lib.LLVMPY_AddLoopExtractorPass(self)
|
| 413 |
+
|
| 414 |
+
def add_single_loop_extractor_pass(self):
|
| 415 |
+
"""
|
| 416 |
+
See https://llvm.org/docs/Passes.html#loop-extract-single-extract-at-most-one-loop-into-a-new-function
|
| 417 |
+
|
| 418 |
+
LLVM 14: `llvm::createSingleLoopExtractorPass`
|
| 419 |
+
""" # noqa E501
|
| 420 |
+
ffi.lib.LLVMPY_AddSingleLoopExtractorPass(self)
|
| 421 |
+
|
| 422 |
+
def add_sccp_pass(self):
|
| 423 |
+
"""
|
| 424 |
+
See http://llvm.org/docs/Passes.html#sccp-sparse-conditional-constant-propagation
|
| 425 |
+
|
| 426 |
+
LLVM 14: `LLVMAddSCCPPass`
|
| 427 |
+
""" # noqa E501
|
| 428 |
+
ffi.lib.LLVMPY_AddSCCPPass(self)
|
| 429 |
+
|
| 430 |
+
def add_loop_strength_reduce_pass(self):
|
| 431 |
+
"""
|
| 432 |
+
See https://llvm.org/docs/Passes.html#loop-reduce-loop-strength-reduction
|
| 433 |
+
|
| 434 |
+
LLVM 14: `llvm::createLoopStrengthReducePass`
|
| 435 |
+
""" # noqa E501
|
| 436 |
+
ffi.lib.LLVMPY_AddLoopStrengthReducePass(self)
|
| 437 |
+
|
| 438 |
+
def add_loop_simplification_pass(self):
|
| 439 |
+
"""
|
| 440 |
+
See https://llvm.org/docs/Passes.html#loop-simplify-canonicalize-natural-loops
|
| 441 |
+
|
| 442 |
+
LLVM 14: `llvm::createLoopSimplifyPass`
|
| 443 |
+
""" # noqa E501
|
| 444 |
+
ffi.lib.LLVMPY_AddLoopSimplificationPass(self)
|
| 445 |
+
|
| 446 |
+
def add_loop_unroll_pass(self):
|
| 447 |
+
"""
|
| 448 |
+
See https://llvm.org/docs/Passes.html#loop-unroll-unroll-loops
|
| 449 |
+
|
| 450 |
+
LLVM 14: `LLVMAddLoopUnrollPass`
|
| 451 |
+
""" # noqa E501
|
| 452 |
+
ffi.lib.LLVMPY_AddLoopUnrollPass(self)
|
| 453 |
+
|
| 454 |
+
def add_loop_unroll_and_jam_pass(self):
|
| 455 |
+
"""
|
| 456 |
+
See https://llvm.org/docs/Passes.html#loop-unroll-and-jam-unroll-and-jam-loops
|
| 457 |
+
|
| 458 |
+
LLVM 14: `LLVMAddLoopUnrollAndJamPass`
|
| 459 |
+
""" # noqa E501
|
| 460 |
+
ffi.lib.LLVMPY_AddLoopUnrollAndJamPass(self)
|
| 461 |
+
|
| 462 |
+
def add_loop_unswitch_pass(self,
|
| 463 |
+
optimize_for_size=False,
|
| 464 |
+
has_branch_divergence=False):
|
| 465 |
+
"""
|
| 466 |
+
See https://llvm.org/docs/Passes.html#loop-unswitch-unswitch-loops
|
| 467 |
+
|
| 468 |
+
LLVM 14: `llvm::createLoopUnswitchPass`
|
| 469 |
+
""" # noqa E501
|
| 470 |
+
ffi.lib.LLVMPY_AddLoopUnswitchPass(self,
|
| 471 |
+
optimize_for_size,
|
| 472 |
+
has_branch_divergence)
|
| 473 |
+
|
| 474 |
+
def add_lower_atomic_pass(self):
|
| 475 |
+
"""
|
| 476 |
+
See https://llvm.org/docs/Passes.html#loweratomic-lower-atomic-intrinsics-to-non-atomic-form
|
| 477 |
+
|
| 478 |
+
LLVM 14: `llvm::createLowerAtomicPass`
|
| 479 |
+
""" # noqa E501
|
| 480 |
+
ffi.lib.LLVMPY_AddLowerAtomicPass(self)
|
| 481 |
+
|
| 482 |
+
def add_lower_invoke_pass(self):
|
| 483 |
+
"""
|
| 484 |
+
See https://llvm.org/docs/Passes.html#lowerinvoke-lower-invokes-to-calls-for-unwindless-code-generators
|
| 485 |
+
|
| 486 |
+
LLVM 14: `llvm::createLowerInvokePass`
|
| 487 |
+
""" # noqa E501
|
| 488 |
+
ffi.lib.LLVMPY_AddLowerInvokePass(self)
|
| 489 |
+
|
| 490 |
+
def add_lower_switch_pass(self):
|
| 491 |
+
"""
|
| 492 |
+
See https://llvm.org/docs/Passes.html#lowerswitch-lower-switchinsts-to-branches
|
| 493 |
+
|
| 494 |
+
LLVM 14: `llvm::createLowerSwitchPass`
|
| 495 |
+
""" # noqa E501
|
| 496 |
+
ffi.lib.LLVMPY_AddLowerSwitchPass(self)
|
| 497 |
+
|
| 498 |
+
def add_memcpy_optimization_pass(self):
|
| 499 |
+
"""
|
| 500 |
+
See https://llvm.org/docs/Passes.html#memcpyopt-memcpy-optimization
|
| 501 |
+
|
| 502 |
+
LLVM 14: `llvm::createMemCpyOptPass`
|
| 503 |
+
""" # noqa E501
|
| 504 |
+
ffi.lib.LLVMPY_AddMemCpyOptimizationPass(self)
|
| 505 |
+
|
| 506 |
+
def add_merge_functions_pass(self):
|
| 507 |
+
"""
|
| 508 |
+
See https://llvm.org/docs/Passes.html#mergefunc-merge-functions
|
| 509 |
+
|
| 510 |
+
LLVM 14: `llvm::createMergeFunctionsPass`
|
| 511 |
+
""" # noqa E501
|
| 512 |
+
ffi.lib.LLVMPY_AddMergeFunctionsPass(self)
|
| 513 |
+
|
| 514 |
+
def add_merge_returns_pass(self):
|
| 515 |
+
"""
|
| 516 |
+
See https://llvm.org/docs/Passes.html#mergereturn-unify-function-exit-nodes
|
| 517 |
+
|
| 518 |
+
LLVM 14: `llvm::createUnifyFunctionExitNodesPass`
|
| 519 |
+
""" # noqa E501
|
| 520 |
+
ffi.lib.LLVMPY_AddMergeReturnsPass(self)
|
| 521 |
+
|
| 522 |
+
def add_partial_inlining_pass(self):
|
| 523 |
+
"""
|
| 524 |
+
See https://llvm.org/docs/Passes.html#partial-inliner-partial-inliner
|
| 525 |
+
|
| 526 |
+
LLVM 14: `llvm::createPartialInliningPass`
|
| 527 |
+
""" # noqa E501
|
| 528 |
+
ffi.lib.LLVMPY_AddPartialInliningPass(self)
|
| 529 |
+
|
| 530 |
+
def add_prune_exception_handling_pass(self):
|
| 531 |
+
"""
|
| 532 |
+
See https://llvm.org/docs/Passes.html#prune-eh-remove-unused-exception-handling-info
|
| 533 |
+
|
| 534 |
+
LLVM 14: `llvm::createPruneEHPass`
|
| 535 |
+
""" # noqa E501
|
| 536 |
+
ffi.lib.LLVMPY_AddPruneExceptionHandlingPass(self)
|
| 537 |
+
|
| 538 |
+
def add_reassociate_expressions_pass(self):
|
| 539 |
+
"""
|
| 540 |
+
See https://llvm.org/docs/Passes.html#reassociate-reassociate-expressions
|
| 541 |
+
|
| 542 |
+
LLVM 14: `llvm::createReassociatePass`
|
| 543 |
+
""" # noqa E501
|
| 544 |
+
ffi.lib.LLVMPY_AddReassociatePass(self)
|
| 545 |
+
|
| 546 |
+
def add_demote_register_to_memory_pass(self):
|
| 547 |
+
"""
|
| 548 |
+
See https://llvm.org/docs/Passes.html#rel-lookup-table-converter-relative-lookup-table-converter
|
| 549 |
+
|
| 550 |
+
LLVM 14: `llvm::createDemoteRegisterToMemoryPass`
|
| 551 |
+
""" # noqa E501
|
| 552 |
+
ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass(self)
|
| 553 |
+
|
| 554 |
+
def add_sroa_pass(self):
|
| 555 |
+
"""
|
| 556 |
+
See http://llvm.org/docs/Passes.html#scalarrepl-scalar-replacement-of-aggregates-dt
|
| 557 |
+
Note that this pass corresponds to the ``opt -sroa`` command-line option,
|
| 558 |
+
despite the link above.
|
| 559 |
+
|
| 560 |
+
LLVM 14: `llvm::createSROAPass`
|
| 561 |
+
""" # noqa E501
|
| 562 |
+
ffi.lib.LLVMPY_AddSROAPass(self)
|
| 563 |
+
|
| 564 |
+
def add_sink_pass(self):
|
| 565 |
+
"""
|
| 566 |
+
See https://llvm.org/docs/Passes.html#sink-code-sinking
|
| 567 |
+
|
| 568 |
+
LLVM 14: `llvm::createSinkingPass`
|
| 569 |
+
""" # noqa E501
|
| 570 |
+
ffi.lib.LLVMPY_AddSinkPass(self)
|
| 571 |
+
|
| 572 |
+
def add_strip_symbols_pass(self, only_debug=False):
|
| 573 |
+
"""
|
| 574 |
+
See https://llvm.org/docs/Passes.html#strip-strip-all-symbols-from-a-module
|
| 575 |
+
|
| 576 |
+
LLVM 14: `llvm::createStripSymbolsPass`
|
| 577 |
+
""" # noqa E501
|
| 578 |
+
ffi.lib.LLVMPY_AddStripSymbolsPass(self, only_debug)
|
| 579 |
+
|
| 580 |
+
def add_strip_dead_debug_info_pass(self):
|
| 581 |
+
"""
|
| 582 |
+
See https://llvm.org/docs/Passes.html#strip-dead-debug-info-strip-debug-info-for-unused-symbols
|
| 583 |
+
|
| 584 |
+
LLVM 14: `llvm::createStripDeadDebugInfoPass`
|
| 585 |
+
""" # noqa E501
|
| 586 |
+
ffi.lib.LLVMPY_AddStripDeadDebugInfoPass(self)
|
| 587 |
+
|
| 588 |
+
def add_strip_dead_prototypes_pass(self):
|
| 589 |
+
"""
|
| 590 |
+
See https://llvm.org/docs/Passes.html#strip-dead-prototypes-strip-unused-function-prototypes
|
| 591 |
+
|
| 592 |
+
LLVM 14: `llvm::createStripDeadPrototypesPass`
|
| 593 |
+
""" # noqa E501
|
| 594 |
+
ffi.lib.LLVMPY_AddStripDeadPrototypesPass(self)
|
| 595 |
+
|
| 596 |
+
def add_strip_debug_declare_pass(self):
|
| 597 |
+
"""
|
| 598 |
+
See https://llvm.org/docs/Passes.html#strip-debug-declare-strip-all-llvm-dbg-declare-intrinsics
|
| 599 |
+
|
| 600 |
+
LLVM 14: `llvm::createStripDebugDeclarePass`
|
| 601 |
+
""" # noqa E501
|
| 602 |
+
ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass(self)
|
| 603 |
+
|
| 604 |
+
def add_strip_nondebug_symbols_pass(self):
|
| 605 |
+
"""
|
| 606 |
+
See https://llvm.org/docs/Passes.html#strip-nondebug-strip-all-symbols-except-dbg-symbols-from-a-module
|
| 607 |
+
|
| 608 |
+
LLVM 14: `llvm::createStripNonDebugSymbolsPass`
|
| 609 |
+
""" # noqa E501
|
| 610 |
+
ffi.lib.LLVMPY_AddStripNondebugSymbolsPass(self)
|
| 611 |
+
|
| 612 |
+
def add_tail_call_elimination_pass(self):
|
| 613 |
+
"""
|
| 614 |
+
See https://llvm.org/docs/Passes.html#tailcallelim-tail-call-elimination
|
| 615 |
+
|
| 616 |
+
LLVM 14: `llvm::createTailCallEliminationPass`
|
| 617 |
+
""" # noqa E501
|
| 618 |
+
ffi.lib.LLVMPY_AddTailCallEliminationPass(self)
|
| 619 |
+
|
| 620 |
+
def add_type_based_alias_analysis_pass(self):
|
| 621 |
+
"""
|
| 622 |
+
LLVM 14: `LLVMAddTypeBasedAliasAnalysisPass`
|
| 623 |
+
""" # noqa E501
|
| 624 |
+
ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass(self)
|
| 625 |
+
|
| 626 |
+
def add_basic_alias_analysis_pass(self):
|
| 627 |
+
"""
|
| 628 |
+
See http://llvm.org/docs/AliasAnalysis.html#the-basicaa-pass
|
| 629 |
+
|
| 630 |
+
LLVM 14: `LLVMAddBasicAliasAnalysisPass`
|
| 631 |
+
"""
|
| 632 |
+
ffi.lib.LLVMPY_AddBasicAliasAnalysisPass(self)
|
| 633 |
+
|
| 634 |
+
def add_loop_rotate_pass(self):
|
| 635 |
+
"""http://llvm.org/docs/Passes.html#loop-rotate-rotate-loops."""
|
| 636 |
+
ffi.lib.LLVMPY_LLVMAddLoopRotatePass(self)
|
| 637 |
+
|
| 638 |
+
def add_target_library_info(self, triple):
|
| 639 |
+
ffi.lib.LLVMPY_AddTargetLibraryInfoPass(self, _encode_string(triple))
|
| 640 |
+
|
| 641 |
+
# Non-standard LLVM passes
|
| 642 |
+
|
| 643 |
+
def add_refprune_pass(self, subpasses_flags=RefPruneSubpasses.ALL,
|
| 644 |
+
subgraph_limit=1000):
|
| 645 |
+
"""Add Numba specific Reference count pruning pass.
|
| 646 |
+
|
| 647 |
+
Parameters
|
| 648 |
+
----------
|
| 649 |
+
subpasses_flags : RefPruneSubpasses
|
| 650 |
+
A bitmask to control the subpasses to be enabled.
|
| 651 |
+
subgraph_limit : int
|
| 652 |
+
Limit the fanout pruners to working on a subgraph no bigger than
|
| 653 |
+
this number of basic-blocks to avoid spending too much time in very
|
| 654 |
+
large graphs. Default is 1000. Subject to change in future
|
| 655 |
+
versions.
|
| 656 |
+
"""
|
| 657 |
+
iflags = RefPruneSubpasses(subpasses_flags)
|
| 658 |
+
ffi.lib.LLVMPY_AddRefPrunePass(self, iflags, subgraph_limit)
|
| 659 |
+
|
| 660 |
+
|
| 661 |
+
class ModulePassManager(PassManager):
|
| 662 |
+
|
| 663 |
+
def __init__(self, ptr=None):
|
| 664 |
+
if ptr is None:
|
| 665 |
+
ptr = ffi.lib.LLVMPY_CreatePassManager()
|
| 666 |
+
PassManager.__init__(self, ptr)
|
| 667 |
+
|
| 668 |
+
def run(self, module, remarks_file=None, remarks_format='yaml',
|
| 669 |
+
remarks_filter=''):
|
| 670 |
+
"""
|
| 671 |
+
Run optimization passes on the given module.
|
| 672 |
+
|
| 673 |
+
Parameters
|
| 674 |
+
----------
|
| 675 |
+
module : llvmlite.binding.ModuleRef
|
| 676 |
+
The module to be optimized inplace
|
| 677 |
+
remarks_file : str; optional
|
| 678 |
+
If not `None`, it is the file to store the optimization remarks.
|
| 679 |
+
remarks_format : str; optional
|
| 680 |
+
The format to write; YAML is default
|
| 681 |
+
remarks_filter : str; optional
|
| 682 |
+
The filter that should be applied to the remarks output.
|
| 683 |
+
"""
|
| 684 |
+
if remarks_file is None:
|
| 685 |
+
return ffi.lib.LLVMPY_RunPassManager(self, module)
|
| 686 |
+
else:
|
| 687 |
+
r = ffi.lib.LLVMPY_RunPassManagerWithRemarks(
|
| 688 |
+
self, module, _encode_string(remarks_format),
|
| 689 |
+
_encode_string(remarks_filter),
|
| 690 |
+
_encode_string(remarks_file))
|
| 691 |
+
if r == -1:
|
| 692 |
+
raise IOError("Failed to initialize remarks file.")
|
| 693 |
+
return r > 0
|
| 694 |
+
|
| 695 |
+
def run_with_remarks(self, module, remarks_format='yaml',
|
| 696 |
+
remarks_filter=''):
|
| 697 |
+
"""
|
| 698 |
+
Run optimization passes on the given module and returns the result and
|
| 699 |
+
the remarks data.
|
| 700 |
+
|
| 701 |
+
Parameters
|
| 702 |
+
----------
|
| 703 |
+
module : llvmlite.binding.ModuleRef
|
| 704 |
+
The module to be optimized
|
| 705 |
+
remarks_format : str
|
| 706 |
+
The remarks output; YAML is the default
|
| 707 |
+
remarks_filter : str; optional
|
| 708 |
+
The filter that should be applied to the remarks output.
|
| 709 |
+
"""
|
| 710 |
+
remarkdesc, remarkfile = mkstemp()
|
| 711 |
+
try:
|
| 712 |
+
with os.fdopen(remarkdesc, 'r'):
|
| 713 |
+
pass
|
| 714 |
+
r = self.run(module, remarkfile, remarks_format, remarks_filter)
|
| 715 |
+
if r == -1:
|
| 716 |
+
raise IOError("Failed to initialize remarks file.")
|
| 717 |
+
with open(remarkfile) as f:
|
| 718 |
+
return bool(r), f.read()
|
| 719 |
+
finally:
|
| 720 |
+
os.unlink(remarkfile)
|
| 721 |
+
|
| 722 |
+
|
| 723 |
+
class FunctionPassManager(PassManager):
|
| 724 |
+
|
| 725 |
+
def __init__(self, module):
|
| 726 |
+
ptr = ffi.lib.LLVMPY_CreateFunctionPassManager(module)
|
| 727 |
+
self._module = module
|
| 728 |
+
module._owned = True
|
| 729 |
+
PassManager.__init__(self, ptr)
|
| 730 |
+
|
| 731 |
+
def initialize(self):
|
| 732 |
+
"""
|
| 733 |
+
Initialize the FunctionPassManager. Returns True if it produced
|
| 734 |
+
any changes (?).
|
| 735 |
+
"""
|
| 736 |
+
return ffi.lib.LLVMPY_InitializeFunctionPassManager(self)
|
| 737 |
+
|
| 738 |
+
def finalize(self):
|
| 739 |
+
"""
|
| 740 |
+
Finalize the FunctionPassManager. Returns True if it produced
|
| 741 |
+
any changes (?).
|
| 742 |
+
"""
|
| 743 |
+
return ffi.lib.LLVMPY_FinalizeFunctionPassManager(self)
|
| 744 |
+
|
| 745 |
+
def run(self, function, remarks_file=None, remarks_format='yaml',
|
| 746 |
+
remarks_filter=''):
|
| 747 |
+
"""
|
| 748 |
+
Run optimization passes on the given function.
|
| 749 |
+
|
| 750 |
+
Parameters
|
| 751 |
+
----------
|
| 752 |
+
function : llvmlite.binding.FunctionRef
|
| 753 |
+
The function to be optimized inplace
|
| 754 |
+
remarks_file : str; optional
|
| 755 |
+
If not `None`, it is the file to store the optimization remarks.
|
| 756 |
+
remarks_format : str; optional
|
| 757 |
+
The format of the remarks file; the default is YAML
|
| 758 |
+
remarks_filter : str; optional
|
| 759 |
+
The filter that should be applied to the remarks output.
|
| 760 |
+
"""
|
| 761 |
+
if remarks_file is None:
|
| 762 |
+
return ffi.lib.LLVMPY_RunFunctionPassManager(self, function)
|
| 763 |
+
else:
|
| 764 |
+
r = ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks(
|
| 765 |
+
self, function, _encode_string(remarks_format),
|
| 766 |
+
_encode_string(remarks_filter),
|
| 767 |
+
_encode_string(remarks_file))
|
| 768 |
+
if r == -1:
|
| 769 |
+
raise IOError("Failed to initialize remarks file.")
|
| 770 |
+
return bool(r)
|
| 771 |
+
|
| 772 |
+
def run_with_remarks(self, function, remarks_format='yaml',
|
| 773 |
+
remarks_filter=''):
|
| 774 |
+
"""
|
| 775 |
+
Run optimization passes on the given function and returns the result
|
| 776 |
+
and the remarks data.
|
| 777 |
+
|
| 778 |
+
Parameters
|
| 779 |
+
----------
|
| 780 |
+
function : llvmlite.binding.FunctionRef
|
| 781 |
+
The function to be optimized inplace
|
| 782 |
+
remarks_format : str; optional
|
| 783 |
+
The format of the remarks file; the default is YAML
|
| 784 |
+
remarks_filter : str; optional
|
| 785 |
+
The filter that should be applied to the remarks output.
|
| 786 |
+
"""
|
| 787 |
+
# LLVM is going to need to close this file and then reopen it, so we
|
| 788 |
+
# can't use an unlinked temporary file.
|
| 789 |
+
remarkdesc, remarkfile = mkstemp()
|
| 790 |
+
try:
|
| 791 |
+
# We get an open handle, but we need LLVM to write first, so close
|
| 792 |
+
# it.
|
| 793 |
+
with os.fdopen(remarkdesc, 'r'):
|
| 794 |
+
pass
|
| 795 |
+
r = self.run(function, remarkfile, remarks_format, remarks_filter)
|
| 796 |
+
if r == -1:
|
| 797 |
+
raise IOError("Failed to initialize remarks file.")
|
| 798 |
+
with open(remarkfile) as f:
|
| 799 |
+
return bool(r), f.read()
|
| 800 |
+
finally:
|
| 801 |
+
os.unlink(remarkfile)
|
| 802 |
+
|
| 803 |
+
|
| 804 |
+
# ============================================================================
|
| 805 |
+
# FFI
|
| 806 |
+
|
| 807 |
+
ffi.lib.LLVMPY_CreatePassManager.restype = ffi.LLVMPassManagerRef
|
| 808 |
+
|
| 809 |
+
ffi.lib.LLVMPY_CreateFunctionPassManager.argtypes = [ffi.LLVMModuleRef]
|
| 810 |
+
ffi.lib.LLVMPY_CreateFunctionPassManager.restype = ffi.LLVMPassManagerRef
|
| 811 |
+
|
| 812 |
+
ffi.lib.LLVMPY_DisposePassManager.argtypes = [ffi.LLVMPassManagerRef]
|
| 813 |
+
|
| 814 |
+
ffi.lib.LLVMPY_RunPassManager.argtypes = [ffi.LLVMPassManagerRef,
|
| 815 |
+
ffi.LLVMModuleRef]
|
| 816 |
+
ffi.lib.LLVMPY_RunPassManager.restype = c_bool
|
| 817 |
+
|
| 818 |
+
ffi.lib.LLVMPY_RunPassManagerWithRemarks.argtypes = [ffi.LLVMPassManagerRef,
|
| 819 |
+
ffi.LLVMModuleRef,
|
| 820 |
+
c_char_p,
|
| 821 |
+
c_char_p,
|
| 822 |
+
c_char_p]
|
| 823 |
+
ffi.lib.LLVMPY_RunPassManagerWithRemarks.restype = c_int
|
| 824 |
+
|
| 825 |
+
ffi.lib.LLVMPY_InitializeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef]
|
| 826 |
+
ffi.lib.LLVMPY_InitializeFunctionPassManager.restype = c_bool
|
| 827 |
+
|
| 828 |
+
ffi.lib.LLVMPY_FinalizeFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef]
|
| 829 |
+
ffi.lib.LLVMPY_FinalizeFunctionPassManager.restype = c_bool
|
| 830 |
+
|
| 831 |
+
ffi.lib.LLVMPY_RunFunctionPassManager.argtypes = [ffi.LLVMPassManagerRef,
|
| 832 |
+
ffi.LLVMValueRef]
|
| 833 |
+
ffi.lib.LLVMPY_RunFunctionPassManager.restype = c_bool
|
| 834 |
+
|
| 835 |
+
ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.argtypes = [
|
| 836 |
+
ffi.LLVMPassManagerRef, ffi.LLVMValueRef, c_char_p, c_char_p, c_char_p
|
| 837 |
+
]
|
| 838 |
+
ffi.lib.LLVMPY_RunFunctionPassManagerWithRemarks.restype = c_int
|
| 839 |
+
|
| 840 |
+
ffi.lib.LLVMPY_AddAAEvalPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 841 |
+
ffi.lib.LLVMPY_AddBasicAAWrapperPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 842 |
+
ffi.lib.LLVMPY_AddConstantMergePass.argtypes = [ffi.LLVMPassManagerRef]
|
| 843 |
+
ffi.lib.LLVMPY_AddDeadArgEliminationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 844 |
+
ffi.lib.LLVMPY_AddDependenceAnalysisPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 845 |
+
ffi.lib.LLVMPY_AddCallGraphDOTPrinterPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 846 |
+
ffi.lib.LLVMPY_AddCFGPrinterPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 847 |
+
ffi.lib.LLVMPY_AddDotDomPrinterPass.argtypes = [ffi.LLVMPassManagerRef, c_bool]
|
| 848 |
+
ffi.lib.LLVMPY_AddDotPostDomPrinterPass.argtypes = [
|
| 849 |
+
ffi.LLVMPassManagerRef,
|
| 850 |
+
c_bool]
|
| 851 |
+
ffi.lib.LLVMPY_AddGlobalsModRefAAPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 852 |
+
ffi.lib.LLVMPY_AddInstructionCountPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 853 |
+
ffi.lib.LLVMPY_AddIVUsersPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 854 |
+
ffi.lib.LLVMPY_AddLazyValueInfoPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 855 |
+
ffi.lib.LLVMPY_AddLintPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 856 |
+
ffi.lib.LLVMPY_AddModuleDebugInfoPrinterPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 857 |
+
ffi.lib.LLVMPY_AddRegionInfoPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 858 |
+
ffi.lib.LLVMPY_AddScalarEvolutionAAPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 859 |
+
ffi.lib.LLVMPY_AddAggressiveDCEPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 860 |
+
ffi.lib.LLVMPY_AddAlwaysInlinerPass.argtypes = [ffi.LLVMPassManagerRef, c_bool]
|
| 861 |
+
ffi.lib.LLVMPY_AddArgPromotionPass.argtypes = [ffi.LLVMPassManagerRef, c_uint]
|
| 862 |
+
ffi.lib.LLVMPY_AddBreakCriticalEdgesPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 863 |
+
ffi.lib.LLVMPY_AddDeadStoreEliminationPass.argtypes = [
|
| 864 |
+
ffi.LLVMPassManagerRef]
|
| 865 |
+
ffi.lib.LLVMPY_AddReversePostOrderFunctionAttrsPass.argtypes = [
|
| 866 |
+
ffi.LLVMPassManagerRef]
|
| 867 |
+
ffi.lib.LLVMPY_AddAggressiveInstructionCombiningPass.argtypes = [
|
| 868 |
+
ffi.LLVMPassManagerRef]
|
| 869 |
+
ffi.lib.LLVMPY_AddInternalizePass.argtypes = [ffi.LLVMPassManagerRef]
|
| 870 |
+
ffi.lib.LLVMPY_AddLCSSAPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 871 |
+
ffi.lib.LLVMPY_AddLoopDeletionPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 872 |
+
ffi.lib.LLVMPY_AddLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 873 |
+
ffi.lib.LLVMPY_AddSingleLoopExtractorPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 874 |
+
ffi.lib.LLVMPY_AddLoopStrengthReducePass.argtypes = [ffi.LLVMPassManagerRef]
|
| 875 |
+
ffi.lib.LLVMPY_AddLoopSimplificationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 876 |
+
ffi.lib.LLVMPY_AddLoopUnrollPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 877 |
+
ffi.lib.LLVMPY_AddLoopUnrollAndJamPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 878 |
+
ffi.lib.LLVMPY_AddLoopUnswitchPass.argtypes = [
|
| 879 |
+
ffi.LLVMPassManagerRef,
|
| 880 |
+
c_bool,
|
| 881 |
+
c_bool]
|
| 882 |
+
ffi.lib.LLVMPY_AddLowerAtomicPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 883 |
+
ffi.lib.LLVMPY_AddLowerInvokePass.argtypes = [ffi.LLVMPassManagerRef]
|
| 884 |
+
ffi.lib.LLVMPY_AddLowerSwitchPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 885 |
+
ffi.lib.LLVMPY_AddMemCpyOptimizationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 886 |
+
ffi.lib.LLVMPY_AddMergeFunctionsPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 887 |
+
ffi.lib.LLVMPY_AddMergeReturnsPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 888 |
+
ffi.lib.LLVMPY_AddPartialInliningPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 889 |
+
ffi.lib.LLVMPY_AddPruneExceptionHandlingPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 890 |
+
ffi.lib.LLVMPY_AddReassociatePass.argtypes = [ffi.LLVMPassManagerRef]
|
| 891 |
+
ffi.lib.LLVMPY_AddDemoteRegisterToMemoryPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 892 |
+
ffi.lib.LLVMPY_AddSinkPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 893 |
+
ffi.lib.LLVMPY_AddStripSymbolsPass.argtypes = [ffi.LLVMPassManagerRef, c_bool]
|
| 894 |
+
ffi.lib.LLVMPY_AddStripDeadDebugInfoPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 895 |
+
ffi.lib.LLVMPY_AddStripDeadPrototypesPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 896 |
+
ffi.lib.LLVMPY_AddStripDebugDeclarePrototypesPass.argtypes = [
|
| 897 |
+
ffi.LLVMPassManagerRef]
|
| 898 |
+
ffi.lib.LLVMPY_AddStripNondebugSymbolsPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 899 |
+
ffi.lib.LLVMPY_AddTailCallEliminationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 900 |
+
ffi.lib.LLVMPY_AddJumpThreadingPass.argtypes = [ffi.LLVMPassManagerRef, c_int]
|
| 901 |
+
ffi.lib.LLVMPY_AddFunctionAttrsPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 902 |
+
ffi.lib.LLVMPY_AddFunctionInliningPass.argtypes = [
|
| 903 |
+
ffi.LLVMPassManagerRef, c_int]
|
| 904 |
+
ffi.lib.LLVMPY_AddGlobalDCEPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 905 |
+
ffi.lib.LLVMPY_AddGlobalOptimizerPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 906 |
+
ffi.lib.LLVMPY_AddIPSCCPPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 907 |
+
|
| 908 |
+
ffi.lib.LLVMPY_AddDeadCodeEliminationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 909 |
+
ffi.lib.LLVMPY_AddCFGSimplificationPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 910 |
+
ffi.lib.LLVMPY_AddGVNPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 911 |
+
ffi.lib.LLVMPY_AddInstructionCombiningPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 912 |
+
ffi.lib.LLVMPY_AddLICMPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 913 |
+
ffi.lib.LLVMPY_AddSCCPPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 914 |
+
ffi.lib.LLVMPY_AddSROAPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 915 |
+
ffi.lib.LLVMPY_AddTypeBasedAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 916 |
+
ffi.lib.LLVMPY_AddBasicAliasAnalysisPass.argtypes = [ffi.LLVMPassManagerRef]
|
| 917 |
+
ffi.lib.LLVMPY_AddTargetLibraryInfoPass.argtypes = [ffi.LLVMPassManagerRef,
|
| 918 |
+
c_char_p]
|
| 919 |
+
|
| 920 |
+
ffi.lib.LLVMPY_AddRefPrunePass.argtypes = [ffi.LLVMPassManagerRef, c_int,
|
| 921 |
+
c_size_t]
|
| 922 |
+
|
| 923 |
+
ffi.lib.LLVMPY_DumpRefPruneStats.argtypes = [POINTER(_c_PruneStats), c_bool]
|
lib/python3.11/site-packages/llvmlite/binding/targets.py
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from ctypes import (POINTER, c_char_p, c_longlong, c_int, c_size_t,
|
| 3 |
+
c_void_p, string_at)
|
| 4 |
+
|
| 5 |
+
from llvmlite.binding import ffi
|
| 6 |
+
from llvmlite.binding.common import _decode_string, _encode_string
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def get_process_triple():
|
| 10 |
+
"""
|
| 11 |
+
Return a target triple suitable for generating code for the current process.
|
| 12 |
+
An example when the default triple from ``get_default_triple()`` is not be
|
| 13 |
+
suitable is when LLVM is compiled for 32-bit but the process is executing
|
| 14 |
+
in 64-bit mode.
|
| 15 |
+
"""
|
| 16 |
+
with ffi.OutputString() as out:
|
| 17 |
+
ffi.lib.LLVMPY_GetProcessTriple(out)
|
| 18 |
+
return str(out)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class FeatureMap(dict):
|
| 22 |
+
"""
|
| 23 |
+
Maps feature name to a boolean indicating the availability of the feature.
|
| 24 |
+
Extends ``dict`` to add `.flatten()` method.
|
| 25 |
+
"""
|
| 26 |
+
|
| 27 |
+
def flatten(self, sort=True):
|
| 28 |
+
"""
|
| 29 |
+
Args
|
| 30 |
+
----
|
| 31 |
+
sort: bool
|
| 32 |
+
Optional. If True, the features are sorted by name; otherwise,
|
| 33 |
+
the ordering is unstable between python session due to hash
|
| 34 |
+
randomization. Defaults to True.
|
| 35 |
+
|
| 36 |
+
Returns a string suitable for use as the ``features`` argument to
|
| 37 |
+
``Target.create_target_machine()``.
|
| 38 |
+
|
| 39 |
+
"""
|
| 40 |
+
iterator = sorted(self.items()) if sort else iter(self.items())
|
| 41 |
+
flag_map = {True: '+', False: '-'}
|
| 42 |
+
return ','.join('{0}{1}'.format(flag_map[v], k)
|
| 43 |
+
for k, v in iterator)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def get_host_cpu_features():
|
| 47 |
+
"""
|
| 48 |
+
Returns a dictionary-like object indicating the CPU features for current
|
| 49 |
+
architecture and whether they are enabled for this CPU. The key-value pairs
|
| 50 |
+
are the feature name as string and a boolean indicating whether the feature
|
| 51 |
+
is available. The returned value is an instance of ``FeatureMap`` class,
|
| 52 |
+
which adds a new method ``.flatten()`` for returning a string suitable for
|
| 53 |
+
use as the "features" argument to ``Target.create_target_machine()``.
|
| 54 |
+
|
| 55 |
+
If LLVM has not implemented this feature or it fails to get the information,
|
| 56 |
+
this function will raise a RuntimeError exception.
|
| 57 |
+
"""
|
| 58 |
+
with ffi.OutputString() as out:
|
| 59 |
+
outdict = FeatureMap()
|
| 60 |
+
if not ffi.lib.LLVMPY_GetHostCPUFeatures(out):
|
| 61 |
+
return outdict
|
| 62 |
+
flag_map = {'+': True, '-': False}
|
| 63 |
+
content = str(out)
|
| 64 |
+
if content: # protect against empty string
|
| 65 |
+
for feat in content.split(','):
|
| 66 |
+
if feat: # protect against empty feature
|
| 67 |
+
outdict[feat[1:]] = flag_map[feat[0]]
|
| 68 |
+
return outdict
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def get_default_triple():
|
| 72 |
+
"""
|
| 73 |
+
Return the default target triple LLVM is configured to produce code for.
|
| 74 |
+
"""
|
| 75 |
+
with ffi.OutputString() as out:
|
| 76 |
+
ffi.lib.LLVMPY_GetDefaultTargetTriple(out)
|
| 77 |
+
return str(out)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def get_host_cpu_name():
|
| 81 |
+
"""
|
| 82 |
+
Get the name of the host's CPU, suitable for using with
|
| 83 |
+
:meth:`Target.create_target_machine()`.
|
| 84 |
+
"""
|
| 85 |
+
with ffi.OutputString() as out:
|
| 86 |
+
ffi.lib.LLVMPY_GetHostCPUName(out)
|
| 87 |
+
return str(out)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
_object_formats = {
|
| 91 |
+
1: "COFF",
|
| 92 |
+
2: "ELF",
|
| 93 |
+
3: "MachO",
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def get_object_format(triple=None):
|
| 98 |
+
"""
|
| 99 |
+
Get the object format for the given *triple* string (or the default
|
| 100 |
+
triple if omitted).
|
| 101 |
+
A string is returned
|
| 102 |
+
"""
|
| 103 |
+
if triple is None:
|
| 104 |
+
triple = get_default_triple()
|
| 105 |
+
res = ffi.lib.LLVMPY_GetTripleObjectFormat(_encode_string(triple))
|
| 106 |
+
return _object_formats[res]
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def create_target_data(layout):
|
| 110 |
+
"""
|
| 111 |
+
Create a TargetData instance for the given *layout* string.
|
| 112 |
+
"""
|
| 113 |
+
return TargetData(ffi.lib.LLVMPY_CreateTargetData(_encode_string(layout)))
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class TargetData(ffi.ObjectRef):
|
| 117 |
+
"""
|
| 118 |
+
A TargetData provides structured access to a data layout.
|
| 119 |
+
Use :func:`create_target_data` to create instances.
|
| 120 |
+
"""
|
| 121 |
+
|
| 122 |
+
def __str__(self):
|
| 123 |
+
if self._closed:
|
| 124 |
+
return "<dead TargetData>"
|
| 125 |
+
with ffi.OutputString() as out:
|
| 126 |
+
ffi.lib.LLVMPY_CopyStringRepOfTargetData(self, out)
|
| 127 |
+
return str(out)
|
| 128 |
+
|
| 129 |
+
def _dispose(self):
|
| 130 |
+
self._capi.LLVMPY_DisposeTargetData(self)
|
| 131 |
+
|
| 132 |
+
def get_abi_size(self, ty):
|
| 133 |
+
"""
|
| 134 |
+
Get ABI size of LLVM type *ty*.
|
| 135 |
+
"""
|
| 136 |
+
return ffi.lib.LLVMPY_ABISizeOfType(self, ty)
|
| 137 |
+
|
| 138 |
+
def get_element_offset(self, ty, position):
|
| 139 |
+
"""
|
| 140 |
+
Get byte offset of type's ty element at the given position
|
| 141 |
+
"""
|
| 142 |
+
|
| 143 |
+
offset = ffi.lib.LLVMPY_OffsetOfElement(self, ty, position)
|
| 144 |
+
if offset == -1:
|
| 145 |
+
raise ValueError("Could not determined offset of {}th "
|
| 146 |
+
"element of the type '{}'. Is it a struct"
|
| 147 |
+
"type?".format(position, str(ty)))
|
| 148 |
+
return offset
|
| 149 |
+
|
| 150 |
+
def get_pointee_abi_size(self, ty):
|
| 151 |
+
"""
|
| 152 |
+
Get ABI size of pointee type of LLVM pointer type *ty*.
|
| 153 |
+
"""
|
| 154 |
+
size = ffi.lib.LLVMPY_ABISizeOfElementType(self, ty)
|
| 155 |
+
if size == -1:
|
| 156 |
+
raise RuntimeError("Not a pointer type: %s" % (ty,))
|
| 157 |
+
return size
|
| 158 |
+
|
| 159 |
+
def get_pointee_abi_alignment(self, ty):
|
| 160 |
+
"""
|
| 161 |
+
Get minimum ABI alignment of pointee type of LLVM pointer type *ty*.
|
| 162 |
+
"""
|
| 163 |
+
size = ffi.lib.LLVMPY_ABIAlignmentOfElementType(self, ty)
|
| 164 |
+
if size == -1:
|
| 165 |
+
raise RuntimeError("Not a pointer type: %s" % (ty,))
|
| 166 |
+
return size
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
RELOC = frozenset(['default', 'static', 'pic', 'dynamicnopic'])
|
| 170 |
+
CODEMODEL = frozenset(['default', 'jitdefault', 'small', 'kernel', 'medium',
|
| 171 |
+
'large'])
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
class Target(ffi.ObjectRef):
|
| 175 |
+
_triple = ''
|
| 176 |
+
|
| 177 |
+
# No _dispose() method since LLVMGetTargetFromTriple() returns a
|
| 178 |
+
# persistent object.
|
| 179 |
+
|
| 180 |
+
@classmethod
|
| 181 |
+
def from_default_triple(cls):
|
| 182 |
+
"""
|
| 183 |
+
Create a Target instance for the default triple.
|
| 184 |
+
"""
|
| 185 |
+
triple = get_default_triple()
|
| 186 |
+
return cls.from_triple(triple)
|
| 187 |
+
|
| 188 |
+
@classmethod
|
| 189 |
+
def from_triple(cls, triple):
|
| 190 |
+
"""
|
| 191 |
+
Create a Target instance for the given triple (a string).
|
| 192 |
+
"""
|
| 193 |
+
with ffi.OutputString() as outerr:
|
| 194 |
+
target = ffi.lib.LLVMPY_GetTargetFromTriple(triple.encode('utf8'),
|
| 195 |
+
outerr)
|
| 196 |
+
if not target:
|
| 197 |
+
raise RuntimeError(str(outerr))
|
| 198 |
+
target = cls(target)
|
| 199 |
+
target._triple = triple
|
| 200 |
+
return target
|
| 201 |
+
|
| 202 |
+
@property
|
| 203 |
+
def name(self):
|
| 204 |
+
s = ffi.lib.LLVMPY_GetTargetName(self)
|
| 205 |
+
return _decode_string(s)
|
| 206 |
+
|
| 207 |
+
@property
|
| 208 |
+
def description(self):
|
| 209 |
+
s = ffi.lib.LLVMPY_GetTargetDescription(self)
|
| 210 |
+
return _decode_string(s)
|
| 211 |
+
|
| 212 |
+
@property
|
| 213 |
+
def triple(self):
|
| 214 |
+
return self._triple
|
| 215 |
+
|
| 216 |
+
def __str__(self):
|
| 217 |
+
return "<Target {0} ({1})>".format(self.name, self.description)
|
| 218 |
+
|
| 219 |
+
def create_target_machine(self, cpu='', features='',
|
| 220 |
+
opt=2, reloc='default', codemodel='jitdefault',
|
| 221 |
+
printmc=False, jit=False, abiname=''):
|
| 222 |
+
"""
|
| 223 |
+
Create a new TargetMachine for this target and the given options.
|
| 224 |
+
|
| 225 |
+
Specifying codemodel='default' will result in the use of the "small"
|
| 226 |
+
code model. Specifying codemodel='jitdefault' will result in the code
|
| 227 |
+
model being picked based on platform bitness (32="small", 64="large").
|
| 228 |
+
|
| 229 |
+
The `printmc` option corresponds to llvm's `-print-machineinstrs`.
|
| 230 |
+
|
| 231 |
+
The `jit` option should be set when the target-machine is to be used
|
| 232 |
+
in a JIT engine.
|
| 233 |
+
|
| 234 |
+
The `abiname` option specifies the ABI. RISC-V targets with hard-float
|
| 235 |
+
needs to pass the ABI name to LLVM.
|
| 236 |
+
"""
|
| 237 |
+
assert 0 <= opt <= 3
|
| 238 |
+
assert reloc in RELOC
|
| 239 |
+
assert codemodel in CODEMODEL
|
| 240 |
+
triple = self._triple
|
| 241 |
+
# MCJIT under Windows only supports ELF objects, see
|
| 242 |
+
# http://lists.llvm.org/pipermail/llvm-dev/2013-December/068341.html
|
| 243 |
+
# Note we still want to produce regular COFF files in AOT mode.
|
| 244 |
+
if os.name == 'nt' and codemodel == 'jitdefault':
|
| 245 |
+
triple += '-elf'
|
| 246 |
+
tm = ffi.lib.LLVMPY_CreateTargetMachine(self,
|
| 247 |
+
_encode_string(triple),
|
| 248 |
+
_encode_string(cpu),
|
| 249 |
+
_encode_string(features),
|
| 250 |
+
opt,
|
| 251 |
+
_encode_string(reloc),
|
| 252 |
+
_encode_string(codemodel),
|
| 253 |
+
int(printmc),
|
| 254 |
+
int(jit),
|
| 255 |
+
_encode_string(abiname),
|
| 256 |
+
)
|
| 257 |
+
if tm:
|
| 258 |
+
return TargetMachine(tm)
|
| 259 |
+
else:
|
| 260 |
+
raise RuntimeError("Cannot create target machine")
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
class TargetMachine(ffi.ObjectRef):
|
| 264 |
+
|
| 265 |
+
def _dispose(self):
|
| 266 |
+
self._capi.LLVMPY_DisposeTargetMachine(self)
|
| 267 |
+
|
| 268 |
+
def add_analysis_passes(self, pm):
|
| 269 |
+
"""
|
| 270 |
+
Register analysis passes for this target machine with a pass manager.
|
| 271 |
+
"""
|
| 272 |
+
ffi.lib.LLVMPY_AddAnalysisPasses(self, pm)
|
| 273 |
+
|
| 274 |
+
def set_asm_verbosity(self, verbose):
|
| 275 |
+
"""
|
| 276 |
+
Set whether this target machine will emit assembly with human-readable
|
| 277 |
+
comments describing control flow, debug information, and so on.
|
| 278 |
+
"""
|
| 279 |
+
ffi.lib.LLVMPY_SetTargetMachineAsmVerbosity(self, verbose)
|
| 280 |
+
|
| 281 |
+
def emit_object(self, module):
|
| 282 |
+
"""
|
| 283 |
+
Represent the module as a code object, suitable for use with
|
| 284 |
+
the platform's linker. Returns a byte string.
|
| 285 |
+
"""
|
| 286 |
+
return self._emit_to_memory(module, use_object=True)
|
| 287 |
+
|
| 288 |
+
def emit_assembly(self, module):
|
| 289 |
+
"""
|
| 290 |
+
Return the raw assembler of the module, as a string.
|
| 291 |
+
|
| 292 |
+
llvm.initialize_native_asmprinter() must have been called first.
|
| 293 |
+
"""
|
| 294 |
+
return _decode_string(self._emit_to_memory(module, use_object=False))
|
| 295 |
+
|
| 296 |
+
def _emit_to_memory(self, module, use_object=False):
|
| 297 |
+
"""Returns bytes of object code of the module.
|
| 298 |
+
|
| 299 |
+
Args
|
| 300 |
+
----
|
| 301 |
+
use_object : bool
|
| 302 |
+
Emit object code or (if False) emit assembly code.
|
| 303 |
+
"""
|
| 304 |
+
with ffi.OutputString() as outerr:
|
| 305 |
+
mb = ffi.lib.LLVMPY_TargetMachineEmitToMemory(self, module,
|
| 306 |
+
int(use_object),
|
| 307 |
+
outerr)
|
| 308 |
+
if not mb:
|
| 309 |
+
raise RuntimeError(str(outerr))
|
| 310 |
+
|
| 311 |
+
bufptr = ffi.lib.LLVMPY_GetBufferStart(mb)
|
| 312 |
+
bufsz = ffi.lib.LLVMPY_GetBufferSize(mb)
|
| 313 |
+
try:
|
| 314 |
+
return string_at(bufptr, bufsz)
|
| 315 |
+
finally:
|
| 316 |
+
ffi.lib.LLVMPY_DisposeMemoryBuffer(mb)
|
| 317 |
+
|
| 318 |
+
@property
|
| 319 |
+
def target_data(self):
|
| 320 |
+
return TargetData(ffi.lib.LLVMPY_CreateTargetMachineData(self))
|
| 321 |
+
|
| 322 |
+
@property
|
| 323 |
+
def triple(self):
|
| 324 |
+
with ffi.OutputString() as out:
|
| 325 |
+
ffi.lib.LLVMPY_GetTargetMachineTriple(self, out)
|
| 326 |
+
return str(out)
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
def has_svml():
|
| 330 |
+
"""
|
| 331 |
+
Returns True if SVML was enabled at FFI support compile time.
|
| 332 |
+
"""
|
| 333 |
+
if ffi.lib.LLVMPY_HasSVMLSupport() == 0:
|
| 334 |
+
return False
|
| 335 |
+
else:
|
| 336 |
+
return True
|
| 337 |
+
|
| 338 |
+
|
| 339 |
+
# ============================================================================
|
| 340 |
+
# FFI
|
| 341 |
+
|
| 342 |
+
ffi.lib.LLVMPY_GetProcessTriple.argtypes = [POINTER(c_char_p)]
|
| 343 |
+
|
| 344 |
+
ffi.lib.LLVMPY_GetHostCPUFeatures.argtypes = [POINTER(c_char_p)]
|
| 345 |
+
ffi.lib.LLVMPY_GetHostCPUFeatures.restype = c_int
|
| 346 |
+
|
| 347 |
+
ffi.lib.LLVMPY_GetDefaultTargetTriple.argtypes = [POINTER(c_char_p)]
|
| 348 |
+
|
| 349 |
+
ffi.lib.LLVMPY_GetHostCPUName.argtypes = [POINTER(c_char_p)]
|
| 350 |
+
|
| 351 |
+
ffi.lib.LLVMPY_GetTripleObjectFormat.argtypes = [c_char_p]
|
| 352 |
+
ffi.lib.LLVMPY_GetTripleObjectFormat.restype = c_int
|
| 353 |
+
|
| 354 |
+
ffi.lib.LLVMPY_CreateTargetData.argtypes = [c_char_p]
|
| 355 |
+
ffi.lib.LLVMPY_CreateTargetData.restype = ffi.LLVMTargetDataRef
|
| 356 |
+
|
| 357 |
+
ffi.lib.LLVMPY_CopyStringRepOfTargetData.argtypes = [
|
| 358 |
+
ffi.LLVMTargetDataRef,
|
| 359 |
+
POINTER(c_char_p),
|
| 360 |
+
]
|
| 361 |
+
|
| 362 |
+
ffi.lib.LLVMPY_DisposeTargetData.argtypes = [
|
| 363 |
+
ffi.LLVMTargetDataRef,
|
| 364 |
+
]
|
| 365 |
+
|
| 366 |
+
ffi.lib.LLVMPY_ABISizeOfType.argtypes = [ffi.LLVMTargetDataRef,
|
| 367 |
+
ffi.LLVMTypeRef]
|
| 368 |
+
ffi.lib.LLVMPY_ABISizeOfType.restype = c_longlong
|
| 369 |
+
|
| 370 |
+
ffi.lib.LLVMPY_OffsetOfElement.argtypes = [ffi.LLVMTargetDataRef,
|
| 371 |
+
ffi.LLVMTypeRef,
|
| 372 |
+
c_int]
|
| 373 |
+
ffi.lib.LLVMPY_OffsetOfElement.restype = c_longlong
|
| 374 |
+
|
| 375 |
+
ffi.lib.LLVMPY_ABISizeOfElementType.argtypes = [ffi.LLVMTargetDataRef,
|
| 376 |
+
ffi.LLVMTypeRef]
|
| 377 |
+
ffi.lib.LLVMPY_ABISizeOfElementType.restype = c_longlong
|
| 378 |
+
|
| 379 |
+
ffi.lib.LLVMPY_ABIAlignmentOfElementType.argtypes = [ffi.LLVMTargetDataRef,
|
| 380 |
+
ffi.LLVMTypeRef]
|
| 381 |
+
ffi.lib.LLVMPY_ABIAlignmentOfElementType.restype = c_longlong
|
| 382 |
+
|
| 383 |
+
ffi.lib.LLVMPY_GetTargetFromTriple.argtypes = [c_char_p, POINTER(c_char_p)]
|
| 384 |
+
ffi.lib.LLVMPY_GetTargetFromTriple.restype = ffi.LLVMTargetRef
|
| 385 |
+
|
| 386 |
+
ffi.lib.LLVMPY_GetTargetName.argtypes = [ffi.LLVMTargetRef]
|
| 387 |
+
ffi.lib.LLVMPY_GetTargetName.restype = c_char_p
|
| 388 |
+
|
| 389 |
+
ffi.lib.LLVMPY_GetTargetDescription.argtypes = [ffi.LLVMTargetRef]
|
| 390 |
+
ffi.lib.LLVMPY_GetTargetDescription.restype = c_char_p
|
| 391 |
+
|
| 392 |
+
ffi.lib.LLVMPY_CreateTargetMachine.argtypes = [
|
| 393 |
+
ffi.LLVMTargetRef,
|
| 394 |
+
# Triple
|
| 395 |
+
c_char_p,
|
| 396 |
+
# CPU
|
| 397 |
+
c_char_p,
|
| 398 |
+
# Features
|
| 399 |
+
c_char_p,
|
| 400 |
+
# OptLevel
|
| 401 |
+
c_int,
|
| 402 |
+
# Reloc
|
| 403 |
+
c_char_p,
|
| 404 |
+
# CodeModel
|
| 405 |
+
c_char_p,
|
| 406 |
+
# PrintMC
|
| 407 |
+
c_int,
|
| 408 |
+
# JIT
|
| 409 |
+
c_int,
|
| 410 |
+
# ABIName
|
| 411 |
+
c_char_p,
|
| 412 |
+
]
|
| 413 |
+
ffi.lib.LLVMPY_CreateTargetMachine.restype = ffi.LLVMTargetMachineRef
|
| 414 |
+
|
| 415 |
+
ffi.lib.LLVMPY_DisposeTargetMachine.argtypes = [ffi.LLVMTargetMachineRef]
|
| 416 |
+
|
| 417 |
+
ffi.lib.LLVMPY_GetTargetMachineTriple.argtypes = [ffi.LLVMTargetMachineRef,
|
| 418 |
+
POINTER(c_char_p)]
|
| 419 |
+
|
| 420 |
+
ffi.lib.LLVMPY_SetTargetMachineAsmVerbosity.argtypes = [
|
| 421 |
+
ffi.LLVMTargetMachineRef, c_int]
|
| 422 |
+
|
| 423 |
+
ffi.lib.LLVMPY_AddAnalysisPasses.argtypes = [
|
| 424 |
+
ffi.LLVMTargetMachineRef,
|
| 425 |
+
ffi.LLVMPassManagerRef,
|
| 426 |
+
]
|
| 427 |
+
|
| 428 |
+
ffi.lib.LLVMPY_TargetMachineEmitToMemory.argtypes = [
|
| 429 |
+
ffi.LLVMTargetMachineRef,
|
| 430 |
+
ffi.LLVMModuleRef,
|
| 431 |
+
c_int,
|
| 432 |
+
POINTER(c_char_p),
|
| 433 |
+
]
|
| 434 |
+
ffi.lib.LLVMPY_TargetMachineEmitToMemory.restype = ffi.LLVMMemoryBufferRef
|
| 435 |
+
|
| 436 |
+
ffi.lib.LLVMPY_GetBufferStart.argtypes = [ffi.LLVMMemoryBufferRef]
|
| 437 |
+
ffi.lib.LLVMPY_GetBufferStart.restype = c_void_p
|
| 438 |
+
|
| 439 |
+
ffi.lib.LLVMPY_GetBufferSize.argtypes = [ffi.LLVMMemoryBufferRef]
|
| 440 |
+
ffi.lib.LLVMPY_GetBufferSize.restype = c_size_t
|
| 441 |
+
|
| 442 |
+
ffi.lib.LLVMPY_DisposeMemoryBuffer.argtypes = [ffi.LLVMMemoryBufferRef]
|
| 443 |
+
|
| 444 |
+
ffi.lib.LLVMPY_CreateTargetMachineData.argtypes = [
|
| 445 |
+
ffi.LLVMTargetMachineRef,
|
| 446 |
+
]
|
| 447 |
+
ffi.lib.LLVMPY_CreateTargetMachineData.restype = ffi.LLVMTargetDataRef
|
| 448 |
+
|
| 449 |
+
ffi.lib.LLVMPY_HasSVMLSupport.argtypes = []
|
| 450 |
+
ffi.lib.LLVMPY_HasSVMLSupport.restype = c_int
|
lib/python3.11/site-packages/llvmlite/binding/transforms.py
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import c_uint, c_bool
|
| 2 |
+
from llvmlite.binding import ffi
|
| 3 |
+
from llvmlite.binding import passmanagers
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def create_pass_manager_builder():
|
| 7 |
+
return PassManagerBuilder()
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class PassManagerBuilder(ffi.ObjectRef):
|
| 11 |
+
__slots__ = ()
|
| 12 |
+
|
| 13 |
+
def __init__(self, ptr=None):
|
| 14 |
+
if ptr is None:
|
| 15 |
+
ptr = ffi.lib.LLVMPY_PassManagerBuilderCreate()
|
| 16 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 17 |
+
|
| 18 |
+
@property
|
| 19 |
+
def opt_level(self):
|
| 20 |
+
"""
|
| 21 |
+
The general optimization level as an integer between 0 and 3.
|
| 22 |
+
"""
|
| 23 |
+
return ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel(self)
|
| 24 |
+
|
| 25 |
+
@opt_level.setter
|
| 26 |
+
def opt_level(self, level):
|
| 27 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel(self, level)
|
| 28 |
+
|
| 29 |
+
@property
|
| 30 |
+
def size_level(self):
|
| 31 |
+
"""
|
| 32 |
+
Whether and how much to optimize for size. An integer between 0 and 2.
|
| 33 |
+
"""
|
| 34 |
+
return ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel(self)
|
| 35 |
+
|
| 36 |
+
@size_level.setter
|
| 37 |
+
def size_level(self, size):
|
| 38 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel(self, size)
|
| 39 |
+
|
| 40 |
+
@property
|
| 41 |
+
def inlining_threshold(self):
|
| 42 |
+
"""
|
| 43 |
+
The integer threshold for inlining a function into another. The higher,
|
| 44 |
+
the more likely inlining a function is. This attribute is write-only.
|
| 45 |
+
"""
|
| 46 |
+
raise NotImplementedError("inlining_threshold is write-only")
|
| 47 |
+
|
| 48 |
+
@inlining_threshold.setter
|
| 49 |
+
def inlining_threshold(self, threshold):
|
| 50 |
+
ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold(
|
| 51 |
+
self, threshold)
|
| 52 |
+
|
| 53 |
+
@property
|
| 54 |
+
def disable_unroll_loops(self):
|
| 55 |
+
"""
|
| 56 |
+
If true, disable loop unrolling.
|
| 57 |
+
"""
|
| 58 |
+
return ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops(self)
|
| 59 |
+
|
| 60 |
+
@disable_unroll_loops.setter
|
| 61 |
+
def disable_unroll_loops(self, disable=True):
|
| 62 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops(self, disable)
|
| 63 |
+
|
| 64 |
+
@property
|
| 65 |
+
def loop_vectorize(self):
|
| 66 |
+
"""
|
| 67 |
+
If true, allow vectorizing loops.
|
| 68 |
+
"""
|
| 69 |
+
return ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize(self)
|
| 70 |
+
|
| 71 |
+
@loop_vectorize.setter
|
| 72 |
+
def loop_vectorize(self, enable=True):
|
| 73 |
+
return ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize(self, enable)
|
| 74 |
+
|
| 75 |
+
@property
|
| 76 |
+
def slp_vectorize(self):
|
| 77 |
+
"""
|
| 78 |
+
If true, enable the "SLP vectorizer", which uses a different algorithm
|
| 79 |
+
from the loop vectorizer. Both may be enabled at the same time.
|
| 80 |
+
"""
|
| 81 |
+
return ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize(self)
|
| 82 |
+
|
| 83 |
+
@slp_vectorize.setter
|
| 84 |
+
def slp_vectorize(self, enable=True):
|
| 85 |
+
return ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize(self, enable)
|
| 86 |
+
|
| 87 |
+
def _populate_module_pm(self, pm):
|
| 88 |
+
ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager(self, pm)
|
| 89 |
+
|
| 90 |
+
def _populate_function_pm(self, pm):
|
| 91 |
+
ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager(self, pm)
|
| 92 |
+
|
| 93 |
+
def populate(self, pm):
|
| 94 |
+
if isinstance(pm, passmanagers.ModulePassManager):
|
| 95 |
+
self._populate_module_pm(pm)
|
| 96 |
+
elif isinstance(pm, passmanagers.FunctionPassManager):
|
| 97 |
+
self._populate_function_pm(pm)
|
| 98 |
+
else:
|
| 99 |
+
raise TypeError(pm)
|
| 100 |
+
|
| 101 |
+
def _dispose(self):
|
| 102 |
+
self._capi.LLVMPY_PassManagerBuilderDispose(self)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
# ============================================================================
|
| 106 |
+
# FFI
|
| 107 |
+
|
| 108 |
+
ffi.lib.LLVMPY_PassManagerBuilderCreate.restype = ffi.LLVMPassManagerBuilderRef
|
| 109 |
+
|
| 110 |
+
ffi.lib.LLVMPY_PassManagerBuilderDispose.argtypes = [
|
| 111 |
+
ffi.LLVMPassManagerBuilderRef,
|
| 112 |
+
]
|
| 113 |
+
|
| 114 |
+
ffi.lib.LLVMPY_PassManagerBuilderPopulateModulePassManager.argtypes = [
|
| 115 |
+
ffi.LLVMPassManagerBuilderRef,
|
| 116 |
+
ffi.LLVMPassManagerRef,
|
| 117 |
+
]
|
| 118 |
+
|
| 119 |
+
ffi.lib.LLVMPY_PassManagerBuilderPopulateFunctionPassManager.argtypes = [
|
| 120 |
+
ffi.LLVMPassManagerBuilderRef,
|
| 121 |
+
ffi.LLVMPassManagerRef,
|
| 122 |
+
]
|
| 123 |
+
|
| 124 |
+
# Unsigned int PassManagerBuilder properties
|
| 125 |
+
|
| 126 |
+
for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetOptLevel,
|
| 127 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetSizeLevel,
|
| 128 |
+
ffi.lib.LLVMPY_PassManagerBuilderUseInlinerWithThreshold,
|
| 129 |
+
):
|
| 130 |
+
_func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_uint]
|
| 131 |
+
|
| 132 |
+
for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetOptLevel,
|
| 133 |
+
ffi.lib.LLVMPY_PassManagerBuilderGetSizeLevel,
|
| 134 |
+
):
|
| 135 |
+
_func.argtypes = [ffi.LLVMPassManagerBuilderRef]
|
| 136 |
+
_func.restype = c_uint
|
| 137 |
+
|
| 138 |
+
# Boolean PassManagerBuilder properties
|
| 139 |
+
|
| 140 |
+
for _func in (ffi.lib.LLVMPY_PassManagerBuilderSetDisableUnrollLoops,
|
| 141 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetLoopVectorize,
|
| 142 |
+
ffi.lib.LLVMPY_PassManagerBuilderSetSLPVectorize,
|
| 143 |
+
):
|
| 144 |
+
_func.argtypes = [ffi.LLVMPassManagerBuilderRef, c_bool]
|
| 145 |
+
|
| 146 |
+
for _func in (ffi.lib.LLVMPY_PassManagerBuilderGetDisableUnrollLoops,
|
| 147 |
+
ffi.lib.LLVMPY_PassManagerBuilderGetLoopVectorize,
|
| 148 |
+
ffi.lib.LLVMPY_PassManagerBuilderGetSLPVectorize,
|
| 149 |
+
):
|
| 150 |
+
_func.argtypes = [ffi.LLVMPassManagerBuilderRef]
|
| 151 |
+
_func.restype = c_bool
|
lib/python3.11/site-packages/llvmlite/binding/value.py
ADDED
|
@@ -0,0 +1,624 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from ctypes import (POINTER, byref, cast, c_char_p, c_double, c_int, c_size_t,
|
| 2 |
+
c_uint, c_uint64, c_bool, c_void_p)
|
| 3 |
+
import enum
|
| 4 |
+
|
| 5 |
+
from llvmlite.binding import ffi
|
| 6 |
+
from llvmlite.binding.common import _decode_string, _encode_string
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class Linkage(enum.IntEnum):
|
| 10 |
+
# The LLVMLinkage enum from llvm-c/Core.h
|
| 11 |
+
|
| 12 |
+
external = 0
|
| 13 |
+
available_externally = 1
|
| 14 |
+
linkonce_any = 2
|
| 15 |
+
linkonce_odr = 3
|
| 16 |
+
linkonce_odr_autohide = 4
|
| 17 |
+
weak_any = 5
|
| 18 |
+
weak_odr = 6
|
| 19 |
+
appending = 7
|
| 20 |
+
internal = 8
|
| 21 |
+
private = 9
|
| 22 |
+
dllimport = 10
|
| 23 |
+
dllexport = 11
|
| 24 |
+
external_weak = 12
|
| 25 |
+
ghost = 13
|
| 26 |
+
common = 14
|
| 27 |
+
linker_private = 15
|
| 28 |
+
linker_private_weak = 16
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class Visibility(enum.IntEnum):
|
| 32 |
+
# The LLVMVisibility enum from llvm-c/Core.h
|
| 33 |
+
|
| 34 |
+
default = 0
|
| 35 |
+
hidden = 1
|
| 36 |
+
protected = 2
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class StorageClass(enum.IntEnum):
|
| 40 |
+
# The LLVMDLLStorageClass enum from llvm-c/Core.h
|
| 41 |
+
|
| 42 |
+
default = 0
|
| 43 |
+
dllimport = 1
|
| 44 |
+
dllexport = 2
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
class ValueKind(enum.IntEnum):
|
| 48 |
+
# The LLVMValueKind enum from llvm-c/Core.h
|
| 49 |
+
|
| 50 |
+
argument = 0
|
| 51 |
+
basic_block = 1
|
| 52 |
+
memory_use = 2
|
| 53 |
+
memory_def = 3
|
| 54 |
+
memory_phi = 4
|
| 55 |
+
|
| 56 |
+
function = 5
|
| 57 |
+
global_alias = 6
|
| 58 |
+
global_ifunc = 7
|
| 59 |
+
global_variable = 8
|
| 60 |
+
block_address = 9
|
| 61 |
+
constant_expr = 10
|
| 62 |
+
constant_array = 11
|
| 63 |
+
constant_struct = 12
|
| 64 |
+
constant_vector = 13
|
| 65 |
+
|
| 66 |
+
undef_value = 14
|
| 67 |
+
constant_aggregate_zero = 15
|
| 68 |
+
constant_data_array = 16
|
| 69 |
+
constant_data_vector = 17
|
| 70 |
+
constant_int = 18
|
| 71 |
+
constant_fp = 19
|
| 72 |
+
constant_pointer_null = 20
|
| 73 |
+
constant_token_none = 21
|
| 74 |
+
|
| 75 |
+
metadata_as_value = 22
|
| 76 |
+
inline_asm = 23
|
| 77 |
+
|
| 78 |
+
instruction = 24
|
| 79 |
+
poison_value = 25
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class TypeRef(ffi.ObjectRef):
|
| 83 |
+
"""A weak reference to a LLVM type
|
| 84 |
+
"""
|
| 85 |
+
@property
|
| 86 |
+
def name(self):
|
| 87 |
+
"""
|
| 88 |
+
Get type name
|
| 89 |
+
"""
|
| 90 |
+
return ffi.ret_string(ffi.lib.LLVMPY_GetTypeName(self))
|
| 91 |
+
|
| 92 |
+
@property
|
| 93 |
+
def is_pointer(self):
|
| 94 |
+
"""
|
| 95 |
+
Returns true is the type is a pointer type.
|
| 96 |
+
"""
|
| 97 |
+
return ffi.lib.LLVMPY_TypeIsPointer(self)
|
| 98 |
+
|
| 99 |
+
@property
|
| 100 |
+
def element_type(self):
|
| 101 |
+
"""
|
| 102 |
+
Returns the pointed-to type. When the type is not a pointer,
|
| 103 |
+
raises exception.
|
| 104 |
+
"""
|
| 105 |
+
if not self.is_pointer:
|
| 106 |
+
raise ValueError("Type {} is not a pointer".format(self))
|
| 107 |
+
return TypeRef(ffi.lib.LLVMPY_GetElementType(self))
|
| 108 |
+
|
| 109 |
+
def __str__(self):
|
| 110 |
+
return ffi.ret_string(ffi.lib.LLVMPY_PrintType(self))
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
class ValueRef(ffi.ObjectRef):
|
| 114 |
+
"""A weak reference to a LLVM value.
|
| 115 |
+
"""
|
| 116 |
+
|
| 117 |
+
def __init__(self, ptr, kind, parents):
|
| 118 |
+
self._kind = kind
|
| 119 |
+
self._parents = parents
|
| 120 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 121 |
+
|
| 122 |
+
def __str__(self):
|
| 123 |
+
with ffi.OutputString() as outstr:
|
| 124 |
+
ffi.lib.LLVMPY_PrintValueToString(self, outstr)
|
| 125 |
+
return str(outstr)
|
| 126 |
+
|
| 127 |
+
@property
|
| 128 |
+
def module(self):
|
| 129 |
+
"""
|
| 130 |
+
The module this function or global variable value was obtained from.
|
| 131 |
+
"""
|
| 132 |
+
return self._parents.get('module')
|
| 133 |
+
|
| 134 |
+
@property
|
| 135 |
+
def function(self):
|
| 136 |
+
"""
|
| 137 |
+
The function this argument or basic block value was obtained from.
|
| 138 |
+
"""
|
| 139 |
+
return self._parents.get('function')
|
| 140 |
+
|
| 141 |
+
@property
|
| 142 |
+
def block(self):
|
| 143 |
+
"""
|
| 144 |
+
The block this instruction value was obtained from.
|
| 145 |
+
"""
|
| 146 |
+
return self._parents.get('block')
|
| 147 |
+
|
| 148 |
+
@property
|
| 149 |
+
def instruction(self):
|
| 150 |
+
"""
|
| 151 |
+
The instruction this operand value was obtained from.
|
| 152 |
+
"""
|
| 153 |
+
return self._parents.get('instruction')
|
| 154 |
+
|
| 155 |
+
@property
|
| 156 |
+
def is_global(self):
|
| 157 |
+
return self._kind == 'global'
|
| 158 |
+
|
| 159 |
+
@property
|
| 160 |
+
def is_function(self):
|
| 161 |
+
return self._kind == 'function'
|
| 162 |
+
|
| 163 |
+
@property
|
| 164 |
+
def is_block(self):
|
| 165 |
+
return self._kind == 'block'
|
| 166 |
+
|
| 167 |
+
@property
|
| 168 |
+
def is_argument(self):
|
| 169 |
+
return self._kind == 'argument'
|
| 170 |
+
|
| 171 |
+
@property
|
| 172 |
+
def is_instruction(self):
|
| 173 |
+
return self._kind == 'instruction'
|
| 174 |
+
|
| 175 |
+
@property
|
| 176 |
+
def is_operand(self):
|
| 177 |
+
return self._kind == 'operand'
|
| 178 |
+
|
| 179 |
+
@property
|
| 180 |
+
def is_constant(self):
|
| 181 |
+
return bool(ffi.lib.LLVMPY_IsConstant(self))
|
| 182 |
+
|
| 183 |
+
@property
|
| 184 |
+
def value_kind(self):
|
| 185 |
+
return ValueKind(ffi.lib.LLVMPY_GetValueKind(self))
|
| 186 |
+
|
| 187 |
+
@property
|
| 188 |
+
def name(self):
|
| 189 |
+
return _decode_string(ffi.lib.LLVMPY_GetValueName(self))
|
| 190 |
+
|
| 191 |
+
@name.setter
|
| 192 |
+
def name(self, val):
|
| 193 |
+
ffi.lib.LLVMPY_SetValueName(self, _encode_string(val))
|
| 194 |
+
|
| 195 |
+
@property
|
| 196 |
+
def linkage(self):
|
| 197 |
+
return Linkage(ffi.lib.LLVMPY_GetLinkage(self))
|
| 198 |
+
|
| 199 |
+
@linkage.setter
|
| 200 |
+
def linkage(self, value):
|
| 201 |
+
if not isinstance(value, Linkage):
|
| 202 |
+
value = Linkage[value]
|
| 203 |
+
ffi.lib.LLVMPY_SetLinkage(self, value)
|
| 204 |
+
|
| 205 |
+
@property
|
| 206 |
+
def visibility(self):
|
| 207 |
+
return Visibility(ffi.lib.LLVMPY_GetVisibility(self))
|
| 208 |
+
|
| 209 |
+
@visibility.setter
|
| 210 |
+
def visibility(self, value):
|
| 211 |
+
if not isinstance(value, Visibility):
|
| 212 |
+
value = Visibility[value]
|
| 213 |
+
ffi.lib.LLVMPY_SetVisibility(self, value)
|
| 214 |
+
|
| 215 |
+
@property
|
| 216 |
+
def storage_class(self):
|
| 217 |
+
return StorageClass(ffi.lib.LLVMPY_GetDLLStorageClass(self))
|
| 218 |
+
|
| 219 |
+
@storage_class.setter
|
| 220 |
+
def storage_class(self, value):
|
| 221 |
+
if not isinstance(value, StorageClass):
|
| 222 |
+
value = StorageClass[value]
|
| 223 |
+
ffi.lib.LLVMPY_SetDLLStorageClass(self, value)
|
| 224 |
+
|
| 225 |
+
def add_function_attribute(self, attr):
|
| 226 |
+
"""Only works on function value
|
| 227 |
+
|
| 228 |
+
Parameters
|
| 229 |
+
-----------
|
| 230 |
+
attr : str
|
| 231 |
+
attribute name
|
| 232 |
+
"""
|
| 233 |
+
if not self.is_function:
|
| 234 |
+
raise ValueError('expected function value, got %s' % (self._kind,))
|
| 235 |
+
attrname = str(attr)
|
| 236 |
+
attrval = ffi.lib.LLVMPY_GetEnumAttributeKindForName(
|
| 237 |
+
_encode_string(attrname), len(attrname))
|
| 238 |
+
if attrval == 0:
|
| 239 |
+
raise ValueError('no such attribute {!r}'.format(attrname))
|
| 240 |
+
ffi.lib.LLVMPY_AddFunctionAttr(self, attrval)
|
| 241 |
+
|
| 242 |
+
@property
|
| 243 |
+
def type(self):
|
| 244 |
+
"""
|
| 245 |
+
This value's LLVM type.
|
| 246 |
+
"""
|
| 247 |
+
# XXX what does this return?
|
| 248 |
+
return TypeRef(ffi.lib.LLVMPY_TypeOf(self))
|
| 249 |
+
|
| 250 |
+
@property
|
| 251 |
+
def is_declaration(self):
|
| 252 |
+
"""
|
| 253 |
+
Whether this value (presumably global) is defined in the current
|
| 254 |
+
module.
|
| 255 |
+
"""
|
| 256 |
+
if not (self.is_global or self.is_function):
|
| 257 |
+
raise ValueError('expected global or function value, got %s'
|
| 258 |
+
% (self._kind,))
|
| 259 |
+
return ffi.lib.LLVMPY_IsDeclaration(self)
|
| 260 |
+
|
| 261 |
+
@property
|
| 262 |
+
def attributes(self):
|
| 263 |
+
"""
|
| 264 |
+
Return an iterator over this value's attributes.
|
| 265 |
+
The iterator will yield a string for each attribute.
|
| 266 |
+
"""
|
| 267 |
+
itr = iter(())
|
| 268 |
+
if self.is_function:
|
| 269 |
+
it = ffi.lib.LLVMPY_FunctionAttributesIter(self)
|
| 270 |
+
itr = _AttributeListIterator(it)
|
| 271 |
+
elif self.is_instruction:
|
| 272 |
+
if self.opcode == 'call':
|
| 273 |
+
it = ffi.lib.LLVMPY_CallInstAttributesIter(self)
|
| 274 |
+
itr = _AttributeListIterator(it)
|
| 275 |
+
elif self.opcode == 'invoke':
|
| 276 |
+
it = ffi.lib.LLVMPY_InvokeInstAttributesIter(self)
|
| 277 |
+
itr = _AttributeListIterator(it)
|
| 278 |
+
elif self.is_global:
|
| 279 |
+
it = ffi.lib.LLVMPY_GlobalAttributesIter(self)
|
| 280 |
+
itr = _AttributeSetIterator(it)
|
| 281 |
+
elif self.is_argument:
|
| 282 |
+
it = ffi.lib.LLVMPY_ArgumentAttributesIter(self)
|
| 283 |
+
itr = _AttributeSetIterator(it)
|
| 284 |
+
return itr
|
| 285 |
+
|
| 286 |
+
@property
|
| 287 |
+
def blocks(self):
|
| 288 |
+
"""
|
| 289 |
+
Return an iterator over this function's blocks.
|
| 290 |
+
The iterator will yield a ValueRef for each block.
|
| 291 |
+
"""
|
| 292 |
+
if not self.is_function:
|
| 293 |
+
raise ValueError('expected function value, got %s' % (self._kind,))
|
| 294 |
+
it = ffi.lib.LLVMPY_FunctionBlocksIter(self)
|
| 295 |
+
parents = self._parents.copy()
|
| 296 |
+
parents.update(function=self)
|
| 297 |
+
return _BlocksIterator(it, parents)
|
| 298 |
+
|
| 299 |
+
@property
|
| 300 |
+
def arguments(self):
|
| 301 |
+
"""
|
| 302 |
+
Return an iterator over this function's arguments.
|
| 303 |
+
The iterator will yield a ValueRef for each argument.
|
| 304 |
+
"""
|
| 305 |
+
if not self.is_function:
|
| 306 |
+
raise ValueError('expected function value, got %s' % (self._kind,))
|
| 307 |
+
it = ffi.lib.LLVMPY_FunctionArgumentsIter(self)
|
| 308 |
+
parents = self._parents.copy()
|
| 309 |
+
parents.update(function=self)
|
| 310 |
+
return _ArgumentsIterator(it, parents)
|
| 311 |
+
|
| 312 |
+
@property
|
| 313 |
+
def instructions(self):
|
| 314 |
+
"""
|
| 315 |
+
Return an iterator over this block's instructions.
|
| 316 |
+
The iterator will yield a ValueRef for each instruction.
|
| 317 |
+
"""
|
| 318 |
+
if not self.is_block:
|
| 319 |
+
raise ValueError('expected block value, got %s' % (self._kind,))
|
| 320 |
+
it = ffi.lib.LLVMPY_BlockInstructionsIter(self)
|
| 321 |
+
parents = self._parents.copy()
|
| 322 |
+
parents.update(block=self)
|
| 323 |
+
return _InstructionsIterator(it, parents)
|
| 324 |
+
|
| 325 |
+
@property
|
| 326 |
+
def operands(self):
|
| 327 |
+
"""
|
| 328 |
+
Return an iterator over this instruction's operands.
|
| 329 |
+
The iterator will yield a ValueRef for each operand.
|
| 330 |
+
"""
|
| 331 |
+
if not self.is_instruction:
|
| 332 |
+
raise ValueError('expected instruction value, got %s'
|
| 333 |
+
% (self._kind,))
|
| 334 |
+
it = ffi.lib.LLVMPY_InstructionOperandsIter(self)
|
| 335 |
+
parents = self._parents.copy()
|
| 336 |
+
parents.update(instruction=self)
|
| 337 |
+
return _OperandsIterator(it, parents)
|
| 338 |
+
|
| 339 |
+
@property
|
| 340 |
+
def opcode(self):
|
| 341 |
+
if not self.is_instruction:
|
| 342 |
+
raise ValueError('expected instruction value, got %s'
|
| 343 |
+
% (self._kind,))
|
| 344 |
+
return ffi.ret_string(ffi.lib.LLVMPY_GetOpcodeName(self))
|
| 345 |
+
|
| 346 |
+
def get_constant_value(self, signed_int=False, round_fp=False):
|
| 347 |
+
"""
|
| 348 |
+
Return the constant value, either as a literal (when supported)
|
| 349 |
+
or as a string.
|
| 350 |
+
|
| 351 |
+
Parameters
|
| 352 |
+
-----------
|
| 353 |
+
signed_int : bool
|
| 354 |
+
if True and the constant is an integer, returns a signed version
|
| 355 |
+
round_fp : bool
|
| 356 |
+
if True and the constant is a floating point value, rounds the
|
| 357 |
+
result upon accuracy loss (e.g., when querying an fp128 value).
|
| 358 |
+
By default, raises an exception on accuracy loss
|
| 359 |
+
"""
|
| 360 |
+
if not self.is_constant:
|
| 361 |
+
raise ValueError('expected constant value, got %s'
|
| 362 |
+
% (self._kind,))
|
| 363 |
+
|
| 364 |
+
if self.value_kind == ValueKind.constant_int:
|
| 365 |
+
# Python integers are also arbitrary-precision
|
| 366 |
+
little_endian = c_bool(False)
|
| 367 |
+
words = ffi.lib.LLVMPY_GetConstantIntNumWords(self)
|
| 368 |
+
ptr = ffi.lib.LLVMPY_GetConstantIntRawValue(
|
| 369 |
+
self, byref(little_endian))
|
| 370 |
+
asbytes = bytes(cast(ptr, POINTER(c_uint64 * words)).contents)
|
| 371 |
+
return int.from_bytes(
|
| 372 |
+
asbytes,
|
| 373 |
+
('little' if little_endian.value else 'big'),
|
| 374 |
+
signed=signed_int,
|
| 375 |
+
)
|
| 376 |
+
elif self.value_kind == ValueKind.constant_fp:
|
| 377 |
+
# Convert floating-point values to double-precision (Python float)
|
| 378 |
+
accuracy_loss = c_bool(False)
|
| 379 |
+
value = ffi.lib.LLVMPY_GetConstantFPValue(self,
|
| 380 |
+
byref(accuracy_loss))
|
| 381 |
+
if accuracy_loss.value and not round_fp:
|
| 382 |
+
raise ValueError(
|
| 383 |
+
'Accuracy loss encountered in conversion of constant '
|
| 384 |
+
f'value {str(self)}')
|
| 385 |
+
|
| 386 |
+
return value
|
| 387 |
+
|
| 388 |
+
# Otherwise, return the IR string
|
| 389 |
+
return str(self)
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
class _ValueIterator(ffi.ObjectRef):
|
| 393 |
+
|
| 394 |
+
kind = None # derived classes must specify the Value kind value
|
| 395 |
+
# as class attribute
|
| 396 |
+
|
| 397 |
+
def __init__(self, ptr, parents):
|
| 398 |
+
ffi.ObjectRef.__init__(self, ptr)
|
| 399 |
+
# Keep parent objects (module, function, etc) alive
|
| 400 |
+
self._parents = parents
|
| 401 |
+
if self.kind is None:
|
| 402 |
+
raise NotImplementedError('%s must specify kind attribute'
|
| 403 |
+
% (type(self).__name__,))
|
| 404 |
+
|
| 405 |
+
def __next__(self):
|
| 406 |
+
vp = self._next()
|
| 407 |
+
if vp:
|
| 408 |
+
return ValueRef(vp, self.kind, self._parents)
|
| 409 |
+
else:
|
| 410 |
+
raise StopIteration
|
| 411 |
+
|
| 412 |
+
next = __next__
|
| 413 |
+
|
| 414 |
+
def __iter__(self):
|
| 415 |
+
return self
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
class _AttributeIterator(ffi.ObjectRef):
|
| 419 |
+
|
| 420 |
+
def __next__(self):
|
| 421 |
+
vp = self._next()
|
| 422 |
+
if vp:
|
| 423 |
+
return vp
|
| 424 |
+
else:
|
| 425 |
+
raise StopIteration
|
| 426 |
+
|
| 427 |
+
next = __next__
|
| 428 |
+
|
| 429 |
+
def __iter__(self):
|
| 430 |
+
return self
|
| 431 |
+
|
| 432 |
+
|
| 433 |
+
class _AttributeListIterator(_AttributeIterator):
|
| 434 |
+
|
| 435 |
+
def _dispose(self):
|
| 436 |
+
self._capi.LLVMPY_DisposeAttributeListIter(self)
|
| 437 |
+
|
| 438 |
+
def _next(self):
|
| 439 |
+
return ffi.ret_bytes(ffi.lib.LLVMPY_AttributeListIterNext(self))
|
| 440 |
+
|
| 441 |
+
|
| 442 |
+
class _AttributeSetIterator(_AttributeIterator):
|
| 443 |
+
|
| 444 |
+
def _dispose(self):
|
| 445 |
+
self._capi.LLVMPY_DisposeAttributeSetIter(self)
|
| 446 |
+
|
| 447 |
+
def _next(self):
|
| 448 |
+
return ffi.ret_bytes(ffi.lib.LLVMPY_AttributeSetIterNext(self))
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
class _BlocksIterator(_ValueIterator):
|
| 452 |
+
|
| 453 |
+
kind = 'block'
|
| 454 |
+
|
| 455 |
+
def _dispose(self):
|
| 456 |
+
self._capi.LLVMPY_DisposeBlocksIter(self)
|
| 457 |
+
|
| 458 |
+
def _next(self):
|
| 459 |
+
return ffi.lib.LLVMPY_BlocksIterNext(self)
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
class _ArgumentsIterator(_ValueIterator):
|
| 463 |
+
|
| 464 |
+
kind = 'argument'
|
| 465 |
+
|
| 466 |
+
def _dispose(self):
|
| 467 |
+
self._capi.LLVMPY_DisposeArgumentsIter(self)
|
| 468 |
+
|
| 469 |
+
def _next(self):
|
| 470 |
+
return ffi.lib.LLVMPY_ArgumentsIterNext(self)
|
| 471 |
+
|
| 472 |
+
|
| 473 |
+
class _InstructionsIterator(_ValueIterator):
|
| 474 |
+
|
| 475 |
+
kind = 'instruction'
|
| 476 |
+
|
| 477 |
+
def _dispose(self):
|
| 478 |
+
self._capi.LLVMPY_DisposeInstructionsIter(self)
|
| 479 |
+
|
| 480 |
+
def _next(self):
|
| 481 |
+
return ffi.lib.LLVMPY_InstructionsIterNext(self)
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
class _OperandsIterator(_ValueIterator):
|
| 485 |
+
|
| 486 |
+
kind = 'operand'
|
| 487 |
+
|
| 488 |
+
def _dispose(self):
|
| 489 |
+
self._capi.LLVMPY_DisposeOperandsIter(self)
|
| 490 |
+
|
| 491 |
+
def _next(self):
|
| 492 |
+
return ffi.lib.LLVMPY_OperandsIterNext(self)
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
# FFI
|
| 496 |
+
|
| 497 |
+
ffi.lib.LLVMPY_PrintValueToString.argtypes = [
|
| 498 |
+
ffi.LLVMValueRef,
|
| 499 |
+
POINTER(c_char_p)
|
| 500 |
+
]
|
| 501 |
+
|
| 502 |
+
ffi.lib.LLVMPY_GetGlobalParent.argtypes = [ffi.LLVMValueRef]
|
| 503 |
+
ffi.lib.LLVMPY_GetGlobalParent.restype = ffi.LLVMModuleRef
|
| 504 |
+
|
| 505 |
+
ffi.lib.LLVMPY_GetValueName.argtypes = [ffi.LLVMValueRef]
|
| 506 |
+
ffi.lib.LLVMPY_GetValueName.restype = c_char_p
|
| 507 |
+
|
| 508 |
+
ffi.lib.LLVMPY_SetValueName.argtypes = [ffi.LLVMValueRef, c_char_p]
|
| 509 |
+
|
| 510 |
+
ffi.lib.LLVMPY_TypeOf.argtypes = [ffi.LLVMValueRef]
|
| 511 |
+
ffi.lib.LLVMPY_TypeOf.restype = ffi.LLVMTypeRef
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
ffi.lib.LLVMPY_PrintType.argtypes = [ffi.LLVMTypeRef]
|
| 515 |
+
ffi.lib.LLVMPY_PrintType.restype = c_void_p
|
| 516 |
+
|
| 517 |
+
ffi.lib.LLVMPY_TypeIsPointer.argtypes = [ffi.LLVMTypeRef]
|
| 518 |
+
ffi.lib.LLVMPY_TypeIsPointer.restype = c_bool
|
| 519 |
+
|
| 520 |
+
ffi.lib.LLVMPY_GetElementType.argtypes = [ffi.LLVMTypeRef]
|
| 521 |
+
ffi.lib.LLVMPY_GetElementType.restype = ffi.LLVMTypeRef
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
ffi.lib.LLVMPY_GetTypeName.argtypes = [ffi.LLVMTypeRef]
|
| 525 |
+
ffi.lib.LLVMPY_GetTypeName.restype = c_void_p
|
| 526 |
+
|
| 527 |
+
ffi.lib.LLVMPY_GetLinkage.argtypes = [ffi.LLVMValueRef]
|
| 528 |
+
ffi.lib.LLVMPY_GetLinkage.restype = c_int
|
| 529 |
+
|
| 530 |
+
ffi.lib.LLVMPY_SetLinkage.argtypes = [ffi.LLVMValueRef, c_int]
|
| 531 |
+
|
| 532 |
+
ffi.lib.LLVMPY_GetVisibility.argtypes = [ffi.LLVMValueRef]
|
| 533 |
+
ffi.lib.LLVMPY_GetVisibility.restype = c_int
|
| 534 |
+
|
| 535 |
+
ffi.lib.LLVMPY_SetVisibility.argtypes = [ffi.LLVMValueRef, c_int]
|
| 536 |
+
|
| 537 |
+
ffi.lib.LLVMPY_GetDLLStorageClass.argtypes = [ffi.LLVMValueRef]
|
| 538 |
+
ffi.lib.LLVMPY_GetDLLStorageClass.restype = c_int
|
| 539 |
+
|
| 540 |
+
ffi.lib.LLVMPY_SetDLLStorageClass.argtypes = [ffi.LLVMValueRef, c_int]
|
| 541 |
+
|
| 542 |
+
ffi.lib.LLVMPY_GetEnumAttributeKindForName.argtypes = [c_char_p, c_size_t]
|
| 543 |
+
ffi.lib.LLVMPY_GetEnumAttributeKindForName.restype = c_uint
|
| 544 |
+
|
| 545 |
+
ffi.lib.LLVMPY_AddFunctionAttr.argtypes = [ffi.LLVMValueRef, c_uint]
|
| 546 |
+
|
| 547 |
+
ffi.lib.LLVMPY_IsDeclaration.argtypes = [ffi.LLVMValueRef]
|
| 548 |
+
ffi.lib.LLVMPY_IsDeclaration.restype = c_int
|
| 549 |
+
|
| 550 |
+
ffi.lib.LLVMPY_FunctionAttributesIter.argtypes = [ffi.LLVMValueRef]
|
| 551 |
+
ffi.lib.LLVMPY_FunctionAttributesIter.restype = ffi.LLVMAttributeListIterator
|
| 552 |
+
|
| 553 |
+
ffi.lib.LLVMPY_CallInstAttributesIter.argtypes = [ffi.LLVMValueRef]
|
| 554 |
+
ffi.lib.LLVMPY_CallInstAttributesIter.restype = ffi.LLVMAttributeListIterator
|
| 555 |
+
|
| 556 |
+
ffi.lib.LLVMPY_InvokeInstAttributesIter.argtypes = [ffi.LLVMValueRef]
|
| 557 |
+
ffi.lib.LLVMPY_InvokeInstAttributesIter.restype = ffi.LLVMAttributeListIterator
|
| 558 |
+
|
| 559 |
+
ffi.lib.LLVMPY_GlobalAttributesIter.argtypes = [ffi.LLVMValueRef]
|
| 560 |
+
ffi.lib.LLVMPY_GlobalAttributesIter.restype = ffi.LLVMAttributeSetIterator
|
| 561 |
+
|
| 562 |
+
ffi.lib.LLVMPY_ArgumentAttributesIter.argtypes = [ffi.LLVMValueRef]
|
| 563 |
+
ffi.lib.LLVMPY_ArgumentAttributesIter.restype = ffi.LLVMAttributeSetIterator
|
| 564 |
+
|
| 565 |
+
ffi.lib.LLVMPY_FunctionBlocksIter.argtypes = [ffi.LLVMValueRef]
|
| 566 |
+
ffi.lib.LLVMPY_FunctionBlocksIter.restype = ffi.LLVMBlocksIterator
|
| 567 |
+
|
| 568 |
+
ffi.lib.LLVMPY_FunctionArgumentsIter.argtypes = [ffi.LLVMValueRef]
|
| 569 |
+
ffi.lib.LLVMPY_FunctionArgumentsIter.restype = ffi.LLVMArgumentsIterator
|
| 570 |
+
|
| 571 |
+
ffi.lib.LLVMPY_BlockInstructionsIter.argtypes = [ffi.LLVMValueRef]
|
| 572 |
+
ffi.lib.LLVMPY_BlockInstructionsIter.restype = ffi.LLVMInstructionsIterator
|
| 573 |
+
|
| 574 |
+
ffi.lib.LLVMPY_InstructionOperandsIter.argtypes = [ffi.LLVMValueRef]
|
| 575 |
+
ffi.lib.LLVMPY_InstructionOperandsIter.restype = ffi.LLVMOperandsIterator
|
| 576 |
+
|
| 577 |
+
ffi.lib.LLVMPY_DisposeAttributeListIter.argtypes = [
|
| 578 |
+
ffi.LLVMAttributeListIterator]
|
| 579 |
+
|
| 580 |
+
ffi.lib.LLVMPY_DisposeAttributeSetIter.argtypes = [ffi.LLVMAttributeSetIterator]
|
| 581 |
+
|
| 582 |
+
ffi.lib.LLVMPY_DisposeBlocksIter.argtypes = [ffi.LLVMBlocksIterator]
|
| 583 |
+
|
| 584 |
+
ffi.lib.LLVMPY_DisposeInstructionsIter.argtypes = [ffi.LLVMInstructionsIterator]
|
| 585 |
+
|
| 586 |
+
ffi.lib.LLVMPY_DisposeOperandsIter.argtypes = [ffi.LLVMOperandsIterator]
|
| 587 |
+
|
| 588 |
+
ffi.lib.LLVMPY_AttributeListIterNext.argtypes = [ffi.LLVMAttributeListIterator]
|
| 589 |
+
ffi.lib.LLVMPY_AttributeListIterNext.restype = c_void_p
|
| 590 |
+
|
| 591 |
+
ffi.lib.LLVMPY_AttributeSetIterNext.argtypes = [ffi.LLVMAttributeSetIterator]
|
| 592 |
+
ffi.lib.LLVMPY_AttributeSetIterNext.restype = c_void_p
|
| 593 |
+
|
| 594 |
+
ffi.lib.LLVMPY_BlocksIterNext.argtypes = [ffi.LLVMBlocksIterator]
|
| 595 |
+
ffi.lib.LLVMPY_BlocksIterNext.restype = ffi.LLVMValueRef
|
| 596 |
+
|
| 597 |
+
ffi.lib.LLVMPY_ArgumentsIterNext.argtypes = [ffi.LLVMArgumentsIterator]
|
| 598 |
+
ffi.lib.LLVMPY_ArgumentsIterNext.restype = ffi.LLVMValueRef
|
| 599 |
+
|
| 600 |
+
ffi.lib.LLVMPY_InstructionsIterNext.argtypes = [ffi.LLVMInstructionsIterator]
|
| 601 |
+
ffi.lib.LLVMPY_InstructionsIterNext.restype = ffi.LLVMValueRef
|
| 602 |
+
|
| 603 |
+
ffi.lib.LLVMPY_OperandsIterNext.argtypes = [ffi.LLVMOperandsIterator]
|
| 604 |
+
ffi.lib.LLVMPY_OperandsIterNext.restype = ffi.LLVMValueRef
|
| 605 |
+
|
| 606 |
+
ffi.lib.LLVMPY_GetOpcodeName.argtypes = [ffi.LLVMValueRef]
|
| 607 |
+
ffi.lib.LLVMPY_GetOpcodeName.restype = c_void_p
|
| 608 |
+
|
| 609 |
+
ffi.lib.LLVMPY_IsConstant.argtypes = [ffi.LLVMValueRef]
|
| 610 |
+
ffi.lib.LLVMPY_IsConstant.restype = c_bool
|
| 611 |
+
|
| 612 |
+
ffi.lib.LLVMPY_GetValueKind.argtypes = [ffi.LLVMValueRef]
|
| 613 |
+
ffi.lib.LLVMPY_GetValueKind.restype = c_int
|
| 614 |
+
|
| 615 |
+
ffi.lib.LLVMPY_GetConstantIntRawValue.argtypes = [ffi.LLVMValueRef,
|
| 616 |
+
POINTER(c_bool)]
|
| 617 |
+
ffi.lib.LLVMPY_GetConstantIntRawValue.restype = POINTER(c_uint64)
|
| 618 |
+
|
| 619 |
+
ffi.lib.LLVMPY_GetConstantIntNumWords.argtypes = [ffi.LLVMValueRef]
|
| 620 |
+
ffi.lib.LLVMPY_GetConstantIntNumWords.restype = c_uint
|
| 621 |
+
|
| 622 |
+
ffi.lib.LLVMPY_GetConstantFPValue.argtypes = [ffi.LLVMValueRef,
|
| 623 |
+
POINTER(c_bool)]
|
| 624 |
+
ffi.lib.LLVMPY_GetConstantFPValue.restype = c_double
|
lib/python3.11/site-packages/llvmlite/ir/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This subpackage implements the LLVM IR classes in pure python
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from .types import *
|
| 6 |
+
from .values import *
|
| 7 |
+
from .module import *
|
| 8 |
+
from .builder import *
|
| 9 |
+
from .instructions import *
|
| 10 |
+
from .transforms import *
|
| 11 |
+
from .context import Context, global_context
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (583 Bytes). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/_utils.cpython-311.pyc
ADDED
|
Binary file (5.17 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/builder.cpython-311.pyc
ADDED
|
Binary file (53.2 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/context.cpython-311.pyc
ADDED
|
Binary file (1.32 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/instructions.cpython-311.pyc
ADDED
|
Binary file (62.2 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/module.cpython-311.pyc
ADDED
|
Binary file (14.5 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/transforms.cpython-311.pyc
ADDED
|
Binary file (4.24 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/types.cpython-311.pyc
ADDED
|
Binary file (34.1 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/__pycache__/values.cpython-311.pyc
ADDED
|
Binary file (65.2 kB). View file
|
|
|
lib/python3.11/site-packages/llvmlite/ir/_utils.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from collections import defaultdict
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class DuplicatedNameError(NameError):
|
| 5 |
+
pass
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class NameScope(object):
|
| 9 |
+
def __init__(self):
|
| 10 |
+
self._useset = set([''])
|
| 11 |
+
self._basenamemap = defaultdict(int)
|
| 12 |
+
|
| 13 |
+
def is_used(self, name):
|
| 14 |
+
return name in self._useset
|
| 15 |
+
|
| 16 |
+
def register(self, name, deduplicate=False):
|
| 17 |
+
if deduplicate:
|
| 18 |
+
name = self.deduplicate(name)
|
| 19 |
+
elif self.is_used(name):
|
| 20 |
+
raise DuplicatedNameError(name)
|
| 21 |
+
self._useset.add(name)
|
| 22 |
+
return name
|
| 23 |
+
|
| 24 |
+
def deduplicate(self, name):
|
| 25 |
+
basename = name
|
| 26 |
+
while self.is_used(name):
|
| 27 |
+
ident = self._basenamemap[basename] + 1
|
| 28 |
+
self._basenamemap[basename] = ident
|
| 29 |
+
name = "{0}.{1}".format(basename, ident)
|
| 30 |
+
return name
|
| 31 |
+
|
| 32 |
+
def get_child(self):
|
| 33 |
+
return type(self)(parent=self)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class _StrCaching(object):
|
| 37 |
+
|
| 38 |
+
def _clear_string_cache(self):
|
| 39 |
+
try:
|
| 40 |
+
del self.__cached_str
|
| 41 |
+
except AttributeError:
|
| 42 |
+
pass
|
| 43 |
+
|
| 44 |
+
def __str__(self):
|
| 45 |
+
try:
|
| 46 |
+
return self.__cached_str
|
| 47 |
+
except AttributeError:
|
| 48 |
+
s = self.__cached_str = self._to_string()
|
| 49 |
+
return s
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
class _StringReferenceCaching(object):
|
| 53 |
+
|
| 54 |
+
def get_reference(self):
|
| 55 |
+
try:
|
| 56 |
+
return self.__cached_refstr
|
| 57 |
+
except AttributeError:
|
| 58 |
+
s = self.__cached_refstr = self._get_reference()
|
| 59 |
+
return s
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class _HasMetadata(object):
|
| 63 |
+
|
| 64 |
+
def set_metadata(self, name, node):
|
| 65 |
+
"""
|
| 66 |
+
Attach unnamed metadata *node* to the metadata slot *name* of this
|
| 67 |
+
value.
|
| 68 |
+
"""
|
| 69 |
+
self.metadata[name] = node
|
| 70 |
+
|
| 71 |
+
def _stringify_metadata(self, leading_comma=False):
|
| 72 |
+
if self.metadata:
|
| 73 |
+
buf = []
|
| 74 |
+
if leading_comma:
|
| 75 |
+
buf.append("")
|
| 76 |
+
buf += ["!{0} {1}".format(k, v.get_reference())
|
| 77 |
+
for k, v in self.metadata.items()]
|
| 78 |
+
return ', '.join(buf)
|
| 79 |
+
else:
|
| 80 |
+
return ''
|
lib/python3.11/site-packages/llvmlite/ir/builder.py
ADDED
|
@@ -0,0 +1,1119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import contextlib
|
| 2 |
+
import functools
|
| 3 |
+
|
| 4 |
+
from llvmlite.ir import instructions, types, values
|
| 5 |
+
|
| 6 |
+
_CMP_MAP = {
|
| 7 |
+
'>': 'gt',
|
| 8 |
+
'<': 'lt',
|
| 9 |
+
'==': 'eq',
|
| 10 |
+
'!=': 'ne',
|
| 11 |
+
'>=': 'ge',
|
| 12 |
+
'<=': 'le',
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def _unop(opname, cls=instructions.Instruction):
|
| 17 |
+
def wrap(fn):
|
| 18 |
+
@functools.wraps(fn)
|
| 19 |
+
def wrapped(self, arg, name='', flags=()):
|
| 20 |
+
instr = cls(self.block, arg.type, opname, [arg], name, flags)
|
| 21 |
+
self._insert(instr)
|
| 22 |
+
return instr
|
| 23 |
+
|
| 24 |
+
return wrapped
|
| 25 |
+
|
| 26 |
+
return wrap
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def _binop(opname, cls=instructions.Instruction):
|
| 30 |
+
def wrap(fn):
|
| 31 |
+
@functools.wraps(fn)
|
| 32 |
+
def wrapped(self, lhs, rhs, name='', flags=()):
|
| 33 |
+
if lhs.type != rhs.type:
|
| 34 |
+
raise ValueError("Operands must be the same type, got (%s, %s)"
|
| 35 |
+
% (lhs.type, rhs.type))
|
| 36 |
+
instr = cls(self.block, lhs.type, opname, (lhs, rhs), name, flags)
|
| 37 |
+
self._insert(instr)
|
| 38 |
+
return instr
|
| 39 |
+
|
| 40 |
+
return wrapped
|
| 41 |
+
|
| 42 |
+
return wrap
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _binop_with_overflow(opname, cls=instructions.Instruction):
|
| 46 |
+
def wrap(fn):
|
| 47 |
+
@functools.wraps(fn)
|
| 48 |
+
def wrapped(self, lhs, rhs, name=''):
|
| 49 |
+
if lhs.type != rhs.type:
|
| 50 |
+
raise ValueError("Operands must be the same type, got (%s, %s)"
|
| 51 |
+
% (lhs.type, rhs.type))
|
| 52 |
+
ty = lhs.type
|
| 53 |
+
if not isinstance(ty, types.IntType):
|
| 54 |
+
raise TypeError("expected an integer type, got %s" % (ty,))
|
| 55 |
+
bool_ty = types.IntType(1)
|
| 56 |
+
|
| 57 |
+
mod = self.module
|
| 58 |
+
fnty = types.FunctionType(types.LiteralStructType([ty, bool_ty]),
|
| 59 |
+
[ty, ty])
|
| 60 |
+
fn = mod.declare_intrinsic("llvm.%s.with.overflow" % (opname,),
|
| 61 |
+
[ty], fnty)
|
| 62 |
+
ret = self.call(fn, [lhs, rhs], name=name)
|
| 63 |
+
return ret
|
| 64 |
+
|
| 65 |
+
return wrapped
|
| 66 |
+
|
| 67 |
+
return wrap
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def _uniop(opname, cls=instructions.Instruction):
|
| 71 |
+
def wrap(fn):
|
| 72 |
+
@functools.wraps(fn)
|
| 73 |
+
def wrapped(self, operand, name=''):
|
| 74 |
+
instr = cls(self.block, operand.type, opname, [operand], name)
|
| 75 |
+
self._insert(instr)
|
| 76 |
+
return instr
|
| 77 |
+
|
| 78 |
+
return wrapped
|
| 79 |
+
|
| 80 |
+
return wrap
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def _uniop_intrinsic_int(opname):
|
| 84 |
+
def wrap(fn):
|
| 85 |
+
@functools.wraps(fn)
|
| 86 |
+
def wrapped(self, operand, name=''):
|
| 87 |
+
if not isinstance(operand.type, types.IntType):
|
| 88 |
+
raise TypeError(
|
| 89 |
+
"expected an integer type, got %s" %
|
| 90 |
+
operand.type)
|
| 91 |
+
fn = self.module.declare_intrinsic(opname, [operand.type])
|
| 92 |
+
return self.call(fn, [operand], name)
|
| 93 |
+
|
| 94 |
+
return wrapped
|
| 95 |
+
|
| 96 |
+
return wrap
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def _uniop_intrinsic_float(opname):
|
| 100 |
+
def wrap(fn):
|
| 101 |
+
@functools.wraps(fn)
|
| 102 |
+
def wrapped(self, operand, name=''):
|
| 103 |
+
if not isinstance(
|
| 104 |
+
operand.type, (types.FloatType, types.DoubleType)):
|
| 105 |
+
raise TypeError("expected a float type, got %s" % operand.type)
|
| 106 |
+
fn = self.module.declare_intrinsic(opname, [operand.type])
|
| 107 |
+
return self.call(fn, [operand], name)
|
| 108 |
+
|
| 109 |
+
return wrapped
|
| 110 |
+
|
| 111 |
+
return wrap
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
def _uniop_intrinsic_with_flag(opname):
|
| 115 |
+
def wrap(fn):
|
| 116 |
+
@functools.wraps(fn)
|
| 117 |
+
def wrapped(self, operand, flag, name=''):
|
| 118 |
+
if not isinstance(operand.type, types.IntType):
|
| 119 |
+
raise TypeError(
|
| 120 |
+
"expected an integer type, got %s" %
|
| 121 |
+
operand.type)
|
| 122 |
+
if not (isinstance(flag.type, types.IntType) and
|
| 123 |
+
flag.type.width == 1):
|
| 124 |
+
raise TypeError("expected an i1 type, got %s" % flag.type)
|
| 125 |
+
fn = self.module.declare_intrinsic(
|
| 126 |
+
opname, [operand.type, flag.type])
|
| 127 |
+
return self.call(fn, [operand, flag], name)
|
| 128 |
+
|
| 129 |
+
return wrapped
|
| 130 |
+
|
| 131 |
+
return wrap
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _triop_intrinsic(opname):
|
| 135 |
+
def wrap(fn):
|
| 136 |
+
@functools.wraps(fn)
|
| 137 |
+
def wrapped(self, a, b, c, name=''):
|
| 138 |
+
if a.type != b.type or b.type != c.type:
|
| 139 |
+
raise TypeError(
|
| 140 |
+
"expected types to be the same, got %s, %s, %s" % (
|
| 141 |
+
a.type,
|
| 142 |
+
b.type,
|
| 143 |
+
c.type))
|
| 144 |
+
elif not isinstance(
|
| 145 |
+
a.type,
|
| 146 |
+
(types.HalfType, types.FloatType, types.DoubleType)):
|
| 147 |
+
raise TypeError(
|
| 148 |
+
"expected an floating point type, got %s" %
|
| 149 |
+
a.type)
|
| 150 |
+
fn = self.module.declare_intrinsic(opname, [a.type, b.type, c.type])
|
| 151 |
+
return self.call(fn, [a, b, c], name)
|
| 152 |
+
|
| 153 |
+
return wrapped
|
| 154 |
+
|
| 155 |
+
return wrap
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def _castop(opname, cls=instructions.CastInstr):
|
| 159 |
+
def wrap(fn):
|
| 160 |
+
@functools.wraps(fn)
|
| 161 |
+
def wrapped(self, val, typ, name=''):
|
| 162 |
+
if val.type == typ:
|
| 163 |
+
return val
|
| 164 |
+
instr = cls(self.block, opname, val, typ, name)
|
| 165 |
+
self._insert(instr)
|
| 166 |
+
return instr
|
| 167 |
+
|
| 168 |
+
return wrapped
|
| 169 |
+
|
| 170 |
+
return wrap
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def _label_suffix(label, suffix):
|
| 174 |
+
"""Returns (label + suffix) or a truncated version if it's too long.
|
| 175 |
+
Parameters
|
| 176 |
+
----------
|
| 177 |
+
label : str
|
| 178 |
+
Label name
|
| 179 |
+
suffix : str
|
| 180 |
+
Label suffix
|
| 181 |
+
"""
|
| 182 |
+
if len(label) > 50:
|
| 183 |
+
nhead = 25
|
| 184 |
+
return ''.join([label[:nhead], '..', suffix])
|
| 185 |
+
else:
|
| 186 |
+
return label + suffix
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
class IRBuilder(object):
|
| 190 |
+
def __init__(self, block=None):
|
| 191 |
+
self._block = block
|
| 192 |
+
self._anchor = len(block.instructions) if block else 0
|
| 193 |
+
self.debug_metadata = None
|
| 194 |
+
|
| 195 |
+
@property
|
| 196 |
+
def block(self):
|
| 197 |
+
"""
|
| 198 |
+
The current basic block.
|
| 199 |
+
"""
|
| 200 |
+
return self._block
|
| 201 |
+
|
| 202 |
+
basic_block = block
|
| 203 |
+
|
| 204 |
+
@property
|
| 205 |
+
def function(self):
|
| 206 |
+
"""
|
| 207 |
+
The current function.
|
| 208 |
+
"""
|
| 209 |
+
return self.block.parent
|
| 210 |
+
|
| 211 |
+
@property
|
| 212 |
+
def module(self):
|
| 213 |
+
"""
|
| 214 |
+
The current module.
|
| 215 |
+
"""
|
| 216 |
+
return self.block.parent.module
|
| 217 |
+
|
| 218 |
+
def position_before(self, instr):
|
| 219 |
+
"""
|
| 220 |
+
Position immediately before the given instruction. The current block
|
| 221 |
+
is also changed to the instruction's basic block.
|
| 222 |
+
"""
|
| 223 |
+
self._block = instr.parent
|
| 224 |
+
self._anchor = self._block.instructions.index(instr)
|
| 225 |
+
|
| 226 |
+
def position_after(self, instr):
|
| 227 |
+
"""
|
| 228 |
+
Position immediately after the given instruction. The current block
|
| 229 |
+
is also changed to the instruction's basic block.
|
| 230 |
+
"""
|
| 231 |
+
self._block = instr.parent
|
| 232 |
+
self._anchor = self._block.instructions.index(instr) + 1
|
| 233 |
+
|
| 234 |
+
def position_at_start(self, block):
|
| 235 |
+
"""
|
| 236 |
+
Position at the start of the basic *block*.
|
| 237 |
+
"""
|
| 238 |
+
self._block = block
|
| 239 |
+
self._anchor = 0
|
| 240 |
+
|
| 241 |
+
def position_at_end(self, block):
|
| 242 |
+
"""
|
| 243 |
+
Position at the end of the basic *block*.
|
| 244 |
+
"""
|
| 245 |
+
self._block = block
|
| 246 |
+
self._anchor = len(block.instructions)
|
| 247 |
+
|
| 248 |
+
def append_basic_block(self, name=''):
|
| 249 |
+
"""
|
| 250 |
+
Append a basic block, with the given optional *name*, to the current
|
| 251 |
+
function. The current block is not changed. The new block is returned.
|
| 252 |
+
"""
|
| 253 |
+
return self.function.append_basic_block(name)
|
| 254 |
+
|
| 255 |
+
def remove(self, instr):
|
| 256 |
+
"""Remove the given instruction."""
|
| 257 |
+
idx = self._block.instructions.index(instr)
|
| 258 |
+
del self._block.instructions[idx]
|
| 259 |
+
if self._block.terminator == instr:
|
| 260 |
+
self._block.terminator = None
|
| 261 |
+
if self._anchor > idx:
|
| 262 |
+
self._anchor -= 1
|
| 263 |
+
|
| 264 |
+
@contextlib.contextmanager
|
| 265 |
+
def goto_block(self, block):
|
| 266 |
+
"""
|
| 267 |
+
A context manager which temporarily positions the builder at the end
|
| 268 |
+
of basic block *bb* (but before any terminator).
|
| 269 |
+
"""
|
| 270 |
+
old_block = self.basic_block
|
| 271 |
+
term = block.terminator
|
| 272 |
+
if term is not None:
|
| 273 |
+
self.position_before(term)
|
| 274 |
+
else:
|
| 275 |
+
self.position_at_end(block)
|
| 276 |
+
try:
|
| 277 |
+
yield
|
| 278 |
+
finally:
|
| 279 |
+
self.position_at_end(old_block)
|
| 280 |
+
|
| 281 |
+
@contextlib.contextmanager
|
| 282 |
+
def goto_entry_block(self):
|
| 283 |
+
"""
|
| 284 |
+
A context manager which temporarily positions the builder at the
|
| 285 |
+
end of the function's entry block.
|
| 286 |
+
"""
|
| 287 |
+
with self.goto_block(self.function.entry_basic_block):
|
| 288 |
+
yield
|
| 289 |
+
|
| 290 |
+
@contextlib.contextmanager
|
| 291 |
+
def _branch_helper(self, bbenter, bbexit):
|
| 292 |
+
self.position_at_end(bbenter)
|
| 293 |
+
yield bbexit
|
| 294 |
+
if self.basic_block.terminator is None:
|
| 295 |
+
self.branch(bbexit)
|
| 296 |
+
|
| 297 |
+
@contextlib.contextmanager
|
| 298 |
+
def if_then(self, pred, likely=None):
|
| 299 |
+
"""
|
| 300 |
+
A context manager which sets up a conditional basic block based
|
| 301 |
+
on the given predicate (a i1 value). If the conditional block
|
| 302 |
+
is not explicitly terminated, a branch will be added to the next
|
| 303 |
+
block.
|
| 304 |
+
If *likely* is given, its boolean value indicates whether the
|
| 305 |
+
predicate is likely to be true or not, and metadata is issued
|
| 306 |
+
for LLVM's optimizers to account for that.
|
| 307 |
+
"""
|
| 308 |
+
bb = self.basic_block
|
| 309 |
+
bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
|
| 310 |
+
bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
|
| 311 |
+
br = self.cbranch(pred, bbif, bbend)
|
| 312 |
+
if likely is not None:
|
| 313 |
+
br.set_weights([99, 1] if likely else [1, 99])
|
| 314 |
+
|
| 315 |
+
with self._branch_helper(bbif, bbend):
|
| 316 |
+
yield bbend
|
| 317 |
+
|
| 318 |
+
self.position_at_end(bbend)
|
| 319 |
+
|
| 320 |
+
@contextlib.contextmanager
|
| 321 |
+
def if_else(self, pred, likely=None):
|
| 322 |
+
"""
|
| 323 |
+
A context manager which sets up two conditional basic blocks based
|
| 324 |
+
on the given predicate (a i1 value).
|
| 325 |
+
A tuple of context managers is yield'ed. Each context manager
|
| 326 |
+
acts as a if_then() block.
|
| 327 |
+
*likely* has the same meaning as in if_then().
|
| 328 |
+
|
| 329 |
+
Typical use::
|
| 330 |
+
with builder.if_else(pred) as (then, otherwise):
|
| 331 |
+
with then:
|
| 332 |
+
# emit instructions for when the predicate is true
|
| 333 |
+
with otherwise:
|
| 334 |
+
# emit instructions for when the predicate is false
|
| 335 |
+
"""
|
| 336 |
+
bb = self.basic_block
|
| 337 |
+
bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
|
| 338 |
+
bbelse = self.append_basic_block(name=_label_suffix(bb.name, '.else'))
|
| 339 |
+
bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
|
| 340 |
+
br = self.cbranch(pred, bbif, bbelse)
|
| 341 |
+
if likely is not None:
|
| 342 |
+
br.set_weights([99, 1] if likely else [1, 99])
|
| 343 |
+
|
| 344 |
+
then = self._branch_helper(bbif, bbend)
|
| 345 |
+
otherwise = self._branch_helper(bbelse, bbend)
|
| 346 |
+
|
| 347 |
+
yield then, otherwise
|
| 348 |
+
|
| 349 |
+
self.position_at_end(bbend)
|
| 350 |
+
|
| 351 |
+
def _insert(self, instr):
|
| 352 |
+
if self.debug_metadata is not None and 'dbg' not in instr.metadata:
|
| 353 |
+
instr.metadata['dbg'] = self.debug_metadata
|
| 354 |
+
self._block.instructions.insert(self._anchor, instr)
|
| 355 |
+
self._anchor += 1
|
| 356 |
+
|
| 357 |
+
def _set_terminator(self, term):
|
| 358 |
+
assert not self.block.is_terminated
|
| 359 |
+
self._insert(term)
|
| 360 |
+
self.block.terminator = term
|
| 361 |
+
return term
|
| 362 |
+
|
| 363 |
+
#
|
| 364 |
+
# Arithmetic APIs
|
| 365 |
+
#
|
| 366 |
+
|
| 367 |
+
@_binop('shl')
|
| 368 |
+
def shl(self, lhs, rhs, name=''):
|
| 369 |
+
"""
|
| 370 |
+
Left integer shift:
|
| 371 |
+
name = lhs << rhs
|
| 372 |
+
"""
|
| 373 |
+
|
| 374 |
+
@_binop('lshr')
|
| 375 |
+
def lshr(self, lhs, rhs, name=''):
|
| 376 |
+
"""
|
| 377 |
+
Logical (unsigned) right integer shift:
|
| 378 |
+
name = lhs >> rhs
|
| 379 |
+
"""
|
| 380 |
+
|
| 381 |
+
@_binop('ashr')
|
| 382 |
+
def ashr(self, lhs, rhs, name=''):
|
| 383 |
+
"""
|
| 384 |
+
Arithmetic (signed) right integer shift:
|
| 385 |
+
name = lhs >> rhs
|
| 386 |
+
"""
|
| 387 |
+
|
| 388 |
+
@_binop('add')
|
| 389 |
+
def add(self, lhs, rhs, name=''):
|
| 390 |
+
"""
|
| 391 |
+
Integer addition:
|
| 392 |
+
name = lhs + rhs
|
| 393 |
+
"""
|
| 394 |
+
|
| 395 |
+
@_binop('fadd')
|
| 396 |
+
def fadd(self, lhs, rhs, name=''):
|
| 397 |
+
"""
|
| 398 |
+
Floating-point addition:
|
| 399 |
+
name = lhs + rhs
|
| 400 |
+
"""
|
| 401 |
+
|
| 402 |
+
@_binop('sub')
|
| 403 |
+
def sub(self, lhs, rhs, name=''):
|
| 404 |
+
"""
|
| 405 |
+
Integer subtraction:
|
| 406 |
+
name = lhs - rhs
|
| 407 |
+
"""
|
| 408 |
+
|
| 409 |
+
@_binop('fsub')
|
| 410 |
+
def fsub(self, lhs, rhs, name=''):
|
| 411 |
+
"""
|
| 412 |
+
Floating-point subtraction:
|
| 413 |
+
name = lhs - rhs
|
| 414 |
+
"""
|
| 415 |
+
|
| 416 |
+
@_binop('mul')
|
| 417 |
+
def mul(self, lhs, rhs, name=''):
|
| 418 |
+
"""
|
| 419 |
+
Integer multiplication:
|
| 420 |
+
name = lhs * rhs
|
| 421 |
+
"""
|
| 422 |
+
|
| 423 |
+
@_binop('fmul')
|
| 424 |
+
def fmul(self, lhs, rhs, name=''):
|
| 425 |
+
"""
|
| 426 |
+
Floating-point multiplication:
|
| 427 |
+
name = lhs * rhs
|
| 428 |
+
"""
|
| 429 |
+
|
| 430 |
+
@_binop('udiv')
|
| 431 |
+
def udiv(self, lhs, rhs, name=''):
|
| 432 |
+
"""
|
| 433 |
+
Unsigned integer division:
|
| 434 |
+
name = lhs / rhs
|
| 435 |
+
"""
|
| 436 |
+
|
| 437 |
+
@_binop('sdiv')
|
| 438 |
+
def sdiv(self, lhs, rhs, name=''):
|
| 439 |
+
"""
|
| 440 |
+
Signed integer division:
|
| 441 |
+
name = lhs / rhs
|
| 442 |
+
"""
|
| 443 |
+
|
| 444 |
+
@_binop('fdiv')
|
| 445 |
+
def fdiv(self, lhs, rhs, name=''):
|
| 446 |
+
"""
|
| 447 |
+
Floating-point division:
|
| 448 |
+
name = lhs / rhs
|
| 449 |
+
"""
|
| 450 |
+
|
| 451 |
+
@_binop('urem')
|
| 452 |
+
def urem(self, lhs, rhs, name=''):
|
| 453 |
+
"""
|
| 454 |
+
Unsigned integer remainder:
|
| 455 |
+
name = lhs % rhs
|
| 456 |
+
"""
|
| 457 |
+
|
| 458 |
+
@_binop('srem')
|
| 459 |
+
def srem(self, lhs, rhs, name=''):
|
| 460 |
+
"""
|
| 461 |
+
Signed integer remainder:
|
| 462 |
+
name = lhs % rhs
|
| 463 |
+
"""
|
| 464 |
+
|
| 465 |
+
@_binop('frem')
|
| 466 |
+
def frem(self, lhs, rhs, name=''):
|
| 467 |
+
"""
|
| 468 |
+
Floating-point remainder:
|
| 469 |
+
name = lhs % rhs
|
| 470 |
+
"""
|
| 471 |
+
|
| 472 |
+
@_binop('or')
|
| 473 |
+
def or_(self, lhs, rhs, name=''):
|
| 474 |
+
"""
|
| 475 |
+
Bitwise integer OR:
|
| 476 |
+
name = lhs | rhs
|
| 477 |
+
"""
|
| 478 |
+
|
| 479 |
+
@_binop('and')
|
| 480 |
+
def and_(self, lhs, rhs, name=''):
|
| 481 |
+
"""
|
| 482 |
+
Bitwise integer AND:
|
| 483 |
+
name = lhs & rhs
|
| 484 |
+
"""
|
| 485 |
+
|
| 486 |
+
@_binop('xor')
|
| 487 |
+
def xor(self, lhs, rhs, name=''):
|
| 488 |
+
"""
|
| 489 |
+
Bitwise integer XOR:
|
| 490 |
+
name = lhs ^ rhs
|
| 491 |
+
"""
|
| 492 |
+
|
| 493 |
+
@_binop_with_overflow('sadd')
|
| 494 |
+
def sadd_with_overflow(self, lhs, rhs, name=''):
|
| 495 |
+
"""
|
| 496 |
+
Signed integer addition with overflow:
|
| 497 |
+
name = {result, overflow bit} = lhs + rhs
|
| 498 |
+
"""
|
| 499 |
+
|
| 500 |
+
@_binop_with_overflow('smul')
|
| 501 |
+
def smul_with_overflow(self, lhs, rhs, name=''):
|
| 502 |
+
"""
|
| 503 |
+
Signed integer multiplication with overflow:
|
| 504 |
+
name = {result, overflow bit} = lhs * rhs
|
| 505 |
+
"""
|
| 506 |
+
|
| 507 |
+
@_binop_with_overflow('ssub')
|
| 508 |
+
def ssub_with_overflow(self, lhs, rhs, name=''):
|
| 509 |
+
"""
|
| 510 |
+
Signed integer subtraction with overflow:
|
| 511 |
+
name = {result, overflow bit} = lhs - rhs
|
| 512 |
+
"""
|
| 513 |
+
|
| 514 |
+
@_binop_with_overflow('uadd')
|
| 515 |
+
def uadd_with_overflow(self, lhs, rhs, name=''):
|
| 516 |
+
"""
|
| 517 |
+
Unsigned integer addition with overflow:
|
| 518 |
+
name = {result, overflow bit} = lhs + rhs
|
| 519 |
+
"""
|
| 520 |
+
|
| 521 |
+
@_binop_with_overflow('umul')
|
| 522 |
+
def umul_with_overflow(self, lhs, rhs, name=''):
|
| 523 |
+
"""
|
| 524 |
+
Unsigned integer multiplication with overflow:
|
| 525 |
+
name = {result, overflow bit} = lhs * rhs
|
| 526 |
+
"""
|
| 527 |
+
|
| 528 |
+
@_binop_with_overflow('usub')
|
| 529 |
+
def usub_with_overflow(self, lhs, rhs, name=''):
|
| 530 |
+
"""
|
| 531 |
+
Unsigned integer subtraction with overflow:
|
| 532 |
+
name = {result, overflow bit} = lhs - rhs
|
| 533 |
+
"""
|
| 534 |
+
|
| 535 |
+
#
|
| 536 |
+
# Unary APIs
|
| 537 |
+
#
|
| 538 |
+
|
| 539 |
+
def not_(self, value, name=''):
|
| 540 |
+
"""
|
| 541 |
+
Bitwise integer complement:
|
| 542 |
+
name = ~value
|
| 543 |
+
"""
|
| 544 |
+
if isinstance(value.type, types.VectorType):
|
| 545 |
+
rhs = values.Constant(value.type, (-1,) * value.type.count)
|
| 546 |
+
else:
|
| 547 |
+
rhs = values.Constant(value.type, -1)
|
| 548 |
+
return self.xor(value, rhs, name=name)
|
| 549 |
+
|
| 550 |
+
def neg(self, value, name=''):
|
| 551 |
+
"""
|
| 552 |
+
Integer negative:
|
| 553 |
+
name = -value
|
| 554 |
+
"""
|
| 555 |
+
return self.sub(values.Constant(value.type, 0), value, name=name)
|
| 556 |
+
|
| 557 |
+
@_unop('fneg')
|
| 558 |
+
def fneg(self, arg, name='', flags=()):
|
| 559 |
+
"""
|
| 560 |
+
Floating-point negative:
|
| 561 |
+
name = -arg
|
| 562 |
+
"""
|
| 563 |
+
|
| 564 |
+
#
|
| 565 |
+
# Comparison APIs
|
| 566 |
+
#
|
| 567 |
+
|
| 568 |
+
def _icmp(self, prefix, cmpop, lhs, rhs, name):
|
| 569 |
+
try:
|
| 570 |
+
op = _CMP_MAP[cmpop]
|
| 571 |
+
except KeyError:
|
| 572 |
+
raise ValueError("invalid comparison %r for icmp" % (cmpop,))
|
| 573 |
+
if cmpop not in ('==', '!='):
|
| 574 |
+
op = prefix + op
|
| 575 |
+
instr = instructions.ICMPInstr(self.block, op, lhs, rhs, name=name)
|
| 576 |
+
self._insert(instr)
|
| 577 |
+
return instr
|
| 578 |
+
|
| 579 |
+
def icmp_signed(self, cmpop, lhs, rhs, name=''):
|
| 580 |
+
"""
|
| 581 |
+
Signed integer comparison:
|
| 582 |
+
name = lhs <cmpop> rhs
|
| 583 |
+
|
| 584 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>='
|
| 585 |
+
"""
|
| 586 |
+
return self._icmp('s', cmpop, lhs, rhs, name)
|
| 587 |
+
|
| 588 |
+
def icmp_unsigned(self, cmpop, lhs, rhs, name=''):
|
| 589 |
+
"""
|
| 590 |
+
Unsigned integer (or pointer) comparison:
|
| 591 |
+
name = lhs <cmpop> rhs
|
| 592 |
+
|
| 593 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>='
|
| 594 |
+
"""
|
| 595 |
+
return self._icmp('u', cmpop, lhs, rhs, name)
|
| 596 |
+
|
| 597 |
+
def fcmp_ordered(self, cmpop, lhs, rhs, name='', flags=()):
|
| 598 |
+
"""
|
| 599 |
+
Floating-point ordered comparison:
|
| 600 |
+
name = lhs <cmpop> rhs
|
| 601 |
+
|
| 602 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
|
| 603 |
+
"""
|
| 604 |
+
if cmpop in _CMP_MAP:
|
| 605 |
+
op = 'o' + _CMP_MAP[cmpop]
|
| 606 |
+
else:
|
| 607 |
+
op = cmpop
|
| 608 |
+
instr = instructions.FCMPInstr(
|
| 609 |
+
self.block, op, lhs, rhs, name=name, flags=flags)
|
| 610 |
+
self._insert(instr)
|
| 611 |
+
return instr
|
| 612 |
+
|
| 613 |
+
def fcmp_unordered(self, cmpop, lhs, rhs, name='', flags=()):
|
| 614 |
+
"""
|
| 615 |
+
Floating-point unordered comparison:
|
| 616 |
+
name = lhs <cmpop> rhs
|
| 617 |
+
|
| 618 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
|
| 619 |
+
"""
|
| 620 |
+
if cmpop in _CMP_MAP:
|
| 621 |
+
op = 'u' + _CMP_MAP[cmpop]
|
| 622 |
+
else:
|
| 623 |
+
op = cmpop
|
| 624 |
+
instr = instructions.FCMPInstr(
|
| 625 |
+
self.block, op, lhs, rhs, name=name, flags=flags)
|
| 626 |
+
self._insert(instr)
|
| 627 |
+
return instr
|
| 628 |
+
|
| 629 |
+
def select(self, cond, lhs, rhs, name='', flags=()):
|
| 630 |
+
"""
|
| 631 |
+
Ternary select operator:
|
| 632 |
+
name = cond ? lhs : rhs
|
| 633 |
+
"""
|
| 634 |
+
instr = instructions.SelectInstr(self.block, cond, lhs, rhs, name=name,
|
| 635 |
+
flags=flags)
|
| 636 |
+
self._insert(instr)
|
| 637 |
+
return instr
|
| 638 |
+
|
| 639 |
+
#
|
| 640 |
+
# Cast APIs
|
| 641 |
+
#
|
| 642 |
+
|
| 643 |
+
@_castop('trunc')
|
| 644 |
+
def trunc(self, value, typ, name=''):
|
| 645 |
+
"""
|
| 646 |
+
Truncating integer downcast to a smaller type:
|
| 647 |
+
name = (typ) value
|
| 648 |
+
"""
|
| 649 |
+
|
| 650 |
+
@_castop('zext')
|
| 651 |
+
def zext(self, value, typ, name=''):
|
| 652 |
+
"""
|
| 653 |
+
Zero-extending integer upcast to a larger type:
|
| 654 |
+
name = (typ) value
|
| 655 |
+
"""
|
| 656 |
+
|
| 657 |
+
@_castop('sext')
|
| 658 |
+
def sext(self, value, typ, name=''):
|
| 659 |
+
"""
|
| 660 |
+
Sign-extending integer upcast to a larger type:
|
| 661 |
+
name = (typ) value
|
| 662 |
+
"""
|
| 663 |
+
|
| 664 |
+
@_castop('fptrunc')
|
| 665 |
+
def fptrunc(self, value, typ, name=''):
|
| 666 |
+
"""
|
| 667 |
+
Floating-point downcast to a less precise type:
|
| 668 |
+
name = (typ) value
|
| 669 |
+
"""
|
| 670 |
+
|
| 671 |
+
@_castop('fpext')
|
| 672 |
+
def fpext(self, value, typ, name=''):
|
| 673 |
+
"""
|
| 674 |
+
Floating-point upcast to a more precise type:
|
| 675 |
+
name = (typ) value
|
| 676 |
+
"""
|
| 677 |
+
|
| 678 |
+
@_castop('bitcast')
|
| 679 |
+
def bitcast(self, value, typ, name=''):
|
| 680 |
+
"""
|
| 681 |
+
Pointer cast to a different pointer type:
|
| 682 |
+
name = (typ) value
|
| 683 |
+
"""
|
| 684 |
+
|
| 685 |
+
@_castop('addrspacecast')
|
| 686 |
+
def addrspacecast(self, value, typ, name=''):
|
| 687 |
+
"""
|
| 688 |
+
Pointer cast to a different address space:
|
| 689 |
+
name = (typ) value
|
| 690 |
+
"""
|
| 691 |
+
|
| 692 |
+
@_castop('fptoui')
|
| 693 |
+
def fptoui(self, value, typ, name=''):
|
| 694 |
+
"""
|
| 695 |
+
Convert floating-point to unsigned integer:
|
| 696 |
+
name = (typ) value
|
| 697 |
+
"""
|
| 698 |
+
|
| 699 |
+
@_castop('uitofp')
|
| 700 |
+
def uitofp(self, value, typ, name=''):
|
| 701 |
+
"""
|
| 702 |
+
Convert unsigned integer to floating-point:
|
| 703 |
+
name = (typ) value
|
| 704 |
+
"""
|
| 705 |
+
|
| 706 |
+
@_castop('fptosi')
|
| 707 |
+
def fptosi(self, value, typ, name=''):
|
| 708 |
+
"""
|
| 709 |
+
Convert floating-point to signed integer:
|
| 710 |
+
name = (typ) value
|
| 711 |
+
"""
|
| 712 |
+
|
| 713 |
+
@_castop('sitofp')
|
| 714 |
+
def sitofp(self, value, typ, name=''):
|
| 715 |
+
"""
|
| 716 |
+
Convert signed integer to floating-point:
|
| 717 |
+
name = (typ) value
|
| 718 |
+
"""
|
| 719 |
+
|
| 720 |
+
@_castop('ptrtoint')
|
| 721 |
+
def ptrtoint(self, value, typ, name=''):
|
| 722 |
+
"""
|
| 723 |
+
Cast pointer to integer:
|
| 724 |
+
name = (typ) value
|
| 725 |
+
"""
|
| 726 |
+
|
| 727 |
+
@_castop('inttoptr')
|
| 728 |
+
def inttoptr(self, value, typ, name=''):
|
| 729 |
+
"""
|
| 730 |
+
Cast integer to pointer:
|
| 731 |
+
name = (typ) value
|
| 732 |
+
"""
|
| 733 |
+
|
| 734 |
+
#
|
| 735 |
+
# Memory APIs
|
| 736 |
+
#
|
| 737 |
+
|
| 738 |
+
def alloca(self, typ, size=None, name=''):
|
| 739 |
+
"""
|
| 740 |
+
Stack-allocate a slot for *size* elements of the given type.
|
| 741 |
+
(default one element)
|
| 742 |
+
"""
|
| 743 |
+
if size is None:
|
| 744 |
+
pass
|
| 745 |
+
elif isinstance(size, (values.Value, values.Constant)):
|
| 746 |
+
assert isinstance(size.type, types.IntType)
|
| 747 |
+
else:
|
| 748 |
+
# If it is not a Value instance,
|
| 749 |
+
# assume to be a Python integer.
|
| 750 |
+
size = values.Constant(types.IntType(32), size)
|
| 751 |
+
|
| 752 |
+
al = instructions.AllocaInstr(self.block, typ, size, name)
|
| 753 |
+
self._insert(al)
|
| 754 |
+
return al
|
| 755 |
+
|
| 756 |
+
def load(self, ptr, name='', align=None):
|
| 757 |
+
"""
|
| 758 |
+
Load value from pointer, with optional guaranteed alignment:
|
| 759 |
+
name = *ptr
|
| 760 |
+
"""
|
| 761 |
+
if not isinstance(ptr.type, types.PointerType):
|
| 762 |
+
msg = "cannot load from value of type %s (%r): not a pointer"
|
| 763 |
+
raise TypeError(msg % (ptr.type, str(ptr)))
|
| 764 |
+
ld = instructions.LoadInstr(self.block, ptr, name)
|
| 765 |
+
ld.align = align
|
| 766 |
+
self._insert(ld)
|
| 767 |
+
return ld
|
| 768 |
+
|
| 769 |
+
def store(self, value, ptr, align=None):
|
| 770 |
+
"""
|
| 771 |
+
Store value to pointer, with optional guaranteed alignment:
|
| 772 |
+
*ptr = name
|
| 773 |
+
"""
|
| 774 |
+
if not isinstance(ptr.type, types.PointerType):
|
| 775 |
+
msg = "cannot store to value of type %s (%r): not a pointer"
|
| 776 |
+
raise TypeError(msg % (ptr.type, str(ptr)))
|
| 777 |
+
if ptr.type.pointee != value.type:
|
| 778 |
+
raise TypeError("cannot store %s to %s: mismatching types"
|
| 779 |
+
% (value.type, ptr.type))
|
| 780 |
+
st = instructions.StoreInstr(self.block, value, ptr)
|
| 781 |
+
st.align = align
|
| 782 |
+
self._insert(st)
|
| 783 |
+
return st
|
| 784 |
+
|
| 785 |
+
def load_atomic(self, ptr, ordering, align, name=''):
|
| 786 |
+
"""
|
| 787 |
+
Load value from pointer, with optional guaranteed alignment:
|
| 788 |
+
name = *ptr
|
| 789 |
+
"""
|
| 790 |
+
if not isinstance(ptr.type, types.PointerType):
|
| 791 |
+
msg = "cannot load from value of type %s (%r): not a pointer"
|
| 792 |
+
raise TypeError(msg % (ptr.type, str(ptr)))
|
| 793 |
+
ld = instructions.LoadAtomicInstr(
|
| 794 |
+
self.block, ptr, ordering, align, name)
|
| 795 |
+
self._insert(ld)
|
| 796 |
+
return ld
|
| 797 |
+
|
| 798 |
+
def store_atomic(self, value, ptr, ordering, align):
|
| 799 |
+
"""
|
| 800 |
+
Store value to pointer, with optional guaranteed alignment:
|
| 801 |
+
*ptr = name
|
| 802 |
+
"""
|
| 803 |
+
if not isinstance(ptr.type, types.PointerType):
|
| 804 |
+
msg = "cannot store to value of type %s (%r): not a pointer"
|
| 805 |
+
raise TypeError(msg % (ptr.type, str(ptr)))
|
| 806 |
+
if ptr.type.pointee != value.type:
|
| 807 |
+
raise TypeError("cannot store %s to %s: mismatching types"
|
| 808 |
+
% (value.type, ptr.type))
|
| 809 |
+
st = instructions.StoreAtomicInstr(
|
| 810 |
+
self.block, value, ptr, ordering, align)
|
| 811 |
+
self._insert(st)
|
| 812 |
+
return st
|
| 813 |
+
|
| 814 |
+
#
|
| 815 |
+
# Terminators APIs
|
| 816 |
+
#
|
| 817 |
+
|
| 818 |
+
def switch(self, value, default):
|
| 819 |
+
"""
|
| 820 |
+
Create a switch-case with a single *default* target.
|
| 821 |
+
"""
|
| 822 |
+
swt = instructions.SwitchInstr(self.block, 'switch', value, default)
|
| 823 |
+
self._set_terminator(swt)
|
| 824 |
+
return swt
|
| 825 |
+
|
| 826 |
+
def branch(self, target):
|
| 827 |
+
"""
|
| 828 |
+
Unconditional branch to *target*.
|
| 829 |
+
"""
|
| 830 |
+
br = instructions.Branch(self.block, "br", [target])
|
| 831 |
+
self._set_terminator(br)
|
| 832 |
+
return br
|
| 833 |
+
|
| 834 |
+
def cbranch(self, cond, truebr, falsebr):
|
| 835 |
+
"""
|
| 836 |
+
Conditional branch to *truebr* if *cond* is true, else to *falsebr*.
|
| 837 |
+
"""
|
| 838 |
+
br = instructions.ConditionalBranch(self.block, "br",
|
| 839 |
+
[cond, truebr, falsebr])
|
| 840 |
+
self._set_terminator(br)
|
| 841 |
+
return br
|
| 842 |
+
|
| 843 |
+
def branch_indirect(self, addr):
|
| 844 |
+
"""
|
| 845 |
+
Indirect branch to target *addr*.
|
| 846 |
+
"""
|
| 847 |
+
br = instructions.IndirectBranch(self.block, "indirectbr", addr)
|
| 848 |
+
self._set_terminator(br)
|
| 849 |
+
return br
|
| 850 |
+
|
| 851 |
+
def ret_void(self):
|
| 852 |
+
"""
|
| 853 |
+
Return from function without a value.
|
| 854 |
+
"""
|
| 855 |
+
return self._set_terminator(
|
| 856 |
+
instructions.Ret(self.block, "ret void"))
|
| 857 |
+
|
| 858 |
+
def ret(self, value):
|
| 859 |
+
"""
|
| 860 |
+
Return from function with the given *value*.
|
| 861 |
+
"""
|
| 862 |
+
return self._set_terminator(
|
| 863 |
+
instructions.Ret(self.block, "ret", value))
|
| 864 |
+
|
| 865 |
+
def resume(self, landingpad):
|
| 866 |
+
"""
|
| 867 |
+
Resume an in-flight exception.
|
| 868 |
+
"""
|
| 869 |
+
br = instructions.Branch(self.block, "resume", [landingpad])
|
| 870 |
+
self._set_terminator(br)
|
| 871 |
+
return br
|
| 872 |
+
|
| 873 |
+
# Call APIs
|
| 874 |
+
|
| 875 |
+
def call(self, fn, args, name='', cconv=None, tail=False, fastmath=(),
|
| 876 |
+
attrs=(), arg_attrs=None):
|
| 877 |
+
"""
|
| 878 |
+
Call function *fn* with *args*:
|
| 879 |
+
name = fn(args...)
|
| 880 |
+
"""
|
| 881 |
+
inst = instructions.CallInstr(self.block, fn, args, name=name,
|
| 882 |
+
cconv=cconv, tail=tail, fastmath=fastmath,
|
| 883 |
+
attrs=attrs, arg_attrs=arg_attrs)
|
| 884 |
+
self._insert(inst)
|
| 885 |
+
return inst
|
| 886 |
+
|
| 887 |
+
def asm(self, ftype, asm, constraint, args, side_effect, name=''):
|
| 888 |
+
"""
|
| 889 |
+
Inline assembler.
|
| 890 |
+
"""
|
| 891 |
+
asm = instructions.InlineAsm(ftype, asm, constraint, side_effect)
|
| 892 |
+
return self.call(asm, args, name)
|
| 893 |
+
|
| 894 |
+
def load_reg(self, reg_type, reg_name, name=''):
|
| 895 |
+
"""
|
| 896 |
+
Load a register value into an LLVM value.
|
| 897 |
+
Example: v = load_reg(IntType(32), "eax")
|
| 898 |
+
"""
|
| 899 |
+
ftype = types.FunctionType(reg_type, [])
|
| 900 |
+
return self.asm(ftype, "", "={%s}" % reg_name, [], False, name)
|
| 901 |
+
|
| 902 |
+
def store_reg(self, value, reg_type, reg_name, name=''):
|
| 903 |
+
"""
|
| 904 |
+
Store an LLVM value inside a register
|
| 905 |
+
Example:
|
| 906 |
+
store_reg(Constant(IntType(32), 0xAAAAAAAA), IntType(32), "eax")
|
| 907 |
+
"""
|
| 908 |
+
ftype = types.FunctionType(types.VoidType(), [reg_type])
|
| 909 |
+
return self.asm(ftype, "", "{%s}" % reg_name, [value], True, name)
|
| 910 |
+
|
| 911 |
+
def invoke(self, fn, args, normal_to, unwind_to,
|
| 912 |
+
name='', cconv=None, fastmath=(), attrs=(), arg_attrs=None):
|
| 913 |
+
inst = instructions.InvokeInstr(self.block, fn, args, normal_to,
|
| 914 |
+
unwind_to, name=name, cconv=cconv,
|
| 915 |
+
fastmath=fastmath, attrs=attrs,
|
| 916 |
+
arg_attrs=arg_attrs)
|
| 917 |
+
self._set_terminator(inst)
|
| 918 |
+
return inst
|
| 919 |
+
|
| 920 |
+
# GEP APIs
|
| 921 |
+
|
| 922 |
+
def gep(self, ptr, indices, inbounds=False, name=''):
|
| 923 |
+
"""
|
| 924 |
+
Compute effective address (getelementptr):
|
| 925 |
+
name = getelementptr ptr, <indices...>
|
| 926 |
+
"""
|
| 927 |
+
instr = instructions.GEPInstr(self.block, ptr, indices,
|
| 928 |
+
inbounds=inbounds, name=name)
|
| 929 |
+
self._insert(instr)
|
| 930 |
+
return instr
|
| 931 |
+
|
| 932 |
+
# Vector Operations APIs
|
| 933 |
+
|
| 934 |
+
def extract_element(self, vector, idx, name=''):
|
| 935 |
+
"""
|
| 936 |
+
Returns the value at position idx.
|
| 937 |
+
"""
|
| 938 |
+
instr = instructions.ExtractElement(self.block, vector, idx, name=name)
|
| 939 |
+
self._insert(instr)
|
| 940 |
+
return instr
|
| 941 |
+
|
| 942 |
+
def insert_element(self, vector, value, idx, name=''):
|
| 943 |
+
"""
|
| 944 |
+
Returns vector with vector[idx] replaced by value.
|
| 945 |
+
The result is undefined if the idx is larger or equal the vector length.
|
| 946 |
+
"""
|
| 947 |
+
instr = instructions.InsertElement(self.block, vector, value, idx,
|
| 948 |
+
name=name)
|
| 949 |
+
self._insert(instr)
|
| 950 |
+
return instr
|
| 951 |
+
|
| 952 |
+
def shuffle_vector(self, vector1, vector2, mask, name=''):
|
| 953 |
+
"""
|
| 954 |
+
Constructs a permutation of elements from *vector1* and *vector2*.
|
| 955 |
+
Returns a new vector in the same length of *mask*.
|
| 956 |
+
|
| 957 |
+
* *vector1* and *vector2* must have the same element type.
|
| 958 |
+
* *mask* must be a constant vector of integer types.
|
| 959 |
+
"""
|
| 960 |
+
instr = instructions.ShuffleVector(self.block, vector1, vector2, mask,
|
| 961 |
+
name=name)
|
| 962 |
+
self._insert(instr)
|
| 963 |
+
return instr
|
| 964 |
+
|
| 965 |
+
# Aggregate APIs
|
| 966 |
+
|
| 967 |
+
def extract_value(self, agg, idx, name=''):
|
| 968 |
+
"""
|
| 969 |
+
Extract member number *idx* from aggregate.
|
| 970 |
+
"""
|
| 971 |
+
if not isinstance(idx, (tuple, list)):
|
| 972 |
+
idx = [idx]
|
| 973 |
+
instr = instructions.ExtractValue(self.block, agg, idx, name=name)
|
| 974 |
+
self._insert(instr)
|
| 975 |
+
return instr
|
| 976 |
+
|
| 977 |
+
def insert_value(self, agg, value, idx, name=''):
|
| 978 |
+
"""
|
| 979 |
+
Insert *value* into member number *idx* from aggregate.
|
| 980 |
+
"""
|
| 981 |
+
if not isinstance(idx, (tuple, list)):
|
| 982 |
+
idx = [idx]
|
| 983 |
+
instr = instructions.InsertValue(self.block, agg, value, idx, name=name)
|
| 984 |
+
self._insert(instr)
|
| 985 |
+
return instr
|
| 986 |
+
|
| 987 |
+
# PHI APIs
|
| 988 |
+
|
| 989 |
+
def phi(self, typ, name='', flags=()):
|
| 990 |
+
inst = instructions.PhiInstr(self.block, typ, name=name, flags=flags)
|
| 991 |
+
self._insert(inst)
|
| 992 |
+
return inst
|
| 993 |
+
|
| 994 |
+
# Special API
|
| 995 |
+
|
| 996 |
+
def unreachable(self):
|
| 997 |
+
inst = instructions.Unreachable(self.block)
|
| 998 |
+
self._set_terminator(inst)
|
| 999 |
+
return inst
|
| 1000 |
+
|
| 1001 |
+
def atomic_rmw(self, op, ptr, val, ordering, name=''):
|
| 1002 |
+
inst = instructions.AtomicRMW(
|
| 1003 |
+
self.block, op, ptr, val, ordering, name=name)
|
| 1004 |
+
self._insert(inst)
|
| 1005 |
+
return inst
|
| 1006 |
+
|
| 1007 |
+
def cmpxchg(self, ptr, cmp, val, ordering, failordering=None, name=''):
|
| 1008 |
+
"""
|
| 1009 |
+
Atomic compared-and-set:
|
| 1010 |
+
atomic {
|
| 1011 |
+
old = *ptr
|
| 1012 |
+
success = (old == cmp)
|
| 1013 |
+
if (success)
|
| 1014 |
+
*ptr = val
|
| 1015 |
+
}
|
| 1016 |
+
name = { old, success }
|
| 1017 |
+
|
| 1018 |
+
If failordering is `None`, the value of `ordering` is used.
|
| 1019 |
+
"""
|
| 1020 |
+
failordering = ordering if failordering is None else failordering
|
| 1021 |
+
inst = instructions.CmpXchg(self.block, ptr, cmp, val, ordering,
|
| 1022 |
+
failordering, name=name)
|
| 1023 |
+
self._insert(inst)
|
| 1024 |
+
return inst
|
| 1025 |
+
|
| 1026 |
+
def landingpad(self, typ, name='', cleanup=False):
|
| 1027 |
+
inst = instructions.LandingPadInstr(self.block, typ, name, cleanup)
|
| 1028 |
+
self._insert(inst)
|
| 1029 |
+
return inst
|
| 1030 |
+
|
| 1031 |
+
def assume(self, cond):
|
| 1032 |
+
"""
|
| 1033 |
+
Optimizer hint: assume *cond* is always true.
|
| 1034 |
+
"""
|
| 1035 |
+
fn = self.module.declare_intrinsic("llvm.assume")
|
| 1036 |
+
return self.call(fn, [cond])
|
| 1037 |
+
|
| 1038 |
+
def fence(self, ordering, targetscope=None, name=''):
|
| 1039 |
+
"""
|
| 1040 |
+
Add a memory barrier, preventing certain reorderings of load and/or
|
| 1041 |
+
store accesses with
|
| 1042 |
+
respect to other processors and devices.
|
| 1043 |
+
"""
|
| 1044 |
+
inst = instructions.Fence(self.block, ordering, targetscope, name=name)
|
| 1045 |
+
self._insert(inst)
|
| 1046 |
+
return inst
|
| 1047 |
+
|
| 1048 |
+
def comment(self, text):
|
| 1049 |
+
"""
|
| 1050 |
+
Puts a single-line comment into the generated IR. This will be ignored
|
| 1051 |
+
by LLVM, but can be useful for debugging the output of a compiler. Adds
|
| 1052 |
+
a comment to the source file.
|
| 1053 |
+
|
| 1054 |
+
* *text* is a string that does not contain new line characters.
|
| 1055 |
+
"""
|
| 1056 |
+
inst = instructions.Comment(self.block, text)
|
| 1057 |
+
self._insert(inst)
|
| 1058 |
+
return inst
|
| 1059 |
+
|
| 1060 |
+
@_uniop_intrinsic_int("llvm.bswap")
|
| 1061 |
+
def bswap(self, cond):
|
| 1062 |
+
"""
|
| 1063 |
+
Used to byte swap integer values with an even number of bytes (positive
|
| 1064 |
+
multiple of 16 bits)
|
| 1065 |
+
"""
|
| 1066 |
+
|
| 1067 |
+
@_uniop_intrinsic_int("llvm.bitreverse")
|
| 1068 |
+
def bitreverse(self, cond):
|
| 1069 |
+
"""
|
| 1070 |
+
Reverse the bitpattern of an integer value; for example 0b10110110
|
| 1071 |
+
becomes 0b01101101.
|
| 1072 |
+
"""
|
| 1073 |
+
|
| 1074 |
+
@_uniop_intrinsic_int("llvm.ctpop")
|
| 1075 |
+
def ctpop(self, cond):
|
| 1076 |
+
"""
|
| 1077 |
+
Counts the number of bits set in a value.
|
| 1078 |
+
"""
|
| 1079 |
+
|
| 1080 |
+
@_uniop_intrinsic_with_flag("llvm.ctlz")
|
| 1081 |
+
def ctlz(self, cond, flag):
|
| 1082 |
+
"""
|
| 1083 |
+
Counts leading zero bits in *value*. Boolean *flag* indicates whether
|
| 1084 |
+
the result is defined for ``0``.
|
| 1085 |
+
"""
|
| 1086 |
+
|
| 1087 |
+
@_uniop_intrinsic_with_flag("llvm.cttz")
|
| 1088 |
+
def cttz(self, cond, flag):
|
| 1089 |
+
"""
|
| 1090 |
+
Counts trailing zero bits in *value*. Boolean *flag* indicates whether
|
| 1091 |
+
the result is defined for ``0``.
|
| 1092 |
+
"""
|
| 1093 |
+
|
| 1094 |
+
@_triop_intrinsic("llvm.fma")
|
| 1095 |
+
def fma(self, a, b, c):
|
| 1096 |
+
"""
|
| 1097 |
+
Perform the fused multiply-add operation.
|
| 1098 |
+
"""
|
| 1099 |
+
|
| 1100 |
+
def convert_from_fp16(self, a, to=None, name=''):
|
| 1101 |
+
"""
|
| 1102 |
+
Convert from an i16 to the given FP type
|
| 1103 |
+
"""
|
| 1104 |
+
if not to:
|
| 1105 |
+
raise TypeError("expected a float return type")
|
| 1106 |
+
if not isinstance(to, (types.FloatType, types.DoubleType)):
|
| 1107 |
+
raise TypeError("expected a float type, got %s" % to)
|
| 1108 |
+
if not (isinstance(a.type, types.IntType) and a.type.width == 16):
|
| 1109 |
+
raise TypeError("expected an i16 type, got %s" % a.type)
|
| 1110 |
+
|
| 1111 |
+
opname = 'llvm.convert.from.fp16'
|
| 1112 |
+
fn = self.module.declare_intrinsic(opname, [to])
|
| 1113 |
+
return self.call(fn, [a], name)
|
| 1114 |
+
|
| 1115 |
+
@_uniop_intrinsic_float("llvm.convert.to.fp16")
|
| 1116 |
+
def convert_to_fp16(self, a):
|
| 1117 |
+
"""
|
| 1118 |
+
Convert the given FP number to an i16
|
| 1119 |
+
"""
|
lib/python3.11/site-packages/llvmlite/ir/context.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.ir import _utils
|
| 2 |
+
from llvmlite.ir import types
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class Context(object):
|
| 6 |
+
def __init__(self):
|
| 7 |
+
self.scope = _utils.NameScope()
|
| 8 |
+
self.identified_types = {}
|
| 9 |
+
|
| 10 |
+
def get_identified_type(self, name):
|
| 11 |
+
if name not in self.identified_types:
|
| 12 |
+
self.scope.register(name)
|
| 13 |
+
ty = types.IdentifiedStructType(self, name)
|
| 14 |
+
self.identified_types[name] = ty
|
| 15 |
+
else:
|
| 16 |
+
ty = self.identified_types[name]
|
| 17 |
+
return ty
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
global_context = Context()
|
lib/python3.11/site-packages/llvmlite/ir/instructions.py
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Implementation of LLVM IR instructions.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from llvmlite.ir import types
|
| 6 |
+
from llvmlite.ir.values import (Block, Function, Value, NamedValue, Constant,
|
| 7 |
+
MetaDataArgument, MetaDataString, AttributeSet,
|
| 8 |
+
Undefined, ArgumentAttributes)
|
| 9 |
+
from llvmlite.ir._utils import _HasMetadata
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class Instruction(NamedValue, _HasMetadata):
|
| 13 |
+
def __init__(self, parent, typ, opname, operands, name='', flags=()):
|
| 14 |
+
super(Instruction, self).__init__(parent, typ, name=name)
|
| 15 |
+
assert isinstance(parent, Block)
|
| 16 |
+
assert isinstance(flags, (tuple, list))
|
| 17 |
+
self.opname = opname
|
| 18 |
+
self.operands = operands
|
| 19 |
+
self.flags = list(flags)
|
| 20 |
+
self.metadata = {}
|
| 21 |
+
|
| 22 |
+
@property
|
| 23 |
+
def function(self):
|
| 24 |
+
return self.parent.function
|
| 25 |
+
|
| 26 |
+
@property
|
| 27 |
+
def module(self):
|
| 28 |
+
return self.parent.function.module
|
| 29 |
+
|
| 30 |
+
def descr(self, buf):
|
| 31 |
+
opname = self.opname
|
| 32 |
+
if self.flags:
|
| 33 |
+
opname = ' '.join([opname] + self.flags)
|
| 34 |
+
operands = ', '.join([op.get_reference() for op in self.operands])
|
| 35 |
+
typ = self.type
|
| 36 |
+
metadata = self._stringify_metadata(leading_comma=True)
|
| 37 |
+
buf.append("{0} {1} {2}{3}\n"
|
| 38 |
+
.format(opname, typ, operands, metadata))
|
| 39 |
+
|
| 40 |
+
def replace_usage(self, old, new):
|
| 41 |
+
if old in self.operands:
|
| 42 |
+
ops = []
|
| 43 |
+
for op in self.operands:
|
| 44 |
+
ops.append(new if op is old else op)
|
| 45 |
+
self.operands = tuple(ops)
|
| 46 |
+
self._clear_string_cache()
|
| 47 |
+
|
| 48 |
+
def __repr__(self):
|
| 49 |
+
return "<ir.%s %r of type '%s', opname %r, operands %r>" % (
|
| 50 |
+
self.__class__.__name__, self.name, self.type,
|
| 51 |
+
self.opname, self.operands)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class CallInstrAttributes(AttributeSet):
|
| 55 |
+
_known = frozenset(['noreturn', 'nounwind', 'readonly', 'readnone',
|
| 56 |
+
'noinline', 'alwaysinline'])
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
TailMarkerOptions = frozenset(['tail', 'musttail', 'notail'])
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class FastMathFlags(AttributeSet):
|
| 63 |
+
_known = frozenset(['fast', 'nnan', 'ninf', 'nsz', 'arcp', 'contract',
|
| 64 |
+
'afn', 'reassoc'])
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class CallInstr(Instruction):
|
| 68 |
+
def __init__(self, parent, func, args, name='', cconv=None, tail=None,
|
| 69 |
+
fastmath=(), attrs=(), arg_attrs=None):
|
| 70 |
+
self.cconv = (func.calling_convention
|
| 71 |
+
if cconv is None and isinstance(func, Function)
|
| 72 |
+
else cconv)
|
| 73 |
+
|
| 74 |
+
# For backwards compatibility with previous API of accepting a "truthy"
|
| 75 |
+
# value for a hint to the optimizer to potentially tail optimize.
|
| 76 |
+
if isinstance(tail, str) and tail in TailMarkerOptions:
|
| 77 |
+
pass
|
| 78 |
+
elif tail:
|
| 79 |
+
tail = "tail"
|
| 80 |
+
else:
|
| 81 |
+
tail = ""
|
| 82 |
+
|
| 83 |
+
self.tail = tail
|
| 84 |
+
self.fastmath = FastMathFlags(fastmath)
|
| 85 |
+
self.attributes = CallInstrAttributes(attrs)
|
| 86 |
+
self.arg_attributes = {}
|
| 87 |
+
if arg_attrs:
|
| 88 |
+
for idx, attrs in arg_attrs.items():
|
| 89 |
+
if not (0 <= idx < len(args)):
|
| 90 |
+
raise ValueError("Invalid argument index {}"
|
| 91 |
+
.format(idx))
|
| 92 |
+
self.arg_attributes[idx] = ArgumentAttributes(attrs)
|
| 93 |
+
|
| 94 |
+
# Fix and validate arguments
|
| 95 |
+
args = list(args)
|
| 96 |
+
for i in range(len(func.function_type.args)):
|
| 97 |
+
arg = args[i]
|
| 98 |
+
expected_type = func.function_type.args[i]
|
| 99 |
+
if (isinstance(expected_type, types.MetaDataType) and
|
| 100 |
+
arg.type != expected_type):
|
| 101 |
+
arg = MetaDataArgument(arg)
|
| 102 |
+
if arg.type != expected_type:
|
| 103 |
+
msg = ("Type of #{0} arg mismatch: {1} != {2}"
|
| 104 |
+
.format(1 + i, expected_type, arg.type))
|
| 105 |
+
raise TypeError(msg)
|
| 106 |
+
args[i] = arg
|
| 107 |
+
|
| 108 |
+
super(CallInstr, self).__init__(parent, func.function_type.return_type,
|
| 109 |
+
"call", [func] + list(args), name=name)
|
| 110 |
+
|
| 111 |
+
@property
|
| 112 |
+
def callee(self):
|
| 113 |
+
return self.operands[0]
|
| 114 |
+
|
| 115 |
+
@callee.setter
|
| 116 |
+
def callee(self, newcallee):
|
| 117 |
+
self.operands[0] = newcallee
|
| 118 |
+
|
| 119 |
+
@property
|
| 120 |
+
def args(self):
|
| 121 |
+
return self.operands[1:]
|
| 122 |
+
|
| 123 |
+
def replace_callee(self, newfunc):
|
| 124 |
+
if newfunc.function_type != self.callee.function_type:
|
| 125 |
+
raise TypeError("New function has incompatible type")
|
| 126 |
+
self.callee = newfunc
|
| 127 |
+
|
| 128 |
+
@property
|
| 129 |
+
def called_function(self):
|
| 130 |
+
"""The callee function"""
|
| 131 |
+
return self.callee
|
| 132 |
+
|
| 133 |
+
def _descr(self, buf, add_metadata):
|
| 134 |
+
def descr_arg(i, a):
|
| 135 |
+
if i in self.arg_attributes:
|
| 136 |
+
attrs = ' '.join(self.arg_attributes[i]._to_list(a.type)) + ' '
|
| 137 |
+
else:
|
| 138 |
+
attrs = ''
|
| 139 |
+
return '{0} {1}{2}'.format(a.type, attrs, a.get_reference())
|
| 140 |
+
args = ', '.join([descr_arg(i, a) for i, a in enumerate(self.args)])
|
| 141 |
+
|
| 142 |
+
fnty = self.callee.function_type
|
| 143 |
+
# Only print function type if variable-argument
|
| 144 |
+
if fnty.var_arg:
|
| 145 |
+
ty = fnty
|
| 146 |
+
# Otherwise, just print the return type.
|
| 147 |
+
else:
|
| 148 |
+
# Fastmath flag work only in this case
|
| 149 |
+
ty = fnty.return_type
|
| 150 |
+
callee_ref = "{0} {1}".format(ty, self.callee.get_reference())
|
| 151 |
+
if self.cconv:
|
| 152 |
+
callee_ref = "{0} {1}".format(self.cconv, callee_ref)
|
| 153 |
+
|
| 154 |
+
tail_marker = ""
|
| 155 |
+
if self.tail:
|
| 156 |
+
tail_marker = "{0} ".format(self.tail)
|
| 157 |
+
|
| 158 |
+
fn_attrs = ' ' + ' '.join(self.attributes._to_list(fnty.return_type))\
|
| 159 |
+
if self.attributes else ''
|
| 160 |
+
|
| 161 |
+
fm_attrs = ' ' + ' '.join(self.fastmath._to_list(fnty.return_type))\
|
| 162 |
+
if self.fastmath else ''
|
| 163 |
+
|
| 164 |
+
buf.append("{tail}{op}{fastmath} {callee}({args}){attr}{meta}\n".format(
|
| 165 |
+
tail=tail_marker,
|
| 166 |
+
op=self.opname,
|
| 167 |
+
callee=callee_ref,
|
| 168 |
+
fastmath=fm_attrs,
|
| 169 |
+
args=args,
|
| 170 |
+
attr=fn_attrs,
|
| 171 |
+
meta=(self._stringify_metadata(leading_comma=True)
|
| 172 |
+
if add_metadata else ""),
|
| 173 |
+
))
|
| 174 |
+
|
| 175 |
+
def descr(self, buf):
|
| 176 |
+
self._descr(buf, add_metadata=True)
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
class InvokeInstr(CallInstr):
|
| 180 |
+
def __init__(self, parent, func, args, normal_to, unwind_to, name='',
|
| 181 |
+
cconv=None, fastmath=(), attrs=(), arg_attrs=None):
|
| 182 |
+
assert isinstance(normal_to, Block)
|
| 183 |
+
assert isinstance(unwind_to, Block)
|
| 184 |
+
super(InvokeInstr, self).__init__(parent, func, args, name, cconv,
|
| 185 |
+
tail=False, fastmath=fastmath,
|
| 186 |
+
attrs=attrs, arg_attrs=arg_attrs)
|
| 187 |
+
self.opname = "invoke"
|
| 188 |
+
self.normal_to = normal_to
|
| 189 |
+
self.unwind_to = unwind_to
|
| 190 |
+
|
| 191 |
+
def descr(self, buf):
|
| 192 |
+
super(InvokeInstr, self)._descr(buf, add_metadata=False)
|
| 193 |
+
buf.append(" to label {0} unwind label {1}{metadata}\n".format(
|
| 194 |
+
self.normal_to.get_reference(),
|
| 195 |
+
self.unwind_to.get_reference(),
|
| 196 |
+
metadata=self._stringify_metadata(leading_comma=True),
|
| 197 |
+
))
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
class Terminator(Instruction):
|
| 201 |
+
def __init__(self, parent, opname, operands):
|
| 202 |
+
super(Terminator, self).__init__(parent, types.VoidType(), opname,
|
| 203 |
+
operands)
|
| 204 |
+
|
| 205 |
+
def descr(self, buf):
|
| 206 |
+
opname = self.opname
|
| 207 |
+
operands = ', '.join(["{0} {1}".format(op.type, op.get_reference())
|
| 208 |
+
for op in self.operands])
|
| 209 |
+
metadata = self._stringify_metadata(leading_comma=True)
|
| 210 |
+
buf.append("{0} {1}{2}".format(opname, operands, metadata))
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
class PredictableInstr(Instruction):
|
| 214 |
+
|
| 215 |
+
def set_weights(self, weights):
|
| 216 |
+
operands = [MetaDataString(self.module, "branch_weights")]
|
| 217 |
+
for w in weights:
|
| 218 |
+
if w < 0:
|
| 219 |
+
raise ValueError("branch weight must be a positive integer")
|
| 220 |
+
operands.append(Constant(types.IntType(32), w))
|
| 221 |
+
md = self.module.add_metadata(operands)
|
| 222 |
+
self.set_metadata("prof", md)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
class Ret(Terminator):
|
| 226 |
+
def __init__(self, parent, opname, return_value=None):
|
| 227 |
+
operands = [return_value] if return_value is not None else []
|
| 228 |
+
super(Ret, self).__init__(parent, opname, operands)
|
| 229 |
+
|
| 230 |
+
@property
|
| 231 |
+
def return_value(self):
|
| 232 |
+
if self.operands:
|
| 233 |
+
return self.operands[0]
|
| 234 |
+
else:
|
| 235 |
+
return None
|
| 236 |
+
|
| 237 |
+
def descr(self, buf):
|
| 238 |
+
return_value = self.return_value
|
| 239 |
+
metadata = self._stringify_metadata(leading_comma=True)
|
| 240 |
+
if return_value is not None:
|
| 241 |
+
buf.append("{0} {1} {2}{3}\n"
|
| 242 |
+
.format(self.opname, return_value.type,
|
| 243 |
+
return_value.get_reference(),
|
| 244 |
+
metadata))
|
| 245 |
+
else:
|
| 246 |
+
buf.append("{0}{1}\n".format(self.opname, metadata))
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
class Branch(Terminator):
|
| 250 |
+
pass
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
class ConditionalBranch(PredictableInstr, Terminator):
|
| 254 |
+
pass
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
class IndirectBranch(PredictableInstr, Terminator):
|
| 258 |
+
def __init__(self, parent, opname, addr):
|
| 259 |
+
super(IndirectBranch, self).__init__(parent, opname, [addr])
|
| 260 |
+
self.destinations = []
|
| 261 |
+
|
| 262 |
+
@property
|
| 263 |
+
def address(self):
|
| 264 |
+
return self.operands[0]
|
| 265 |
+
|
| 266 |
+
def add_destination(self, block):
|
| 267 |
+
assert isinstance(block, Block)
|
| 268 |
+
self.destinations.append(block)
|
| 269 |
+
|
| 270 |
+
def descr(self, buf):
|
| 271 |
+
destinations = ["label {0}".format(blk.get_reference())
|
| 272 |
+
for blk in self.destinations]
|
| 273 |
+
buf.append("indirectbr {0} {1}, [{2}] {3}\n".format(
|
| 274 |
+
self.address.type,
|
| 275 |
+
self.address.get_reference(),
|
| 276 |
+
', '.join(destinations),
|
| 277 |
+
self._stringify_metadata(leading_comma=True),
|
| 278 |
+
))
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
class SwitchInstr(PredictableInstr, Terminator):
|
| 282 |
+
|
| 283 |
+
def __init__(self, parent, opname, val, default):
|
| 284 |
+
super(SwitchInstr, self).__init__(parent, opname, [val])
|
| 285 |
+
self.default = default
|
| 286 |
+
self.cases = []
|
| 287 |
+
|
| 288 |
+
@property
|
| 289 |
+
def value(self):
|
| 290 |
+
return self.operands[0]
|
| 291 |
+
|
| 292 |
+
def add_case(self, val, block):
|
| 293 |
+
assert isinstance(block, Block)
|
| 294 |
+
if not isinstance(val, Value):
|
| 295 |
+
val = Constant(self.value.type, val)
|
| 296 |
+
self.cases.append((val, block))
|
| 297 |
+
|
| 298 |
+
def descr(self, buf):
|
| 299 |
+
cases = ["{0} {1}, label {2}".format(val.type, val.get_reference(),
|
| 300 |
+
blk.get_reference())
|
| 301 |
+
for val, blk in self.cases]
|
| 302 |
+
buf.append("switch {0} {1}, label {2} [{3}] {4}\n".format(
|
| 303 |
+
self.value.type,
|
| 304 |
+
self.value.get_reference(),
|
| 305 |
+
self.default.get_reference(),
|
| 306 |
+
' '.join(cases),
|
| 307 |
+
self._stringify_metadata(leading_comma=True),
|
| 308 |
+
))
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
class Resume(Terminator):
|
| 312 |
+
pass
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
class SelectInstr(Instruction):
|
| 316 |
+
def __init__(self, parent, cond, lhs, rhs, name='', flags=()):
|
| 317 |
+
assert lhs.type == rhs.type
|
| 318 |
+
super(SelectInstr, self).__init__(parent, lhs.type, "select",
|
| 319 |
+
[cond, lhs, rhs], name=name,
|
| 320 |
+
flags=flags)
|
| 321 |
+
|
| 322 |
+
@property
|
| 323 |
+
def cond(self):
|
| 324 |
+
return self.operands[0]
|
| 325 |
+
|
| 326 |
+
@property
|
| 327 |
+
def lhs(self):
|
| 328 |
+
return self.operands[1]
|
| 329 |
+
|
| 330 |
+
@property
|
| 331 |
+
def rhs(self):
|
| 332 |
+
return self.operands[2]
|
| 333 |
+
|
| 334 |
+
def descr(self, buf):
|
| 335 |
+
buf.append("select {0} {1} {2}, {3} {4}, {5} {6} {7}\n".format(
|
| 336 |
+
' '.join(self.flags),
|
| 337 |
+
self.cond.type, self.cond.get_reference(),
|
| 338 |
+
self.lhs.type, self.lhs.get_reference(),
|
| 339 |
+
self.rhs.type, self.rhs.get_reference(),
|
| 340 |
+
self._stringify_metadata(leading_comma=True),
|
| 341 |
+
))
|
| 342 |
+
|
| 343 |
+
|
| 344 |
+
class CompareInstr(Instruction):
|
| 345 |
+
# Define the following in subclasses
|
| 346 |
+
OPNAME = 'invalid-compare'
|
| 347 |
+
VALID_OP = {}
|
| 348 |
+
|
| 349 |
+
def __init__(self, parent, op, lhs, rhs, name='', flags=[]):
|
| 350 |
+
if op not in self.VALID_OP:
|
| 351 |
+
raise ValueError("invalid comparison %r for %s" % (op, self.OPNAME))
|
| 352 |
+
for flag in flags:
|
| 353 |
+
if flag not in self.VALID_FLAG:
|
| 354 |
+
raise ValueError("invalid flag %r for %s" % (flag, self.OPNAME))
|
| 355 |
+
opname = self.OPNAME
|
| 356 |
+
if isinstance(lhs.type, types.VectorType):
|
| 357 |
+
typ = types.VectorType(types.IntType(1), lhs.type.count)
|
| 358 |
+
else:
|
| 359 |
+
typ = types.IntType(1)
|
| 360 |
+
super(CompareInstr, self).__init__(parent, typ,
|
| 361 |
+
opname, [lhs, rhs], flags=flags,
|
| 362 |
+
name=name)
|
| 363 |
+
self.op = op
|
| 364 |
+
|
| 365 |
+
def descr(self, buf):
|
| 366 |
+
buf.append("{opname}{flags} {op} {ty} {lhs}, {rhs} {meta}\n".format(
|
| 367 |
+
opname=self.opname,
|
| 368 |
+
flags=''.join(' ' + it for it in self.flags),
|
| 369 |
+
op=self.op,
|
| 370 |
+
ty=self.operands[0].type,
|
| 371 |
+
lhs=self.operands[0].get_reference(),
|
| 372 |
+
rhs=self.operands[1].get_reference(),
|
| 373 |
+
meta=self._stringify_metadata(leading_comma=True),
|
| 374 |
+
))
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
class ICMPInstr(CompareInstr):
|
| 378 |
+
OPNAME = 'icmp'
|
| 379 |
+
VALID_OP = {
|
| 380 |
+
'eq': 'equal',
|
| 381 |
+
'ne': 'not equal',
|
| 382 |
+
'ugt': 'unsigned greater than',
|
| 383 |
+
'uge': 'unsigned greater or equal',
|
| 384 |
+
'ult': 'unsigned less than',
|
| 385 |
+
'ule': 'unsigned less or equal',
|
| 386 |
+
'sgt': 'signed greater than',
|
| 387 |
+
'sge': 'signed greater or equal',
|
| 388 |
+
'slt': 'signed less than',
|
| 389 |
+
'sle': 'signed less or equal',
|
| 390 |
+
}
|
| 391 |
+
VALID_FLAG = set()
|
| 392 |
+
|
| 393 |
+
|
| 394 |
+
class FCMPInstr(CompareInstr):
|
| 395 |
+
OPNAME = 'fcmp'
|
| 396 |
+
VALID_OP = {
|
| 397 |
+
'false': 'no comparison, always returns false',
|
| 398 |
+
'oeq': 'ordered and equal',
|
| 399 |
+
'ogt': 'ordered and greater than',
|
| 400 |
+
'oge': 'ordered and greater than or equal',
|
| 401 |
+
'olt': 'ordered and less than',
|
| 402 |
+
'ole': 'ordered and less than or equal',
|
| 403 |
+
'one': 'ordered and not equal',
|
| 404 |
+
'ord': 'ordered (no nans)',
|
| 405 |
+
'ueq': 'unordered or equal',
|
| 406 |
+
'ugt': 'unordered or greater than',
|
| 407 |
+
'uge': 'unordered or greater than or equal',
|
| 408 |
+
'ult': 'unordered or less than',
|
| 409 |
+
'ule': 'unordered or less than or equal',
|
| 410 |
+
'une': 'unordered or not equal',
|
| 411 |
+
'uno': 'unordered (either nans)',
|
| 412 |
+
'true': 'no comparison, always returns true',
|
| 413 |
+
}
|
| 414 |
+
VALID_FLAG = {'nnan', 'ninf', 'nsz', 'arcp', 'contract', 'afn', 'reassoc',
|
| 415 |
+
'fast'}
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
class CastInstr(Instruction):
|
| 419 |
+
def __init__(self, parent, op, val, typ, name=''):
|
| 420 |
+
super(CastInstr, self).__init__(parent, typ, op, [val], name=name)
|
| 421 |
+
|
| 422 |
+
def descr(self, buf):
|
| 423 |
+
buf.append("{0} {1} {2} to {3} {4}\n".format(
|
| 424 |
+
self.opname,
|
| 425 |
+
self.operands[0].type,
|
| 426 |
+
self.operands[0].get_reference(),
|
| 427 |
+
self.type,
|
| 428 |
+
self._stringify_metadata(leading_comma=True),
|
| 429 |
+
))
|
| 430 |
+
|
| 431 |
+
|
| 432 |
+
class LoadInstr(Instruction):
|
| 433 |
+
|
| 434 |
+
def __init__(self, parent, ptr, name=''):
|
| 435 |
+
super(LoadInstr, self).__init__(parent, ptr.type.pointee, "load",
|
| 436 |
+
[ptr], name=name)
|
| 437 |
+
self.align = None
|
| 438 |
+
|
| 439 |
+
def descr(self, buf):
|
| 440 |
+
[val] = self.operands
|
| 441 |
+
if self.align is not None:
|
| 442 |
+
align = ', align %d' % (self.align)
|
| 443 |
+
else:
|
| 444 |
+
align = ''
|
| 445 |
+
buf.append("load {0}, {1} {2}{3}{4}\n".format(
|
| 446 |
+
val.type.pointee,
|
| 447 |
+
val.type,
|
| 448 |
+
val.get_reference(),
|
| 449 |
+
align,
|
| 450 |
+
self._stringify_metadata(leading_comma=True),
|
| 451 |
+
))
|
| 452 |
+
|
| 453 |
+
|
| 454 |
+
class StoreInstr(Instruction):
|
| 455 |
+
def __init__(self, parent, val, ptr):
|
| 456 |
+
super(StoreInstr, self).__init__(parent, types.VoidType(), "store",
|
| 457 |
+
[val, ptr])
|
| 458 |
+
|
| 459 |
+
def descr(self, buf):
|
| 460 |
+
val, ptr = self.operands
|
| 461 |
+
if self.align is not None:
|
| 462 |
+
align = ', align %d' % (self.align)
|
| 463 |
+
else:
|
| 464 |
+
align = ''
|
| 465 |
+
buf.append("store {0} {1}, {2} {3}{4}{5}\n".format(
|
| 466 |
+
val.type,
|
| 467 |
+
val.get_reference(),
|
| 468 |
+
ptr.type,
|
| 469 |
+
ptr.get_reference(),
|
| 470 |
+
align,
|
| 471 |
+
self._stringify_metadata(leading_comma=True),
|
| 472 |
+
))
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
class LoadAtomicInstr(Instruction):
|
| 476 |
+
def __init__(self, parent, ptr, ordering, align, name=''):
|
| 477 |
+
super(LoadAtomicInstr, self).__init__(parent, ptr.type.pointee,
|
| 478 |
+
"load atomic", [ptr], name=name)
|
| 479 |
+
self.ordering = ordering
|
| 480 |
+
self.align = align
|
| 481 |
+
|
| 482 |
+
def descr(self, buf):
|
| 483 |
+
[val] = self.operands
|
| 484 |
+
buf.append("load atomic {0}, {1} {2} {3}, align {4}{5}\n".format(
|
| 485 |
+
val.type.pointee,
|
| 486 |
+
val.type,
|
| 487 |
+
val.get_reference(),
|
| 488 |
+
self.ordering,
|
| 489 |
+
self.align,
|
| 490 |
+
self._stringify_metadata(leading_comma=True),
|
| 491 |
+
))
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
class StoreAtomicInstr(Instruction):
|
| 495 |
+
def __init__(self, parent, val, ptr, ordering, align):
|
| 496 |
+
super(StoreAtomicInstr, self).__init__(parent, types.VoidType(),
|
| 497 |
+
"store atomic", [val, ptr])
|
| 498 |
+
self.ordering = ordering
|
| 499 |
+
self.align = align
|
| 500 |
+
|
| 501 |
+
def descr(self, buf):
|
| 502 |
+
val, ptr = self.operands
|
| 503 |
+
buf.append("store atomic {0} {1}, {2} {3} {4}, align {5}{6}\n".format(
|
| 504 |
+
val.type,
|
| 505 |
+
val.get_reference(),
|
| 506 |
+
ptr.type,
|
| 507 |
+
ptr.get_reference(),
|
| 508 |
+
self.ordering,
|
| 509 |
+
self.align,
|
| 510 |
+
self._stringify_metadata(leading_comma=True),
|
| 511 |
+
))
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
class AllocaInstr(Instruction):
|
| 515 |
+
def __init__(self, parent, typ, count, name):
|
| 516 |
+
operands = [count] if count else ()
|
| 517 |
+
super(AllocaInstr, self).__init__(parent, typ.as_pointer(), "alloca",
|
| 518 |
+
operands, name)
|
| 519 |
+
self.align = None
|
| 520 |
+
|
| 521 |
+
def descr(self, buf):
|
| 522 |
+
buf.append("{0} {1}".format(self.opname, self.type.pointee))
|
| 523 |
+
if self.operands:
|
| 524 |
+
op, = self.operands
|
| 525 |
+
buf.append(", {0} {1}".format(op.type, op.get_reference()))
|
| 526 |
+
if self.align is not None:
|
| 527 |
+
buf.append(", align {0}".format(self.align))
|
| 528 |
+
if self.metadata:
|
| 529 |
+
buf.append(self._stringify_metadata(leading_comma=True))
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
class GEPInstr(Instruction):
|
| 533 |
+
def __init__(self, parent, ptr, indices, inbounds, name):
|
| 534 |
+
typ = ptr.type
|
| 535 |
+
lasttyp = None
|
| 536 |
+
lastaddrspace = 0
|
| 537 |
+
for i in indices:
|
| 538 |
+
lasttyp, typ = typ, typ.gep(i)
|
| 539 |
+
# inherit the addrspace from the last seen pointer
|
| 540 |
+
if isinstance(lasttyp, types.PointerType):
|
| 541 |
+
lastaddrspace = lasttyp.addrspace
|
| 542 |
+
|
| 543 |
+
if (not isinstance(typ, types.PointerType) and
|
| 544 |
+
isinstance(lasttyp, types.PointerType)):
|
| 545 |
+
typ = lasttyp
|
| 546 |
+
else:
|
| 547 |
+
typ = typ.as_pointer(lastaddrspace)
|
| 548 |
+
|
| 549 |
+
super(GEPInstr, self).__init__(parent, typ, "getelementptr",
|
| 550 |
+
[ptr] + list(indices), name=name)
|
| 551 |
+
self.pointer = ptr
|
| 552 |
+
self.indices = indices
|
| 553 |
+
self.inbounds = inbounds
|
| 554 |
+
|
| 555 |
+
def descr(self, buf):
|
| 556 |
+
indices = ['{0} {1}'.format(i.type, i.get_reference())
|
| 557 |
+
for i in self.indices]
|
| 558 |
+
op = "getelementptr inbounds" if self.inbounds else "getelementptr"
|
| 559 |
+
buf.append("{0} {1}, {2} {3}, {4} {5}\n".format(
|
| 560 |
+
op,
|
| 561 |
+
self.pointer.type.pointee,
|
| 562 |
+
self.pointer.type,
|
| 563 |
+
self.pointer.get_reference(),
|
| 564 |
+
', '.join(indices),
|
| 565 |
+
self._stringify_metadata(leading_comma=True),
|
| 566 |
+
))
|
| 567 |
+
|
| 568 |
+
|
| 569 |
+
class PhiInstr(Instruction):
|
| 570 |
+
def __init__(self, parent, typ, name, flags=()):
|
| 571 |
+
super(PhiInstr, self).__init__(parent, typ, "phi", (), name=name,
|
| 572 |
+
flags=flags)
|
| 573 |
+
self.incomings = []
|
| 574 |
+
|
| 575 |
+
def descr(self, buf):
|
| 576 |
+
incs = ', '.join('[{0}, {1}]'.format(v.get_reference(),
|
| 577 |
+
b.get_reference())
|
| 578 |
+
for v, b in self.incomings)
|
| 579 |
+
buf.append("phi {0} {1} {2} {3}\n".format(
|
| 580 |
+
' '.join(self.flags),
|
| 581 |
+
self.type,
|
| 582 |
+
incs,
|
| 583 |
+
self._stringify_metadata(leading_comma=True),
|
| 584 |
+
))
|
| 585 |
+
|
| 586 |
+
def add_incoming(self, value, block):
|
| 587 |
+
assert isinstance(block, Block)
|
| 588 |
+
self.incomings.append((value, block))
|
| 589 |
+
|
| 590 |
+
def replace_usage(self, old, new):
|
| 591 |
+
self.incomings = [((new if val is old else val), blk)
|
| 592 |
+
for (val, blk) in self.incomings]
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
class ExtractElement(Instruction):
|
| 596 |
+
def __init__(self, parent, vector, index, name=''):
|
| 597 |
+
if not isinstance(vector.type, types.VectorType):
|
| 598 |
+
raise TypeError("vector needs to be of VectorType.")
|
| 599 |
+
if not isinstance(index.type, types.IntType):
|
| 600 |
+
raise TypeError("index needs to be of IntType.")
|
| 601 |
+
typ = vector.type.element
|
| 602 |
+
super(ExtractElement, self).__init__(parent, typ, "extractelement",
|
| 603 |
+
[vector, index], name=name)
|
| 604 |
+
|
| 605 |
+
def descr(self, buf):
|
| 606 |
+
operands = ", ".join("{0} {1}".format(
|
| 607 |
+
op.type, op.get_reference()) for op in self.operands)
|
| 608 |
+
buf.append("{opname} {operands}\n".format(
|
| 609 |
+
opname=self.opname, operands=operands))
|
| 610 |
+
|
| 611 |
+
|
| 612 |
+
class InsertElement(Instruction):
|
| 613 |
+
def __init__(self, parent, vector, value, index, name=''):
|
| 614 |
+
if not isinstance(vector.type, types.VectorType):
|
| 615 |
+
raise TypeError("vector needs to be of VectorType.")
|
| 616 |
+
if not value.type == vector.type.element:
|
| 617 |
+
raise TypeError(
|
| 618 |
+
"value needs to be of type {} not {}.".format(
|
| 619 |
+
vector.type.element, value.type))
|
| 620 |
+
if not isinstance(index.type, types.IntType):
|
| 621 |
+
raise TypeError("index needs to be of IntType.")
|
| 622 |
+
typ = vector.type
|
| 623 |
+
super(InsertElement, self).__init__(parent, typ, "insertelement",
|
| 624 |
+
[vector, value, index], name=name)
|
| 625 |
+
|
| 626 |
+
def descr(self, buf):
|
| 627 |
+
operands = ", ".join("{0} {1}".format(
|
| 628 |
+
op.type, op.get_reference()) for op in self.operands)
|
| 629 |
+
buf.append("{opname} {operands}\n".format(
|
| 630 |
+
opname=self.opname, operands=operands))
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
class ShuffleVector(Instruction):
|
| 634 |
+
def __init__(self, parent, vector1, vector2, mask, name=''):
|
| 635 |
+
if not isinstance(vector1.type, types.VectorType):
|
| 636 |
+
raise TypeError("vector1 needs to be of VectorType.")
|
| 637 |
+
if vector2 != Undefined:
|
| 638 |
+
if vector2.type != vector1.type:
|
| 639 |
+
raise TypeError("vector2 needs to be " +
|
| 640 |
+
"Undefined or of the same type as vector1.")
|
| 641 |
+
if (not isinstance(mask, Constant) or
|
| 642 |
+
not isinstance(mask.type, types.VectorType) or
|
| 643 |
+
not (isinstance(mask.type.element, types.IntType) and
|
| 644 |
+
mask.type.element.width == 32)):
|
| 645 |
+
raise TypeError("mask needs to be a constant i32 vector.")
|
| 646 |
+
typ = types.VectorType(vector1.type.element, mask.type.count)
|
| 647 |
+
index_range = range(vector1.type.count
|
| 648 |
+
if vector2 == Undefined
|
| 649 |
+
else 2 * vector1.type.count)
|
| 650 |
+
if not all(ii.constant in index_range for ii in mask.constant):
|
| 651 |
+
raise IndexError(
|
| 652 |
+
"mask values need to be in {0}".format(index_range),
|
| 653 |
+
)
|
| 654 |
+
super(ShuffleVector, self).__init__(parent, typ, "shufflevector",
|
| 655 |
+
[vector1, vector2, mask], name=name)
|
| 656 |
+
|
| 657 |
+
def descr(self, buf):
|
| 658 |
+
buf.append("shufflevector {0} {1}\n".format(
|
| 659 |
+
", ".join("{0} {1}".format(op.type, op.get_reference())
|
| 660 |
+
for op in self.operands),
|
| 661 |
+
self._stringify_metadata(leading_comma=True),
|
| 662 |
+
))
|
| 663 |
+
|
| 664 |
+
|
| 665 |
+
class ExtractValue(Instruction):
|
| 666 |
+
def __init__(self, parent, agg, indices, name=''):
|
| 667 |
+
typ = agg.type
|
| 668 |
+
try:
|
| 669 |
+
for i in indices:
|
| 670 |
+
typ = typ.elements[i]
|
| 671 |
+
except (AttributeError, IndexError):
|
| 672 |
+
raise TypeError("Can't index at %r in %s"
|
| 673 |
+
% (list(indices), agg.type))
|
| 674 |
+
|
| 675 |
+
super(ExtractValue, self).__init__(parent, typ, "extractvalue",
|
| 676 |
+
[agg], name=name)
|
| 677 |
+
|
| 678 |
+
self.aggregate = agg
|
| 679 |
+
self.indices = indices
|
| 680 |
+
|
| 681 |
+
def descr(self, buf):
|
| 682 |
+
indices = [str(i) for i in self.indices]
|
| 683 |
+
|
| 684 |
+
buf.append("extractvalue {0} {1}, {2} {3}\n".format(
|
| 685 |
+
self.aggregate.type,
|
| 686 |
+
self.aggregate.get_reference(),
|
| 687 |
+
', '.join(indices),
|
| 688 |
+
self._stringify_metadata(leading_comma=True),
|
| 689 |
+
))
|
| 690 |
+
|
| 691 |
+
|
| 692 |
+
class InsertValue(Instruction):
|
| 693 |
+
def __init__(self, parent, agg, elem, indices, name=''):
|
| 694 |
+
typ = agg.type
|
| 695 |
+
try:
|
| 696 |
+
for i in indices:
|
| 697 |
+
typ = typ.elements[i]
|
| 698 |
+
except (AttributeError, IndexError):
|
| 699 |
+
raise TypeError("Can't index at %r in %s"
|
| 700 |
+
% (list(indices), agg.type))
|
| 701 |
+
if elem.type != typ:
|
| 702 |
+
raise TypeError("Can only insert %s at %r in %s: got %s"
|
| 703 |
+
% (typ, list(indices), agg.type, elem.type))
|
| 704 |
+
super(InsertValue, self).__init__(parent, agg.type, "insertvalue",
|
| 705 |
+
[agg, elem], name=name)
|
| 706 |
+
|
| 707 |
+
self.aggregate = agg
|
| 708 |
+
self.value = elem
|
| 709 |
+
self.indices = indices
|
| 710 |
+
|
| 711 |
+
def descr(self, buf):
|
| 712 |
+
indices = [str(i) for i in self.indices]
|
| 713 |
+
|
| 714 |
+
buf.append("insertvalue {0} {1}, {2} {3}, {4} {5}\n".format(
|
| 715 |
+
self.aggregate.type, self.aggregate.get_reference(),
|
| 716 |
+
self.value.type, self.value.get_reference(),
|
| 717 |
+
', '.join(indices),
|
| 718 |
+
self._stringify_metadata(leading_comma=True),
|
| 719 |
+
))
|
| 720 |
+
|
| 721 |
+
|
| 722 |
+
class Unreachable(Instruction):
|
| 723 |
+
def __init__(self, parent):
|
| 724 |
+
super(Unreachable, self).__init__(parent, types.VoidType(),
|
| 725 |
+
"unreachable", (), name='')
|
| 726 |
+
|
| 727 |
+
def descr(self, buf):
|
| 728 |
+
buf += (self.opname, "\n")
|
| 729 |
+
|
| 730 |
+
|
| 731 |
+
class InlineAsm(object):
|
| 732 |
+
def __init__(self, ftype, asm, constraint, side_effect=False):
|
| 733 |
+
self.type = ftype.return_type
|
| 734 |
+
self.function_type = ftype
|
| 735 |
+
self.asm = asm
|
| 736 |
+
self.constraint = constraint
|
| 737 |
+
self.side_effect = side_effect
|
| 738 |
+
|
| 739 |
+
def descr(self, buf):
|
| 740 |
+
sideeffect = 'sideeffect' if self.side_effect else ''
|
| 741 |
+
fmt = 'asm {sideeffect} "{asm}", "{constraint}"\n'
|
| 742 |
+
buf.append(fmt.format(sideeffect=sideeffect, asm=self.asm,
|
| 743 |
+
constraint=self.constraint))
|
| 744 |
+
|
| 745 |
+
def get_reference(self):
|
| 746 |
+
buf = []
|
| 747 |
+
self.descr(buf)
|
| 748 |
+
return "".join(buf)
|
| 749 |
+
|
| 750 |
+
def __str__(self):
|
| 751 |
+
return "{0} {1}".format(self.type, self.get_reference())
|
| 752 |
+
|
| 753 |
+
|
| 754 |
+
class AtomicRMW(Instruction):
|
| 755 |
+
def __init__(self, parent, op, ptr, val, ordering, name):
|
| 756 |
+
super(AtomicRMW, self).__init__(parent, val.type, "atomicrmw",
|
| 757 |
+
(ptr, val), name=name)
|
| 758 |
+
self.operation = op
|
| 759 |
+
self.ordering = ordering
|
| 760 |
+
|
| 761 |
+
def descr(self, buf):
|
| 762 |
+
ptr, val = self.operands
|
| 763 |
+
fmt = ("atomicrmw {op} {ptrty} {ptr}, {valty} {val} {ordering} "
|
| 764 |
+
"{metadata}\n")
|
| 765 |
+
buf.append(fmt.format(op=self.operation,
|
| 766 |
+
ptrty=ptr.type,
|
| 767 |
+
ptr=ptr.get_reference(),
|
| 768 |
+
valty=val.type,
|
| 769 |
+
val=val.get_reference(),
|
| 770 |
+
ordering=self.ordering,
|
| 771 |
+
metadata=self._stringify_metadata(
|
| 772 |
+
leading_comma=True),
|
| 773 |
+
))
|
| 774 |
+
|
| 775 |
+
|
| 776 |
+
class CmpXchg(Instruction):
|
| 777 |
+
"""This instruction has changed since llvm3.5. It is not compatible with
|
| 778 |
+
older llvm versions.
|
| 779 |
+
"""
|
| 780 |
+
|
| 781 |
+
def __init__(self, parent, ptr, cmp, val, ordering, failordering, name):
|
| 782 |
+
outtype = types.LiteralStructType([val.type, types.IntType(1)])
|
| 783 |
+
super(CmpXchg, self).__init__(parent, outtype, "cmpxchg",
|
| 784 |
+
(ptr, cmp, val), name=name)
|
| 785 |
+
self.ordering = ordering
|
| 786 |
+
self.failordering = failordering
|
| 787 |
+
|
| 788 |
+
def descr(self, buf):
|
| 789 |
+
ptr, cmpval, val = self.operands
|
| 790 |
+
fmt = "cmpxchg {ptrty} {ptr}, {ty} {cmp}, {ty} {val} {ordering} " \
|
| 791 |
+
"{failordering} {metadata}\n"
|
| 792 |
+
buf.append(fmt.format(ptrty=ptr.type,
|
| 793 |
+
ptr=ptr.get_reference(),
|
| 794 |
+
ty=cmpval.type,
|
| 795 |
+
cmp=cmpval.get_reference(),
|
| 796 |
+
val=val.get_reference(),
|
| 797 |
+
ordering=self.ordering,
|
| 798 |
+
failordering=self.failordering,
|
| 799 |
+
metadata=self._stringify_metadata(
|
| 800 |
+
leading_comma=True),
|
| 801 |
+
))
|
| 802 |
+
|
| 803 |
+
|
| 804 |
+
class _LandingPadClause(object):
|
| 805 |
+
def __init__(self, value):
|
| 806 |
+
self.value = value
|
| 807 |
+
|
| 808 |
+
def __str__(self):
|
| 809 |
+
return "{kind} {type} {value}".format(
|
| 810 |
+
kind=self.kind,
|
| 811 |
+
type=self.value.type,
|
| 812 |
+
value=self.value.get_reference())
|
| 813 |
+
|
| 814 |
+
|
| 815 |
+
class CatchClause(_LandingPadClause):
|
| 816 |
+
kind = 'catch'
|
| 817 |
+
|
| 818 |
+
|
| 819 |
+
class FilterClause(_LandingPadClause):
|
| 820 |
+
kind = 'filter'
|
| 821 |
+
|
| 822 |
+
def __init__(self, value):
|
| 823 |
+
assert isinstance(value, Constant)
|
| 824 |
+
assert isinstance(value.type, types.ArrayType)
|
| 825 |
+
super(FilterClause, self).__init__(value)
|
| 826 |
+
|
| 827 |
+
|
| 828 |
+
class LandingPadInstr(Instruction):
|
| 829 |
+
def __init__(self, parent, typ, name='', cleanup=False):
|
| 830 |
+
super(LandingPadInstr, self).__init__(parent, typ, "landingpad", [],
|
| 831 |
+
name=name)
|
| 832 |
+
self.cleanup = cleanup
|
| 833 |
+
self.clauses = []
|
| 834 |
+
|
| 835 |
+
def add_clause(self, clause):
|
| 836 |
+
assert isinstance(clause, _LandingPadClause)
|
| 837 |
+
self.clauses.append(clause)
|
| 838 |
+
|
| 839 |
+
def descr(self, buf):
|
| 840 |
+
fmt = "landingpad {type}{cleanup}{clauses}\n"
|
| 841 |
+
buf.append(fmt.format(type=self.type,
|
| 842 |
+
cleanup=' cleanup' if self.cleanup else '',
|
| 843 |
+
clauses=''.join(["\n {0}".format(clause)
|
| 844 |
+
for clause in self.clauses]),
|
| 845 |
+
))
|
| 846 |
+
|
| 847 |
+
|
| 848 |
+
class Fence(Instruction):
|
| 849 |
+
"""
|
| 850 |
+
The `fence` instruction.
|
| 851 |
+
|
| 852 |
+
As of LLVM 5.0.1:
|
| 853 |
+
|
| 854 |
+
fence [syncscope("<target-scope>")] <ordering> ; yields void
|
| 855 |
+
"""
|
| 856 |
+
|
| 857 |
+
VALID_FENCE_ORDERINGS = {"acquire", "release", "acq_rel", "seq_cst"}
|
| 858 |
+
|
| 859 |
+
def __init__(self, parent, ordering, targetscope=None, name=''):
|
| 860 |
+
super(Fence, self).__init__(parent, types.VoidType(), "fence", (),
|
| 861 |
+
name=name)
|
| 862 |
+
if ordering not in self.VALID_FENCE_ORDERINGS:
|
| 863 |
+
msg = "Invalid fence ordering \"{0}\"! Should be one of {1}."
|
| 864 |
+
raise ValueError(msg .format(ordering,
|
| 865 |
+
", ".join(self.VALID_FENCE_ORDERINGS)))
|
| 866 |
+
self.ordering = ordering
|
| 867 |
+
self.targetscope = targetscope
|
| 868 |
+
|
| 869 |
+
def descr(self, buf):
|
| 870 |
+
if self.targetscope is None:
|
| 871 |
+
syncscope = ""
|
| 872 |
+
else:
|
| 873 |
+
syncscope = 'syncscope("{0}") '.format(self.targetscope)
|
| 874 |
+
|
| 875 |
+
fmt = "fence {syncscope}{ordering}\n"
|
| 876 |
+
buf.append(fmt.format(syncscope=syncscope,
|
| 877 |
+
ordering=self.ordering,
|
| 878 |
+
))
|
| 879 |
+
|
| 880 |
+
|
| 881 |
+
class Comment(Instruction):
|
| 882 |
+
"""
|
| 883 |
+
A line comment.
|
| 884 |
+
"""
|
| 885 |
+
|
| 886 |
+
def __init__(self, parent, text):
|
| 887 |
+
super(Comment, self).__init__(parent, types.VoidType(), ";", (),
|
| 888 |
+
name='')
|
| 889 |
+
assert "\n" not in text, "Comment cannot contain new line"
|
| 890 |
+
self.text = text
|
| 891 |
+
|
| 892 |
+
def descr(self, buf):
|
| 893 |
+
buf.append(f"; {self.text}")
|
lib/python3.11/site-packages/llvmlite/ir/module.py
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import collections
|
| 2 |
+
|
| 3 |
+
from llvmlite.ir import context, values, types, _utils
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class Module(object):
|
| 7 |
+
def __init__(self, name='', context=context.global_context):
|
| 8 |
+
self.context = context
|
| 9 |
+
self.name = name # name is for debugging/informational
|
| 10 |
+
self.data_layout = ""
|
| 11 |
+
self.scope = _utils.NameScope()
|
| 12 |
+
self.triple = 'unknown-unknown-unknown'
|
| 13 |
+
self.globals = collections.OrderedDict()
|
| 14 |
+
# Innamed metadata nodes.
|
| 15 |
+
self.metadata = []
|
| 16 |
+
# Named metadata nodes
|
| 17 |
+
self.namedmetadata = {}
|
| 18 |
+
# Cache for metadata node deduplication
|
| 19 |
+
self._metadatacache = {}
|
| 20 |
+
|
| 21 |
+
def _fix_metadata_operands(self, operands):
|
| 22 |
+
fixed_ops = []
|
| 23 |
+
for op in operands:
|
| 24 |
+
if op is None:
|
| 25 |
+
# A literal None creates a null metadata value
|
| 26 |
+
op = types.MetaDataType()(None)
|
| 27 |
+
elif isinstance(op, str):
|
| 28 |
+
# A literal string creates a metadata string value
|
| 29 |
+
op = values.MetaDataString(self, op)
|
| 30 |
+
elif isinstance(op, (list, tuple)):
|
| 31 |
+
# A sequence creates a metadata node reference
|
| 32 |
+
op = self.add_metadata(op)
|
| 33 |
+
fixed_ops.append(op)
|
| 34 |
+
return fixed_ops
|
| 35 |
+
|
| 36 |
+
def _fix_di_operands(self, operands):
|
| 37 |
+
fixed_ops = []
|
| 38 |
+
for name, op in operands:
|
| 39 |
+
if isinstance(op, (list, tuple)):
|
| 40 |
+
# A sequence creates a metadata node reference
|
| 41 |
+
op = self.add_metadata(op)
|
| 42 |
+
fixed_ops.append((name, op))
|
| 43 |
+
return fixed_ops
|
| 44 |
+
|
| 45 |
+
def add_metadata(self, operands):
|
| 46 |
+
"""
|
| 47 |
+
Add an unnamed metadata to the module with the given *operands*
|
| 48 |
+
(a sequence of values) or return a previous equivalent metadata.
|
| 49 |
+
A MDValue instance is returned, it can then be associated to
|
| 50 |
+
e.g. an instruction.
|
| 51 |
+
"""
|
| 52 |
+
if not isinstance(operands, (list, tuple)):
|
| 53 |
+
raise TypeError("expected a list or tuple of metadata values, "
|
| 54 |
+
"got %r" % (operands,))
|
| 55 |
+
operands = self._fix_metadata_operands(operands)
|
| 56 |
+
key = tuple(operands)
|
| 57 |
+
if key not in self._metadatacache:
|
| 58 |
+
n = len(self.metadata)
|
| 59 |
+
md = values.MDValue(self, operands, name=str(n))
|
| 60 |
+
self._metadatacache[key] = md
|
| 61 |
+
else:
|
| 62 |
+
md = self._metadatacache[key]
|
| 63 |
+
return md
|
| 64 |
+
|
| 65 |
+
def add_debug_info(self, kind, operands, is_distinct=False):
|
| 66 |
+
"""
|
| 67 |
+
Add debug information metadata to the module with the given
|
| 68 |
+
*operands* (a dict of values with string keys) or return
|
| 69 |
+
a previous equivalent metadata. *kind* is a string of the
|
| 70 |
+
debug information kind (e.g. "DICompileUnit").
|
| 71 |
+
|
| 72 |
+
A DIValue instance is returned, it can then be associated to e.g.
|
| 73 |
+
an instruction.
|
| 74 |
+
"""
|
| 75 |
+
operands = tuple(sorted(self._fix_di_operands(operands.items())))
|
| 76 |
+
key = (kind, operands, is_distinct)
|
| 77 |
+
if key not in self._metadatacache:
|
| 78 |
+
n = len(self.metadata)
|
| 79 |
+
di = values.DIValue(self, is_distinct, kind, operands, name=str(n))
|
| 80 |
+
self._metadatacache[key] = di
|
| 81 |
+
else:
|
| 82 |
+
di = self._metadatacache[key]
|
| 83 |
+
return di
|
| 84 |
+
|
| 85 |
+
def add_named_metadata(self, name, element=None):
|
| 86 |
+
"""
|
| 87 |
+
Add a named metadata node to the module, if it doesn't exist,
|
| 88 |
+
or return the existing node.
|
| 89 |
+
If *element* is given, it will append a new element to
|
| 90 |
+
the named metadata node. If *element* is a sequence of values
|
| 91 |
+
(rather than a metadata value), a new unnamed node will first be
|
| 92 |
+
created.
|
| 93 |
+
|
| 94 |
+
Example::
|
| 95 |
+
module.add_named_metadata("llvm.ident", ["llvmlite/1.0"])
|
| 96 |
+
"""
|
| 97 |
+
if name in self.namedmetadata:
|
| 98 |
+
nmd = self.namedmetadata[name]
|
| 99 |
+
else:
|
| 100 |
+
nmd = self.namedmetadata[name] = values.NamedMetaData(self)
|
| 101 |
+
if element is not None:
|
| 102 |
+
if not isinstance(element, values.Value):
|
| 103 |
+
element = self.add_metadata(element)
|
| 104 |
+
if not isinstance(element.type, types.MetaDataType):
|
| 105 |
+
raise TypeError("wrong type for metadata element: got %r"
|
| 106 |
+
% (element,))
|
| 107 |
+
nmd.add(element)
|
| 108 |
+
return nmd
|
| 109 |
+
|
| 110 |
+
def get_named_metadata(self, name):
|
| 111 |
+
"""
|
| 112 |
+
Return the metadata node with the given *name*. KeyError is raised
|
| 113 |
+
if no such node exists (contrast with add_named_metadata()).
|
| 114 |
+
"""
|
| 115 |
+
return self.namedmetadata[name]
|
| 116 |
+
|
| 117 |
+
@property
|
| 118 |
+
def functions(self):
|
| 119 |
+
"""
|
| 120 |
+
A list of functions declared or defined in this module.
|
| 121 |
+
"""
|
| 122 |
+
return [v for v in self.globals.values()
|
| 123 |
+
if isinstance(v, values.Function)]
|
| 124 |
+
|
| 125 |
+
@property
|
| 126 |
+
def global_values(self):
|
| 127 |
+
"""
|
| 128 |
+
An iterable of global values in this module.
|
| 129 |
+
"""
|
| 130 |
+
return self.globals.values()
|
| 131 |
+
|
| 132 |
+
def get_global(self, name):
|
| 133 |
+
"""
|
| 134 |
+
Get a global value by name.
|
| 135 |
+
"""
|
| 136 |
+
return self.globals[name]
|
| 137 |
+
|
| 138 |
+
def add_global(self, globalvalue):
|
| 139 |
+
"""
|
| 140 |
+
Add a new global value.
|
| 141 |
+
"""
|
| 142 |
+
assert globalvalue.name not in self.globals
|
| 143 |
+
self.globals[globalvalue.name] = globalvalue
|
| 144 |
+
|
| 145 |
+
def get_unique_name(self, name=''):
|
| 146 |
+
"""
|
| 147 |
+
Get a unique global name with the following *name* hint.
|
| 148 |
+
"""
|
| 149 |
+
return self.scope.deduplicate(name)
|
| 150 |
+
|
| 151 |
+
def declare_intrinsic(self, intrinsic, tys=(), fnty=None):
|
| 152 |
+
def _error():
|
| 153 |
+
raise NotImplementedError("unknown intrinsic %r with %d types"
|
| 154 |
+
% (intrinsic, len(tys)))
|
| 155 |
+
|
| 156 |
+
if intrinsic in {'llvm.cttz', 'llvm.ctlz', 'llvm.fma'}:
|
| 157 |
+
suffixes = [tys[0].intrinsic_name]
|
| 158 |
+
else:
|
| 159 |
+
suffixes = [t.intrinsic_name for t in tys]
|
| 160 |
+
name = '.'.join([intrinsic] + suffixes)
|
| 161 |
+
if name in self.globals:
|
| 162 |
+
return self.globals[name]
|
| 163 |
+
|
| 164 |
+
if fnty is not None:
|
| 165 |
+
# General case: function type is given
|
| 166 |
+
pass
|
| 167 |
+
# Compute function type if omitted for common cases
|
| 168 |
+
elif len(tys) == 0 and intrinsic == 'llvm.assume':
|
| 169 |
+
fnty = types.FunctionType(types.VoidType(), [types.IntType(1)])
|
| 170 |
+
elif len(tys) == 1:
|
| 171 |
+
if intrinsic == 'llvm.powi':
|
| 172 |
+
fnty = types.FunctionType(tys[0], [tys[0], types.IntType(32)])
|
| 173 |
+
elif intrinsic == 'llvm.pow':
|
| 174 |
+
fnty = types.FunctionType(tys[0], tys * 2)
|
| 175 |
+
elif intrinsic == 'llvm.convert.from.fp16':
|
| 176 |
+
fnty = types.FunctionType(tys[0], [types.IntType(16)])
|
| 177 |
+
elif intrinsic == 'llvm.convert.to.fp16':
|
| 178 |
+
fnty = types.FunctionType(types.IntType(16), tys)
|
| 179 |
+
else:
|
| 180 |
+
fnty = types.FunctionType(tys[0], tys)
|
| 181 |
+
elif len(tys) == 2:
|
| 182 |
+
if intrinsic == 'llvm.memset':
|
| 183 |
+
tys = [tys[0], types.IntType(8), tys[1],
|
| 184 |
+
types.IntType(1)]
|
| 185 |
+
fnty = types.FunctionType(types.VoidType(), tys)
|
| 186 |
+
elif intrinsic in {'llvm.cttz', 'llvm.ctlz'}:
|
| 187 |
+
tys = [tys[0], types.IntType(1)]
|
| 188 |
+
fnty = types.FunctionType(tys[0], tys)
|
| 189 |
+
else:
|
| 190 |
+
_error()
|
| 191 |
+
elif len(tys) == 3:
|
| 192 |
+
if intrinsic in ('llvm.memcpy', 'llvm.memmove'):
|
| 193 |
+
tys = tys + [types.IntType(1)]
|
| 194 |
+
fnty = types.FunctionType(types.VoidType(), tys)
|
| 195 |
+
elif intrinsic == 'llvm.fma':
|
| 196 |
+
tys = [tys[0]] * 3
|
| 197 |
+
fnty = types.FunctionType(tys[0], tys)
|
| 198 |
+
else:
|
| 199 |
+
_error()
|
| 200 |
+
else:
|
| 201 |
+
_error()
|
| 202 |
+
return values.Function(self, fnty, name=name)
|
| 203 |
+
|
| 204 |
+
def get_identified_types(self):
|
| 205 |
+
return self.context.identified_types
|
| 206 |
+
|
| 207 |
+
def _get_body_lines(self):
|
| 208 |
+
# Type declarations
|
| 209 |
+
lines = [it.get_declaration()
|
| 210 |
+
for it in self.get_identified_types().values()]
|
| 211 |
+
# Global values (including function definitions)
|
| 212 |
+
lines += [str(v) for v in self.globals.values()]
|
| 213 |
+
return lines
|
| 214 |
+
|
| 215 |
+
def _get_metadata_lines(self):
|
| 216 |
+
mdbuf = []
|
| 217 |
+
for k, v in self.namedmetadata.items():
|
| 218 |
+
mdbuf.append("!{name} = !{{ {operands} }}".format(
|
| 219 |
+
name=k, operands=', '.join(i.get_reference()
|
| 220 |
+
for i in v.operands)))
|
| 221 |
+
for md in self.metadata:
|
| 222 |
+
mdbuf.append(str(md))
|
| 223 |
+
return mdbuf
|
| 224 |
+
|
| 225 |
+
def _stringify_body(self):
|
| 226 |
+
# For testing
|
| 227 |
+
return "\n".join(self._get_body_lines())
|
| 228 |
+
|
| 229 |
+
def _stringify_metadata(self):
|
| 230 |
+
# For testing
|
| 231 |
+
return "\n".join(self._get_metadata_lines())
|
| 232 |
+
|
| 233 |
+
def __repr__(self):
|
| 234 |
+
lines = []
|
| 235 |
+
# Header
|
| 236 |
+
lines += [
|
| 237 |
+
'; ModuleID = "%s"' % (self.name,),
|
| 238 |
+
'target triple = "%s"' % (self.triple,),
|
| 239 |
+
'target datalayout = "%s"' % (self.data_layout,),
|
| 240 |
+
'']
|
| 241 |
+
# Body
|
| 242 |
+
lines += self._get_body_lines()
|
| 243 |
+
# Metadata
|
| 244 |
+
lines += self._get_metadata_lines()
|
| 245 |
+
|
| 246 |
+
return "\n".join(lines)
|
lib/python3.11/site-packages/llvmlite/ir/transforms.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.ir import CallInstr
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class Visitor(object):
|
| 5 |
+
def visit(self, module):
|
| 6 |
+
self._module = module
|
| 7 |
+
for func in module.functions:
|
| 8 |
+
self.visit_Function(func)
|
| 9 |
+
|
| 10 |
+
def visit_Function(self, func):
|
| 11 |
+
self._function = func
|
| 12 |
+
for bb in func.blocks:
|
| 13 |
+
self.visit_BasicBlock(bb)
|
| 14 |
+
|
| 15 |
+
def visit_BasicBlock(self, bb):
|
| 16 |
+
self._basic_block = bb
|
| 17 |
+
for instr in bb.instructions:
|
| 18 |
+
self.visit_Instruction(instr)
|
| 19 |
+
|
| 20 |
+
def visit_Instruction(self, instr):
|
| 21 |
+
raise NotImplementedError
|
| 22 |
+
|
| 23 |
+
@property
|
| 24 |
+
def module(self):
|
| 25 |
+
return self._module
|
| 26 |
+
|
| 27 |
+
@property
|
| 28 |
+
def function(self):
|
| 29 |
+
return self._function
|
| 30 |
+
|
| 31 |
+
@property
|
| 32 |
+
def basic_block(self):
|
| 33 |
+
return self._basic_block
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class CallVisitor(Visitor):
|
| 37 |
+
def visit_Instruction(self, instr):
|
| 38 |
+
if isinstance(instr, CallInstr):
|
| 39 |
+
self.visit_Call(instr)
|
| 40 |
+
|
| 41 |
+
def visit_Call(self, instr):
|
| 42 |
+
raise NotImplementedError
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class ReplaceCalls(CallVisitor):
|
| 46 |
+
def __init__(self, orig, repl):
|
| 47 |
+
super(ReplaceCalls, self).__init__()
|
| 48 |
+
self.orig = orig
|
| 49 |
+
self.repl = repl
|
| 50 |
+
self.calls = []
|
| 51 |
+
|
| 52 |
+
def visit_Call(self, instr):
|
| 53 |
+
if instr.callee == self.orig:
|
| 54 |
+
instr.replace_callee(self.repl)
|
| 55 |
+
self.calls.append(instr)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def replace_all_calls(mod, orig, repl):
|
| 59 |
+
"""Replace all calls to `orig` to `repl` in module `mod`.
|
| 60 |
+
Returns the references to the returned calls
|
| 61 |
+
"""
|
| 62 |
+
rc = ReplaceCalls(orig, repl)
|
| 63 |
+
rc.visit(mod)
|
| 64 |
+
return rc.calls
|
lib/python3.11/site-packages/llvmlite/ir/types.py
ADDED
|
@@ -0,0 +1,614 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Classes that are LLVM types
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import struct
|
| 6 |
+
|
| 7 |
+
from llvmlite.ir._utils import _StrCaching
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def _wrapname(x):
|
| 11 |
+
return '"{0}"'.format(x.replace('\\', '\\5c').replace('"', '\\22'))
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class Type(_StrCaching):
|
| 15 |
+
"""
|
| 16 |
+
The base class for all LLVM types.
|
| 17 |
+
"""
|
| 18 |
+
is_pointer = False
|
| 19 |
+
null = 'zeroinitializer'
|
| 20 |
+
|
| 21 |
+
def __repr__(self):
|
| 22 |
+
return "<%s %s>" % (type(self), str(self))
|
| 23 |
+
|
| 24 |
+
def _to_string(self):
|
| 25 |
+
raise NotImplementedError
|
| 26 |
+
|
| 27 |
+
def as_pointer(self, addrspace=0):
|
| 28 |
+
return PointerType(self, addrspace)
|
| 29 |
+
|
| 30 |
+
def __ne__(self, other):
|
| 31 |
+
return not (self == other)
|
| 32 |
+
|
| 33 |
+
def _get_ll_pointer_type(self, target_data, context=None):
|
| 34 |
+
"""
|
| 35 |
+
Convert this type object to an LLVM type.
|
| 36 |
+
"""
|
| 37 |
+
from llvmlite.ir import Module, GlobalVariable
|
| 38 |
+
from llvmlite.binding import parse_assembly
|
| 39 |
+
|
| 40 |
+
if context is None:
|
| 41 |
+
m = Module()
|
| 42 |
+
else:
|
| 43 |
+
m = Module(context=context)
|
| 44 |
+
foo = GlobalVariable(m, self, name="foo")
|
| 45 |
+
with parse_assembly(str(m)) as llmod:
|
| 46 |
+
return llmod.get_global_variable(foo.name).type
|
| 47 |
+
|
| 48 |
+
def get_abi_size(self, target_data, context=None):
|
| 49 |
+
"""
|
| 50 |
+
Get the ABI size of this type according to data layout *target_data*.
|
| 51 |
+
"""
|
| 52 |
+
llty = self._get_ll_pointer_type(target_data, context)
|
| 53 |
+
return target_data.get_pointee_abi_size(llty)
|
| 54 |
+
|
| 55 |
+
def get_abi_alignment(self, target_data, context=None):
|
| 56 |
+
"""
|
| 57 |
+
Get the minimum ABI alignment of this type according to data layout
|
| 58 |
+
*target_data*.
|
| 59 |
+
"""
|
| 60 |
+
llty = self._get_ll_pointer_type(target_data, context)
|
| 61 |
+
return target_data.get_pointee_abi_alignment(llty)
|
| 62 |
+
|
| 63 |
+
def format_constant(self, value):
|
| 64 |
+
"""
|
| 65 |
+
Format constant *value* of this type. This method may be overriden
|
| 66 |
+
by subclasses.
|
| 67 |
+
"""
|
| 68 |
+
return str(value)
|
| 69 |
+
|
| 70 |
+
def wrap_constant_value(self, value):
|
| 71 |
+
"""
|
| 72 |
+
Wrap constant *value* if necessary. This method may be overriden
|
| 73 |
+
by subclasses (especially aggregate types).
|
| 74 |
+
"""
|
| 75 |
+
return value
|
| 76 |
+
|
| 77 |
+
def __call__(self, value):
|
| 78 |
+
"""
|
| 79 |
+
Create a LLVM constant of this type with the given Python value.
|
| 80 |
+
"""
|
| 81 |
+
from llvmlite.ir import Constant
|
| 82 |
+
return Constant(self, value)
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
class MetaDataType(Type):
|
| 86 |
+
|
| 87 |
+
def _to_string(self):
|
| 88 |
+
return "metadata"
|
| 89 |
+
|
| 90 |
+
def as_pointer(self):
|
| 91 |
+
raise TypeError
|
| 92 |
+
|
| 93 |
+
def __eq__(self, other):
|
| 94 |
+
return isinstance(other, MetaDataType)
|
| 95 |
+
|
| 96 |
+
def __hash__(self):
|
| 97 |
+
return hash(MetaDataType)
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
class LabelType(Type):
|
| 101 |
+
"""
|
| 102 |
+
The label type is the type of e.g. basic blocks.
|
| 103 |
+
"""
|
| 104 |
+
|
| 105 |
+
def _to_string(self):
|
| 106 |
+
return "label"
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
class PointerType(Type):
|
| 110 |
+
"""
|
| 111 |
+
The type of all pointer values.
|
| 112 |
+
"""
|
| 113 |
+
is_pointer = True
|
| 114 |
+
null = 'null'
|
| 115 |
+
|
| 116 |
+
def __init__(self, pointee, addrspace=0):
|
| 117 |
+
assert not isinstance(pointee, VoidType)
|
| 118 |
+
self.pointee = pointee
|
| 119 |
+
self.addrspace = addrspace
|
| 120 |
+
|
| 121 |
+
def _to_string(self):
|
| 122 |
+
if self.addrspace != 0:
|
| 123 |
+
return "{0} addrspace({1})*".format(self.pointee, self.addrspace)
|
| 124 |
+
else:
|
| 125 |
+
return "{0}*".format(self.pointee)
|
| 126 |
+
|
| 127 |
+
def __eq__(self, other):
|
| 128 |
+
if isinstance(other, PointerType):
|
| 129 |
+
return (self.pointee, self.addrspace) == (other.pointee,
|
| 130 |
+
other.addrspace)
|
| 131 |
+
else:
|
| 132 |
+
return False
|
| 133 |
+
|
| 134 |
+
def __hash__(self):
|
| 135 |
+
return hash(PointerType)
|
| 136 |
+
|
| 137 |
+
def gep(self, i):
|
| 138 |
+
"""
|
| 139 |
+
Resolve the type of the i-th element (for getelementptr lookups).
|
| 140 |
+
"""
|
| 141 |
+
if not isinstance(i.type, IntType):
|
| 142 |
+
raise TypeError(i.type)
|
| 143 |
+
return self.pointee
|
| 144 |
+
|
| 145 |
+
@property
|
| 146 |
+
def intrinsic_name(self):
|
| 147 |
+
return 'p%d%s' % (self.addrspace, self.pointee.intrinsic_name)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class VoidType(Type):
|
| 151 |
+
"""
|
| 152 |
+
The type for empty values (e.g. a function returning no value).
|
| 153 |
+
"""
|
| 154 |
+
|
| 155 |
+
def _to_string(self):
|
| 156 |
+
return 'void'
|
| 157 |
+
|
| 158 |
+
def __eq__(self, other):
|
| 159 |
+
return isinstance(other, VoidType)
|
| 160 |
+
|
| 161 |
+
def __hash__(self):
|
| 162 |
+
return hash(VoidType)
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
class FunctionType(Type):
|
| 166 |
+
"""
|
| 167 |
+
The type for functions.
|
| 168 |
+
"""
|
| 169 |
+
|
| 170 |
+
def __init__(self, return_type, args, var_arg=False):
|
| 171 |
+
self.return_type = return_type
|
| 172 |
+
self.args = tuple(args)
|
| 173 |
+
self.var_arg = var_arg
|
| 174 |
+
|
| 175 |
+
def _to_string(self):
|
| 176 |
+
if self.args:
|
| 177 |
+
strargs = ', '.join([str(a) for a in self.args])
|
| 178 |
+
if self.var_arg:
|
| 179 |
+
return '{0} ({1}, ...)'.format(self.return_type, strargs)
|
| 180 |
+
else:
|
| 181 |
+
return '{0} ({1})'.format(self.return_type, strargs)
|
| 182 |
+
elif self.var_arg:
|
| 183 |
+
return '{0} (...)'.format(self.return_type)
|
| 184 |
+
else:
|
| 185 |
+
return '{0} ()'.format(self.return_type)
|
| 186 |
+
|
| 187 |
+
def __eq__(self, other):
|
| 188 |
+
if isinstance(other, FunctionType):
|
| 189 |
+
return (self.return_type == other.return_type and
|
| 190 |
+
self.args == other.args and self.var_arg == other.var_arg)
|
| 191 |
+
else:
|
| 192 |
+
return False
|
| 193 |
+
|
| 194 |
+
def __hash__(self):
|
| 195 |
+
return hash(FunctionType)
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
class IntType(Type):
|
| 199 |
+
"""
|
| 200 |
+
The type for integers.
|
| 201 |
+
"""
|
| 202 |
+
null = '0'
|
| 203 |
+
_instance_cache = {}
|
| 204 |
+
width: int
|
| 205 |
+
|
| 206 |
+
def __new__(cls, bits):
|
| 207 |
+
# Cache all common integer types
|
| 208 |
+
if 0 <= bits <= 128:
|
| 209 |
+
try:
|
| 210 |
+
return cls._instance_cache[bits]
|
| 211 |
+
except KeyError:
|
| 212 |
+
inst = cls._instance_cache[bits] = cls.__new(bits)
|
| 213 |
+
return inst
|
| 214 |
+
return cls.__new(bits)
|
| 215 |
+
|
| 216 |
+
@classmethod
|
| 217 |
+
def __new(cls, bits):
|
| 218 |
+
assert isinstance(bits, int) and bits >= 0
|
| 219 |
+
self = super(IntType, cls).__new__(cls)
|
| 220 |
+
self.width = bits
|
| 221 |
+
return self
|
| 222 |
+
|
| 223 |
+
def __getnewargs__(self):
|
| 224 |
+
return self.width,
|
| 225 |
+
|
| 226 |
+
def __copy__(self):
|
| 227 |
+
return self
|
| 228 |
+
|
| 229 |
+
def _to_string(self):
|
| 230 |
+
return 'i%u' % (self.width,)
|
| 231 |
+
|
| 232 |
+
def __eq__(self, other):
|
| 233 |
+
if isinstance(other, IntType):
|
| 234 |
+
return self.width == other.width
|
| 235 |
+
else:
|
| 236 |
+
return False
|
| 237 |
+
|
| 238 |
+
def __hash__(self):
|
| 239 |
+
return hash(IntType)
|
| 240 |
+
|
| 241 |
+
def format_constant(self, val):
|
| 242 |
+
if isinstance(val, bool):
|
| 243 |
+
return str(val).lower()
|
| 244 |
+
else:
|
| 245 |
+
return str(val)
|
| 246 |
+
|
| 247 |
+
def wrap_constant_value(self, val):
|
| 248 |
+
if val is None:
|
| 249 |
+
return 0
|
| 250 |
+
return val
|
| 251 |
+
|
| 252 |
+
@property
|
| 253 |
+
def intrinsic_name(self):
|
| 254 |
+
return str(self)
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def _as_float(value):
|
| 258 |
+
"""
|
| 259 |
+
Truncate to single-precision float.
|
| 260 |
+
"""
|
| 261 |
+
return struct.unpack('f', struct.pack('f', value))[0]
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def _as_half(value):
|
| 265 |
+
"""
|
| 266 |
+
Truncate to half-precision float.
|
| 267 |
+
"""
|
| 268 |
+
try:
|
| 269 |
+
return struct.unpack('e', struct.pack('e', value))[0]
|
| 270 |
+
except struct.error:
|
| 271 |
+
# 'e' only added in Python 3.6+
|
| 272 |
+
return _as_float(value)
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
def _format_float_as_hex(value, packfmt, unpackfmt, numdigits):
|
| 276 |
+
raw = struct.pack(packfmt, float(value))
|
| 277 |
+
intrep = struct.unpack(unpackfmt, raw)[0]
|
| 278 |
+
out = '{{0:#{0}x}}'.format(numdigits).format(intrep)
|
| 279 |
+
return out
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def _format_double(value):
|
| 283 |
+
"""
|
| 284 |
+
Format *value* as a hexadecimal string of its IEEE double precision
|
| 285 |
+
representation.
|
| 286 |
+
"""
|
| 287 |
+
return _format_float_as_hex(value, 'd', 'Q', 16)
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
class _BaseFloatType(Type):
|
| 291 |
+
|
| 292 |
+
def __new__(cls):
|
| 293 |
+
return cls._instance_cache
|
| 294 |
+
|
| 295 |
+
def __eq__(self, other):
|
| 296 |
+
return isinstance(other, type(self))
|
| 297 |
+
|
| 298 |
+
def __hash__(self):
|
| 299 |
+
return hash(type(self))
|
| 300 |
+
|
| 301 |
+
@classmethod
|
| 302 |
+
def _create_instance(cls):
|
| 303 |
+
cls._instance_cache = super(_BaseFloatType, cls).__new__(cls)
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
class HalfType(_BaseFloatType):
|
| 307 |
+
"""
|
| 308 |
+
The type for single-precision floats.
|
| 309 |
+
"""
|
| 310 |
+
null = '0.0'
|
| 311 |
+
intrinsic_name = 'f16'
|
| 312 |
+
|
| 313 |
+
def __str__(self):
|
| 314 |
+
return 'half'
|
| 315 |
+
|
| 316 |
+
def format_constant(self, value):
|
| 317 |
+
return _format_double(_as_half(value))
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
class FloatType(_BaseFloatType):
|
| 321 |
+
"""
|
| 322 |
+
The type for single-precision floats.
|
| 323 |
+
"""
|
| 324 |
+
null = '0.0'
|
| 325 |
+
intrinsic_name = 'f32'
|
| 326 |
+
|
| 327 |
+
def __str__(self):
|
| 328 |
+
return 'float'
|
| 329 |
+
|
| 330 |
+
def format_constant(self, value):
|
| 331 |
+
return _format_double(_as_float(value))
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
class DoubleType(_BaseFloatType):
|
| 335 |
+
"""
|
| 336 |
+
The type for double-precision floats.
|
| 337 |
+
"""
|
| 338 |
+
null = '0.0'
|
| 339 |
+
intrinsic_name = 'f64'
|
| 340 |
+
|
| 341 |
+
def __str__(self):
|
| 342 |
+
return 'double'
|
| 343 |
+
|
| 344 |
+
def format_constant(self, value):
|
| 345 |
+
return _format_double(value)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
for _cls in (HalfType, FloatType, DoubleType):
|
| 349 |
+
_cls._create_instance()
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
class _Repeat(object):
|
| 353 |
+
def __init__(self, value, size):
|
| 354 |
+
self.value = value
|
| 355 |
+
self.size = size
|
| 356 |
+
|
| 357 |
+
def __len__(self):
|
| 358 |
+
return self.size
|
| 359 |
+
|
| 360 |
+
def __getitem__(self, item):
|
| 361 |
+
if 0 <= item < self.size:
|
| 362 |
+
return self.value
|
| 363 |
+
else:
|
| 364 |
+
raise IndexError(item)
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
class VectorType(Type):
|
| 368 |
+
"""
|
| 369 |
+
The type for vectors of primitive data items (e.g. "<f32 x 4>").
|
| 370 |
+
"""
|
| 371 |
+
|
| 372 |
+
def __init__(self, element, count):
|
| 373 |
+
self.element = element
|
| 374 |
+
self.count = count
|
| 375 |
+
|
| 376 |
+
@property
|
| 377 |
+
def elements(self):
|
| 378 |
+
return _Repeat(self.element, self.count)
|
| 379 |
+
|
| 380 |
+
def __len__(self):
|
| 381 |
+
return self.count
|
| 382 |
+
|
| 383 |
+
def _to_string(self):
|
| 384 |
+
return "<%d x %s>" % (self.count, self.element)
|
| 385 |
+
|
| 386 |
+
def __eq__(self, other):
|
| 387 |
+
if isinstance(other, VectorType):
|
| 388 |
+
return self.element == other.element and self.count == other.count
|
| 389 |
+
|
| 390 |
+
def __hash__(self):
|
| 391 |
+
# TODO: why does this not take self.element/self.count into account?
|
| 392 |
+
return hash(VectorType)
|
| 393 |
+
|
| 394 |
+
def __copy__(self):
|
| 395 |
+
return self
|
| 396 |
+
|
| 397 |
+
def format_constant(self, value):
|
| 398 |
+
itemstring = ", " .join(["{0} {1}".format(x.type, x.get_reference())
|
| 399 |
+
for x in value])
|
| 400 |
+
return "<{0}>".format(itemstring)
|
| 401 |
+
|
| 402 |
+
def wrap_constant_value(self, values):
|
| 403 |
+
from . import Value, Constant
|
| 404 |
+
if not isinstance(values, (list, tuple)):
|
| 405 |
+
if isinstance(values, Constant):
|
| 406 |
+
if values.type != self.element:
|
| 407 |
+
raise TypeError("expected {} for {}".format(
|
| 408 |
+
self.element, values.type))
|
| 409 |
+
return (values, ) * self.count
|
| 410 |
+
return (Constant(self.element, values), ) * self.count
|
| 411 |
+
if len(values) != len(self):
|
| 412 |
+
raise ValueError("wrong constant size for %s: got %d elements"
|
| 413 |
+
% (self, len(values)))
|
| 414 |
+
return [Constant(ty, val) if not isinstance(val, Value) else val
|
| 415 |
+
for ty, val in zip(self.elements, values)]
|
| 416 |
+
|
| 417 |
+
|
| 418 |
+
class Aggregate(Type):
|
| 419 |
+
"""
|
| 420 |
+
Base class for aggregate types.
|
| 421 |
+
See http://llvm.org/docs/LangRef.html#t-aggregate
|
| 422 |
+
"""
|
| 423 |
+
|
| 424 |
+
def wrap_constant_value(self, values):
|
| 425 |
+
from . import Value, Constant
|
| 426 |
+
|
| 427 |
+
if not isinstance(values, (list, tuple)):
|
| 428 |
+
return values
|
| 429 |
+
if len(values) != len(self):
|
| 430 |
+
raise ValueError("wrong constant size for %s: got %d elements"
|
| 431 |
+
% (self, len(values)))
|
| 432 |
+
return [Constant(ty, val) if not isinstance(val, Value) else val
|
| 433 |
+
for ty, val in zip(self.elements, values)]
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
class ArrayType(Aggregate):
|
| 437 |
+
"""
|
| 438 |
+
The type for fixed-size homogenous arrays (e.g. "[f32 x 3]").
|
| 439 |
+
"""
|
| 440 |
+
|
| 441 |
+
def __init__(self, element, count):
|
| 442 |
+
self.element = element
|
| 443 |
+
self.count = count
|
| 444 |
+
|
| 445 |
+
@property
|
| 446 |
+
def elements(self):
|
| 447 |
+
return _Repeat(self.element, self.count)
|
| 448 |
+
|
| 449 |
+
def __len__(self):
|
| 450 |
+
return self.count
|
| 451 |
+
|
| 452 |
+
def _to_string(self):
|
| 453 |
+
return "[%d x %s]" % (self.count, self.element)
|
| 454 |
+
|
| 455 |
+
def __eq__(self, other):
|
| 456 |
+
if isinstance(other, ArrayType):
|
| 457 |
+
return self.element == other.element and self.count == other.count
|
| 458 |
+
|
| 459 |
+
def __hash__(self):
|
| 460 |
+
return hash(ArrayType)
|
| 461 |
+
|
| 462 |
+
def gep(self, i):
|
| 463 |
+
"""
|
| 464 |
+
Resolve the type of the i-th element (for getelementptr lookups).
|
| 465 |
+
"""
|
| 466 |
+
if not isinstance(i.type, IntType):
|
| 467 |
+
raise TypeError(i.type)
|
| 468 |
+
return self.element
|
| 469 |
+
|
| 470 |
+
def format_constant(self, value):
|
| 471 |
+
itemstring = ", " .join(["{0} {1}".format(x.type, x.get_reference())
|
| 472 |
+
for x in value])
|
| 473 |
+
return "[{0}]".format(itemstring)
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
class BaseStructType(Aggregate):
|
| 477 |
+
"""
|
| 478 |
+
The base type for heterogenous struct types.
|
| 479 |
+
"""
|
| 480 |
+
_packed = False
|
| 481 |
+
|
| 482 |
+
@property
|
| 483 |
+
def packed(self):
|
| 484 |
+
"""
|
| 485 |
+
A boolean attribute that indicates whether the structure uses
|
| 486 |
+
packed layout.
|
| 487 |
+
"""
|
| 488 |
+
return self._packed
|
| 489 |
+
|
| 490 |
+
@packed.setter
|
| 491 |
+
def packed(self, val):
|
| 492 |
+
self._packed = bool(val)
|
| 493 |
+
|
| 494 |
+
def __len__(self):
|
| 495 |
+
assert self.elements is not None
|
| 496 |
+
return len(self.elements)
|
| 497 |
+
|
| 498 |
+
def __iter__(self):
|
| 499 |
+
assert self.elements is not None
|
| 500 |
+
return iter(self.elements)
|
| 501 |
+
|
| 502 |
+
@property
|
| 503 |
+
def is_opaque(self):
|
| 504 |
+
return self.elements is None
|
| 505 |
+
|
| 506 |
+
def structure_repr(self):
|
| 507 |
+
"""
|
| 508 |
+
Return the LLVM IR for the structure representation
|
| 509 |
+
"""
|
| 510 |
+
ret = '{%s}' % ', '.join([str(x) for x in self.elements])
|
| 511 |
+
return self._wrap_packed(ret)
|
| 512 |
+
|
| 513 |
+
def format_constant(self, value):
|
| 514 |
+
itemstring = ", " .join(["{0} {1}".format(x.type, x.get_reference())
|
| 515 |
+
for x in value])
|
| 516 |
+
ret = "{{{0}}}".format(itemstring)
|
| 517 |
+
return self._wrap_packed(ret)
|
| 518 |
+
|
| 519 |
+
def gep(self, i):
|
| 520 |
+
"""
|
| 521 |
+
Resolve the type of the i-th element (for getelementptr lookups).
|
| 522 |
+
|
| 523 |
+
*i* needs to be a LLVM constant, so that the type can be determined
|
| 524 |
+
at compile-time.
|
| 525 |
+
"""
|
| 526 |
+
if not isinstance(i.type, IntType):
|
| 527 |
+
raise TypeError(i.type)
|
| 528 |
+
return self.elements[i.constant]
|
| 529 |
+
|
| 530 |
+
def _wrap_packed(self, textrepr):
|
| 531 |
+
"""
|
| 532 |
+
Internal helper to wrap textual repr of struct type into packed struct
|
| 533 |
+
"""
|
| 534 |
+
if self.packed:
|
| 535 |
+
return '<{}>'.format(textrepr)
|
| 536 |
+
else:
|
| 537 |
+
return textrepr
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
class LiteralStructType(BaseStructType):
|
| 541 |
+
"""
|
| 542 |
+
The type of "literal" structs, i.e. structs with a literally-defined
|
| 543 |
+
type (by contrast with IdentifiedStructType).
|
| 544 |
+
"""
|
| 545 |
+
|
| 546 |
+
null = 'zeroinitializer'
|
| 547 |
+
|
| 548 |
+
def __init__(self, elems, packed=False):
|
| 549 |
+
"""
|
| 550 |
+
*elems* is a sequence of types to be used as members.
|
| 551 |
+
*packed* controls the use of packed layout.
|
| 552 |
+
"""
|
| 553 |
+
self.elements = tuple(elems)
|
| 554 |
+
self.packed = packed
|
| 555 |
+
|
| 556 |
+
def _to_string(self):
|
| 557 |
+
return self.structure_repr()
|
| 558 |
+
|
| 559 |
+
def __eq__(self, other):
|
| 560 |
+
if isinstance(other, LiteralStructType):
|
| 561 |
+
return self.elements == other.elements
|
| 562 |
+
|
| 563 |
+
def __hash__(self):
|
| 564 |
+
return hash(LiteralStructType)
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
class IdentifiedStructType(BaseStructType):
|
| 568 |
+
"""
|
| 569 |
+
A type which is a named alias for another struct type, akin to a typedef.
|
| 570 |
+
While literal struct types can be structurally equal (see
|
| 571 |
+
LiteralStructType), identified struct types are compared by name.
|
| 572 |
+
|
| 573 |
+
Do not use this directly.
|
| 574 |
+
"""
|
| 575 |
+
null = 'zeroinitializer'
|
| 576 |
+
|
| 577 |
+
def __init__(self, context, name, packed=False):
|
| 578 |
+
"""
|
| 579 |
+
*context* is a llvmlite.ir.Context.
|
| 580 |
+
*name* is the identifier for the new struct type.
|
| 581 |
+
*packed* controls the use of packed layout.
|
| 582 |
+
"""
|
| 583 |
+
assert name
|
| 584 |
+
self.context = context
|
| 585 |
+
self.name = name
|
| 586 |
+
self.elements = None
|
| 587 |
+
self.packed = packed
|
| 588 |
+
|
| 589 |
+
def _to_string(self):
|
| 590 |
+
return "%{name}".format(name=_wrapname(self.name))
|
| 591 |
+
|
| 592 |
+
def get_declaration(self):
|
| 593 |
+
"""
|
| 594 |
+
Returns the string for the declaration of the type
|
| 595 |
+
"""
|
| 596 |
+
if self.is_opaque:
|
| 597 |
+
out = "{strrep} = type opaque".format(strrep=str(self))
|
| 598 |
+
else:
|
| 599 |
+
out = "{strrep} = type {struct}".format(
|
| 600 |
+
strrep=str(self), struct=self.structure_repr())
|
| 601 |
+
return out
|
| 602 |
+
|
| 603 |
+
def __eq__(self, other):
|
| 604 |
+
if isinstance(other, IdentifiedStructType):
|
| 605 |
+
return self.name == other.name
|
| 606 |
+
|
| 607 |
+
def __hash__(self):
|
| 608 |
+
return hash(IdentifiedStructType)
|
| 609 |
+
|
| 610 |
+
def set_body(self, *elems):
|
| 611 |
+
if not self.is_opaque:
|
| 612 |
+
raise RuntimeError("{name} is already defined".format(
|
| 613 |
+
name=self.name))
|
| 614 |
+
self.elements = tuple(elems)
|
lib/python3.11/site-packages/llvmlite/ir/values.py
ADDED
|
@@ -0,0 +1,1217 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Classes that are LLVM values: Value, Constant...
|
| 3 |
+
Instructions are in the instructions module.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import functools
|
| 7 |
+
import string
|
| 8 |
+
import re
|
| 9 |
+
from types import MappingProxyType
|
| 10 |
+
|
| 11 |
+
from llvmlite.ir import values, types, _utils
|
| 12 |
+
from llvmlite.ir._utils import (_StrCaching, _StringReferenceCaching,
|
| 13 |
+
_HasMetadata)
|
| 14 |
+
|
| 15 |
+
_VALID_CHARS = (frozenset(map(ord, string.ascii_letters)) |
|
| 16 |
+
frozenset(map(ord, string.digits)) |
|
| 17 |
+
frozenset(map(ord, ' !#$%&\'()*+,-./:;<=>?@[]^_`{|}~')))
|
| 18 |
+
|
| 19 |
+
_SIMPLE_IDENTIFIER_RE = re.compile(r"[-a-zA-Z$._][-a-zA-Z$._0-9]*$")
|
| 20 |
+
|
| 21 |
+
_CMP_MAP = {
|
| 22 |
+
'>': 'gt',
|
| 23 |
+
'<': 'lt',
|
| 24 |
+
'==': 'eq',
|
| 25 |
+
'!=': 'ne',
|
| 26 |
+
'>=': 'ge',
|
| 27 |
+
'<=': 'le',
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def _escape_string(text, _map={}):
|
| 32 |
+
"""
|
| 33 |
+
Escape the given bytestring for safe use as a LLVM array constant.
|
| 34 |
+
Any unicode string input is first encoded with utf8 into bytes.
|
| 35 |
+
"""
|
| 36 |
+
if isinstance(text, str):
|
| 37 |
+
text = text.encode()
|
| 38 |
+
assert isinstance(text, (bytes, bytearray))
|
| 39 |
+
|
| 40 |
+
if not _map:
|
| 41 |
+
for ch in range(256):
|
| 42 |
+
if ch in _VALID_CHARS:
|
| 43 |
+
_map[ch] = chr(ch)
|
| 44 |
+
else:
|
| 45 |
+
_map[ch] = '\\%02x' % ch
|
| 46 |
+
|
| 47 |
+
buf = [_map[ch] for ch in text]
|
| 48 |
+
return ''.join(buf)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def _binop(opname):
|
| 52 |
+
def wrap(fn):
|
| 53 |
+
@functools.wraps(fn)
|
| 54 |
+
def wrapped(lhs, rhs):
|
| 55 |
+
if lhs.type != rhs.type:
|
| 56 |
+
raise ValueError("Operands must be the same type, got (%s, %s)"
|
| 57 |
+
% (lhs.type, rhs.type))
|
| 58 |
+
|
| 59 |
+
fmt = "{0} ({1} {2}, {3} {4})".format(opname,
|
| 60 |
+
lhs.type, lhs.get_reference(),
|
| 61 |
+
rhs.type, rhs.get_reference())
|
| 62 |
+
return FormattedConstant(lhs.type, fmt)
|
| 63 |
+
|
| 64 |
+
return wrapped
|
| 65 |
+
return wrap
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def _castop(opname):
|
| 69 |
+
def wrap(fn):
|
| 70 |
+
@functools.wraps(fn)
|
| 71 |
+
def wrapped(self, typ):
|
| 72 |
+
fn(self, typ)
|
| 73 |
+
if typ == self.type:
|
| 74 |
+
return self
|
| 75 |
+
|
| 76 |
+
op = "{0} ({1} {2} to {3})".format(opname, self.type,
|
| 77 |
+
self.get_reference(), typ)
|
| 78 |
+
return FormattedConstant(typ, op)
|
| 79 |
+
|
| 80 |
+
return wrapped
|
| 81 |
+
return wrap
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
class _ConstOpMixin(object):
|
| 85 |
+
"""
|
| 86 |
+
A mixin defining constant operations, for use in constant-like classes.
|
| 87 |
+
"""
|
| 88 |
+
|
| 89 |
+
#
|
| 90 |
+
# Arithmetic APIs
|
| 91 |
+
#
|
| 92 |
+
|
| 93 |
+
@_binop('shl')
|
| 94 |
+
def shl(self, other):
|
| 95 |
+
"""
|
| 96 |
+
Left integer shift:
|
| 97 |
+
lhs << rhs
|
| 98 |
+
"""
|
| 99 |
+
|
| 100 |
+
@_binop('lshr')
|
| 101 |
+
def lshr(self, other):
|
| 102 |
+
"""
|
| 103 |
+
Logical (unsigned) right integer shift:
|
| 104 |
+
lhs >> rhs
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
@_binop('ashr')
|
| 108 |
+
def ashr(self, other):
|
| 109 |
+
"""
|
| 110 |
+
Arithmetic (signed) right integer shift:
|
| 111 |
+
lhs >> rhs
|
| 112 |
+
"""
|
| 113 |
+
|
| 114 |
+
@_binop('add')
|
| 115 |
+
def add(self, other):
|
| 116 |
+
"""
|
| 117 |
+
Integer addition:
|
| 118 |
+
lhs + rhs
|
| 119 |
+
"""
|
| 120 |
+
|
| 121 |
+
@_binop('fadd')
|
| 122 |
+
def fadd(self, other):
|
| 123 |
+
"""
|
| 124 |
+
Floating-point addition:
|
| 125 |
+
lhs + rhs
|
| 126 |
+
"""
|
| 127 |
+
|
| 128 |
+
@_binop('sub')
|
| 129 |
+
def sub(self, other):
|
| 130 |
+
"""
|
| 131 |
+
Integer subtraction:
|
| 132 |
+
lhs - rhs
|
| 133 |
+
"""
|
| 134 |
+
|
| 135 |
+
@_binop('fsub')
|
| 136 |
+
def fsub(self, other):
|
| 137 |
+
"""
|
| 138 |
+
Floating-point subtraction:
|
| 139 |
+
lhs - rhs
|
| 140 |
+
"""
|
| 141 |
+
|
| 142 |
+
@_binop('mul')
|
| 143 |
+
def mul(self, other):
|
| 144 |
+
"""
|
| 145 |
+
Integer multiplication:
|
| 146 |
+
lhs * rhs
|
| 147 |
+
"""
|
| 148 |
+
|
| 149 |
+
@_binop('fmul')
|
| 150 |
+
def fmul(self, other):
|
| 151 |
+
"""
|
| 152 |
+
Floating-point multiplication:
|
| 153 |
+
lhs * rhs
|
| 154 |
+
"""
|
| 155 |
+
|
| 156 |
+
@_binop('udiv')
|
| 157 |
+
def udiv(self, other):
|
| 158 |
+
"""
|
| 159 |
+
Unsigned integer division:
|
| 160 |
+
lhs / rhs
|
| 161 |
+
"""
|
| 162 |
+
|
| 163 |
+
@_binop('sdiv')
|
| 164 |
+
def sdiv(self, other):
|
| 165 |
+
"""
|
| 166 |
+
Signed integer division:
|
| 167 |
+
lhs / rhs
|
| 168 |
+
"""
|
| 169 |
+
|
| 170 |
+
@_binop('fdiv')
|
| 171 |
+
def fdiv(self, other):
|
| 172 |
+
"""
|
| 173 |
+
Floating-point division:
|
| 174 |
+
lhs / rhs
|
| 175 |
+
"""
|
| 176 |
+
|
| 177 |
+
@_binop('urem')
|
| 178 |
+
def urem(self, other):
|
| 179 |
+
"""
|
| 180 |
+
Unsigned integer remainder:
|
| 181 |
+
lhs % rhs
|
| 182 |
+
"""
|
| 183 |
+
|
| 184 |
+
@_binop('srem')
|
| 185 |
+
def srem(self, other):
|
| 186 |
+
"""
|
| 187 |
+
Signed integer remainder:
|
| 188 |
+
lhs % rhs
|
| 189 |
+
"""
|
| 190 |
+
|
| 191 |
+
@_binop('frem')
|
| 192 |
+
def frem(self, other):
|
| 193 |
+
"""
|
| 194 |
+
Floating-point remainder:
|
| 195 |
+
lhs % rhs
|
| 196 |
+
"""
|
| 197 |
+
|
| 198 |
+
@_binop('or')
|
| 199 |
+
def or_(self, other):
|
| 200 |
+
"""
|
| 201 |
+
Bitwise integer OR:
|
| 202 |
+
lhs | rhs
|
| 203 |
+
"""
|
| 204 |
+
|
| 205 |
+
@_binop('and')
|
| 206 |
+
def and_(self, other):
|
| 207 |
+
"""
|
| 208 |
+
Bitwise integer AND:
|
| 209 |
+
lhs & rhs
|
| 210 |
+
"""
|
| 211 |
+
|
| 212 |
+
@_binop('xor')
|
| 213 |
+
def xor(self, other):
|
| 214 |
+
"""
|
| 215 |
+
Bitwise integer XOR:
|
| 216 |
+
lhs ^ rhs
|
| 217 |
+
"""
|
| 218 |
+
|
| 219 |
+
def _cmp(self, prefix, sign, cmpop, other):
|
| 220 |
+
ins = prefix + 'cmp'
|
| 221 |
+
try:
|
| 222 |
+
op = _CMP_MAP[cmpop]
|
| 223 |
+
except KeyError:
|
| 224 |
+
raise ValueError("invalid comparison %r for %s" % (cmpop, ins))
|
| 225 |
+
|
| 226 |
+
if not (prefix == 'i' and cmpop in ('==', '!=')):
|
| 227 |
+
op = sign + op
|
| 228 |
+
|
| 229 |
+
if self.type != other.type:
|
| 230 |
+
raise ValueError("Operands must be the same type, got (%s, %s)"
|
| 231 |
+
% (self.type, other.type))
|
| 232 |
+
|
| 233 |
+
fmt = "{0} {1} ({2} {3}, {4} {5})".format(
|
| 234 |
+
ins, op,
|
| 235 |
+
self.type, self.get_reference(),
|
| 236 |
+
other.type, other.get_reference())
|
| 237 |
+
|
| 238 |
+
return FormattedConstant(types.IntType(1), fmt)
|
| 239 |
+
|
| 240 |
+
def icmp_signed(self, cmpop, other):
|
| 241 |
+
"""
|
| 242 |
+
Signed integer comparison:
|
| 243 |
+
lhs <cmpop> rhs
|
| 244 |
+
|
| 245 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>='
|
| 246 |
+
"""
|
| 247 |
+
return self._cmp('i', 's', cmpop, other)
|
| 248 |
+
|
| 249 |
+
def icmp_unsigned(self, cmpop, other):
|
| 250 |
+
"""
|
| 251 |
+
Unsigned integer (or pointer) comparison:
|
| 252 |
+
lhs <cmpop> rhs
|
| 253 |
+
|
| 254 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>='
|
| 255 |
+
"""
|
| 256 |
+
return self._cmp('i', 'u', cmpop, other)
|
| 257 |
+
|
| 258 |
+
def fcmp_ordered(self, cmpop, other):
|
| 259 |
+
"""
|
| 260 |
+
Floating-point ordered comparison:
|
| 261 |
+
lhs <cmpop> rhs
|
| 262 |
+
|
| 263 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
|
| 264 |
+
"""
|
| 265 |
+
return self._cmp('f', 'o', cmpop, other)
|
| 266 |
+
|
| 267 |
+
def fcmp_unordered(self, cmpop, other):
|
| 268 |
+
"""
|
| 269 |
+
Floating-point unordered comparison:
|
| 270 |
+
lhs <cmpop> rhs
|
| 271 |
+
|
| 272 |
+
where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
|
| 273 |
+
"""
|
| 274 |
+
return self._cmp('f', 'u', cmpop, other)
|
| 275 |
+
|
| 276 |
+
#
|
| 277 |
+
# Unary APIs
|
| 278 |
+
#
|
| 279 |
+
|
| 280 |
+
def not_(self):
|
| 281 |
+
"""
|
| 282 |
+
Bitwise integer complement:
|
| 283 |
+
~value
|
| 284 |
+
"""
|
| 285 |
+
if isinstance(self.type, types.VectorType):
|
| 286 |
+
rhs = values.Constant(self.type, (-1,) * self.type.count)
|
| 287 |
+
else:
|
| 288 |
+
rhs = values.Constant(self.type, -1)
|
| 289 |
+
|
| 290 |
+
return self.xor(rhs)
|
| 291 |
+
|
| 292 |
+
def neg(self):
|
| 293 |
+
"""
|
| 294 |
+
Integer negative:
|
| 295 |
+
-value
|
| 296 |
+
"""
|
| 297 |
+
zero = values.Constant(self.type, 0)
|
| 298 |
+
return zero.sub(self)
|
| 299 |
+
|
| 300 |
+
def fneg(self):
|
| 301 |
+
"""
|
| 302 |
+
Floating-point negative:
|
| 303 |
+
-value
|
| 304 |
+
"""
|
| 305 |
+
fmt = "fneg ({0} {1})".format(self.type, self.get_reference())
|
| 306 |
+
return FormattedConstant(self.type, fmt)
|
| 307 |
+
|
| 308 |
+
#
|
| 309 |
+
# Cast APIs
|
| 310 |
+
#
|
| 311 |
+
|
| 312 |
+
@_castop('trunc')
|
| 313 |
+
def trunc(self, typ):
|
| 314 |
+
"""
|
| 315 |
+
Truncating integer downcast to a smaller type.
|
| 316 |
+
"""
|
| 317 |
+
|
| 318 |
+
@_castop('zext')
|
| 319 |
+
def zext(self, typ):
|
| 320 |
+
"""
|
| 321 |
+
Zero-extending integer upcast to a larger type
|
| 322 |
+
"""
|
| 323 |
+
|
| 324 |
+
@_castop('sext')
|
| 325 |
+
def sext(self, typ):
|
| 326 |
+
"""
|
| 327 |
+
Sign-extending integer upcast to a larger type.
|
| 328 |
+
"""
|
| 329 |
+
|
| 330 |
+
@_castop('fptrunc')
|
| 331 |
+
def fptrunc(self, typ):
|
| 332 |
+
"""
|
| 333 |
+
Floating-point downcast to a less precise type.
|
| 334 |
+
"""
|
| 335 |
+
|
| 336 |
+
@_castop('fpext')
|
| 337 |
+
def fpext(self, typ):
|
| 338 |
+
"""
|
| 339 |
+
Floating-point upcast to a more precise type.
|
| 340 |
+
"""
|
| 341 |
+
|
| 342 |
+
@_castop('bitcast')
|
| 343 |
+
def bitcast(self, typ):
|
| 344 |
+
"""
|
| 345 |
+
Pointer cast to a different pointer type.
|
| 346 |
+
"""
|
| 347 |
+
|
| 348 |
+
@_castop('fptoui')
|
| 349 |
+
def fptoui(self, typ):
|
| 350 |
+
"""
|
| 351 |
+
Convert floating-point to unsigned integer.
|
| 352 |
+
"""
|
| 353 |
+
|
| 354 |
+
@_castop('uitofp')
|
| 355 |
+
def uitofp(self, typ):
|
| 356 |
+
"""
|
| 357 |
+
Convert unsigned integer to floating-point.
|
| 358 |
+
"""
|
| 359 |
+
|
| 360 |
+
@_castop('fptosi')
|
| 361 |
+
def fptosi(self, typ):
|
| 362 |
+
"""
|
| 363 |
+
Convert floating-point to signed integer.
|
| 364 |
+
"""
|
| 365 |
+
|
| 366 |
+
@_castop('sitofp')
|
| 367 |
+
def sitofp(self, typ):
|
| 368 |
+
"""
|
| 369 |
+
Convert signed integer to floating-point.
|
| 370 |
+
"""
|
| 371 |
+
|
| 372 |
+
@_castop('ptrtoint')
|
| 373 |
+
def ptrtoint(self, typ):
|
| 374 |
+
"""
|
| 375 |
+
Cast pointer to integer.
|
| 376 |
+
"""
|
| 377 |
+
if not isinstance(self.type, types.PointerType):
|
| 378 |
+
msg = "can only call ptrtoint() on pointer type, not '%s'"
|
| 379 |
+
raise TypeError(msg % (self.type,))
|
| 380 |
+
if not isinstance(typ, types.IntType):
|
| 381 |
+
raise TypeError("can only ptrtoint() to integer type, not '%s'"
|
| 382 |
+
% (typ,))
|
| 383 |
+
|
| 384 |
+
@_castop('inttoptr')
|
| 385 |
+
def inttoptr(self, typ):
|
| 386 |
+
"""
|
| 387 |
+
Cast integer to pointer.
|
| 388 |
+
"""
|
| 389 |
+
if not isinstance(self.type, types.IntType):
|
| 390 |
+
msg = "can only call inttoptr() on integer constants, not '%s'"
|
| 391 |
+
raise TypeError(msg % (self.type,))
|
| 392 |
+
if not isinstance(typ, types.PointerType):
|
| 393 |
+
raise TypeError("can only inttoptr() to pointer type, not '%s'"
|
| 394 |
+
% (typ,))
|
| 395 |
+
|
| 396 |
+
def gep(self, indices):
|
| 397 |
+
"""
|
| 398 |
+
Call getelementptr on this pointer constant.
|
| 399 |
+
"""
|
| 400 |
+
if not isinstance(self.type, types.PointerType):
|
| 401 |
+
raise TypeError("can only call gep() on pointer constants, not '%s'"
|
| 402 |
+
% (self.type,))
|
| 403 |
+
|
| 404 |
+
outtype = self.type
|
| 405 |
+
for i in indices:
|
| 406 |
+
outtype = outtype.gep(i)
|
| 407 |
+
|
| 408 |
+
strindices = ["{0} {1}".format(idx.type, idx.get_reference())
|
| 409 |
+
for idx in indices]
|
| 410 |
+
|
| 411 |
+
op = "getelementptr ({0}, {1} {2}, {3})".format(
|
| 412 |
+
self.type.pointee, self.type,
|
| 413 |
+
self.get_reference(), ', '.join(strindices))
|
| 414 |
+
return FormattedConstant(outtype.as_pointer(self.addrspace), op)
|
| 415 |
+
|
| 416 |
+
|
| 417 |
+
class Value(object):
|
| 418 |
+
"""
|
| 419 |
+
The base class for all values.
|
| 420 |
+
"""
|
| 421 |
+
|
| 422 |
+
def __repr__(self):
|
| 423 |
+
return "<ir.%s type='%s' ...>" % (self.__class__.__name__, self.type,)
|
| 424 |
+
|
| 425 |
+
|
| 426 |
+
class _Undefined(object):
|
| 427 |
+
"""
|
| 428 |
+
'undef': a value for undefined values.
|
| 429 |
+
"""
|
| 430 |
+
def __new__(cls):
|
| 431 |
+
try:
|
| 432 |
+
return Undefined
|
| 433 |
+
except NameError:
|
| 434 |
+
return object.__new__(_Undefined)
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
Undefined = _Undefined()
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
class Constant(_StrCaching, _StringReferenceCaching, _ConstOpMixin, Value):
|
| 441 |
+
"""
|
| 442 |
+
A constant LLVM value.
|
| 443 |
+
"""
|
| 444 |
+
|
| 445 |
+
def __init__(self, typ, constant):
|
| 446 |
+
assert isinstance(typ, types.Type)
|
| 447 |
+
assert not isinstance(typ, types.VoidType)
|
| 448 |
+
self.type = typ
|
| 449 |
+
constant = typ.wrap_constant_value(constant)
|
| 450 |
+
self.constant = constant
|
| 451 |
+
|
| 452 |
+
def _to_string(self):
|
| 453 |
+
return '{0} {1}'.format(self.type, self.get_reference())
|
| 454 |
+
|
| 455 |
+
def _get_reference(self):
|
| 456 |
+
if self.constant is None:
|
| 457 |
+
val = self.type.null
|
| 458 |
+
|
| 459 |
+
elif self.constant is Undefined:
|
| 460 |
+
val = "undef"
|
| 461 |
+
|
| 462 |
+
elif isinstance(self.constant, bytearray):
|
| 463 |
+
val = 'c"{0}"'.format(_escape_string(self.constant))
|
| 464 |
+
|
| 465 |
+
else:
|
| 466 |
+
val = self.type.format_constant(self.constant)
|
| 467 |
+
|
| 468 |
+
return val
|
| 469 |
+
|
| 470 |
+
@classmethod
|
| 471 |
+
def literal_array(cls, elems):
|
| 472 |
+
"""
|
| 473 |
+
Construct a literal array constant made of the given members.
|
| 474 |
+
"""
|
| 475 |
+
tys = [el.type for el in elems]
|
| 476 |
+
if len(tys) == 0:
|
| 477 |
+
raise ValueError("need at least one element")
|
| 478 |
+
ty = tys[0]
|
| 479 |
+
for other in tys:
|
| 480 |
+
if ty != other:
|
| 481 |
+
raise TypeError("all elements must have the same type")
|
| 482 |
+
return cls(types.ArrayType(ty, len(elems)), elems)
|
| 483 |
+
|
| 484 |
+
@classmethod
|
| 485 |
+
def literal_struct(cls, elems):
|
| 486 |
+
"""
|
| 487 |
+
Construct a literal structure constant made of the given members.
|
| 488 |
+
"""
|
| 489 |
+
tys = [el.type for el in elems]
|
| 490 |
+
return cls(types.LiteralStructType(tys), elems)
|
| 491 |
+
|
| 492 |
+
@property
|
| 493 |
+
def addrspace(self):
|
| 494 |
+
if not isinstance(self.type, types.PointerType):
|
| 495 |
+
raise TypeError("Only pointer constant have address spaces")
|
| 496 |
+
return self.type.addrspace
|
| 497 |
+
|
| 498 |
+
def __eq__(self, other):
|
| 499 |
+
if isinstance(other, Constant):
|
| 500 |
+
return str(self) == str(other)
|
| 501 |
+
else:
|
| 502 |
+
return False
|
| 503 |
+
|
| 504 |
+
def __ne__(self, other):
|
| 505 |
+
return not self.__eq__(other)
|
| 506 |
+
|
| 507 |
+
def __hash__(self):
|
| 508 |
+
return hash(str(self))
|
| 509 |
+
|
| 510 |
+
def __repr__(self):
|
| 511 |
+
return "<ir.Constant type='%s' value=%r>" % (self.type, self.constant)
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
class FormattedConstant(Constant):
|
| 515 |
+
"""
|
| 516 |
+
A constant with an already formatted IR representation.
|
| 517 |
+
"""
|
| 518 |
+
|
| 519 |
+
def __init__(self, typ, constant):
|
| 520 |
+
assert isinstance(constant, str)
|
| 521 |
+
Constant.__init__(self, typ, constant)
|
| 522 |
+
|
| 523 |
+
def _to_string(self):
|
| 524 |
+
return self.constant
|
| 525 |
+
|
| 526 |
+
def _get_reference(self):
|
| 527 |
+
return self.constant
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
class NamedValue(_StrCaching, _StringReferenceCaching, Value):
|
| 531 |
+
"""
|
| 532 |
+
The base class for named values.
|
| 533 |
+
"""
|
| 534 |
+
name_prefix = '%'
|
| 535 |
+
deduplicate_name = True
|
| 536 |
+
|
| 537 |
+
def __init__(self, parent, type, name):
|
| 538 |
+
assert parent is not None
|
| 539 |
+
assert isinstance(type, types.Type)
|
| 540 |
+
self.parent = parent
|
| 541 |
+
self.type = type
|
| 542 |
+
self._set_name(name)
|
| 543 |
+
|
| 544 |
+
def _to_string(self):
|
| 545 |
+
buf = []
|
| 546 |
+
if not isinstance(self.type, types.VoidType):
|
| 547 |
+
buf.append("{0} = ".format(self.get_reference()))
|
| 548 |
+
self.descr(buf)
|
| 549 |
+
return "".join(buf).rstrip()
|
| 550 |
+
|
| 551 |
+
def descr(self, buf):
|
| 552 |
+
raise NotImplementedError
|
| 553 |
+
|
| 554 |
+
def _get_name(self):
|
| 555 |
+
return self._name
|
| 556 |
+
|
| 557 |
+
def _set_name(self, name):
|
| 558 |
+
name = self.parent.scope.register(name,
|
| 559 |
+
deduplicate=self.deduplicate_name)
|
| 560 |
+
self._name = name
|
| 561 |
+
|
| 562 |
+
name = property(_get_name, _set_name)
|
| 563 |
+
|
| 564 |
+
def _get_reference(self):
|
| 565 |
+
name = self.name
|
| 566 |
+
# Quote and escape value name
|
| 567 |
+
if '\\' in name or '"' in name:
|
| 568 |
+
name = name.replace('\\', '\\5c').replace('"', '\\22')
|
| 569 |
+
return '{0}"{1}"'.format(self.name_prefix, name)
|
| 570 |
+
|
| 571 |
+
def __repr__(self):
|
| 572 |
+
return "<ir.%s %r of type '%s'>" % (
|
| 573 |
+
self.__class__.__name__, self.name, self.type)
|
| 574 |
+
|
| 575 |
+
@property
|
| 576 |
+
def function_type(self):
|
| 577 |
+
ty = self.type
|
| 578 |
+
if isinstance(ty, types.PointerType):
|
| 579 |
+
ty = self.type.pointee
|
| 580 |
+
if isinstance(ty, types.FunctionType):
|
| 581 |
+
return ty
|
| 582 |
+
else:
|
| 583 |
+
raise TypeError("Not a function: {0}".format(self.type))
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
class MetaDataString(NamedValue):
|
| 587 |
+
"""
|
| 588 |
+
A metadata string, i.e. a constant string used as a value in a metadata
|
| 589 |
+
node.
|
| 590 |
+
"""
|
| 591 |
+
|
| 592 |
+
def __init__(self, parent, string):
|
| 593 |
+
super(MetaDataString, self).__init__(parent,
|
| 594 |
+
types.MetaDataType(),
|
| 595 |
+
name="")
|
| 596 |
+
self.string = string
|
| 597 |
+
|
| 598 |
+
def descr(self, buf):
|
| 599 |
+
buf += (self.get_reference(), "\n")
|
| 600 |
+
|
| 601 |
+
def _get_reference(self):
|
| 602 |
+
return '!"{0}"'.format(_escape_string(self.string))
|
| 603 |
+
|
| 604 |
+
_to_string = _get_reference
|
| 605 |
+
|
| 606 |
+
def __eq__(self, other):
|
| 607 |
+
if isinstance(other, MetaDataString):
|
| 608 |
+
return self.string == other.string
|
| 609 |
+
else:
|
| 610 |
+
return False
|
| 611 |
+
|
| 612 |
+
def __ne__(self, other):
|
| 613 |
+
return not self.__eq__(other)
|
| 614 |
+
|
| 615 |
+
def __hash__(self):
|
| 616 |
+
return hash(self.string)
|
| 617 |
+
|
| 618 |
+
|
| 619 |
+
class MetaDataArgument(_StrCaching, _StringReferenceCaching, Value):
|
| 620 |
+
"""
|
| 621 |
+
An argument value to a function taking metadata arguments.
|
| 622 |
+
This can wrap any other kind of LLVM value.
|
| 623 |
+
|
| 624 |
+
Do not instantiate directly, Builder.call() will create these
|
| 625 |
+
automatically.
|
| 626 |
+
"""
|
| 627 |
+
|
| 628 |
+
def __init__(self, value):
|
| 629 |
+
assert isinstance(value, Value)
|
| 630 |
+
assert not isinstance(value.type, types.MetaDataType)
|
| 631 |
+
self.type = types.MetaDataType()
|
| 632 |
+
self.wrapped_value = value
|
| 633 |
+
|
| 634 |
+
def _get_reference(self):
|
| 635 |
+
# e.g. "i32* %2"
|
| 636 |
+
return "{0} {1}".format(self.wrapped_value.type,
|
| 637 |
+
self.wrapped_value.get_reference())
|
| 638 |
+
|
| 639 |
+
_to_string = _get_reference
|
| 640 |
+
|
| 641 |
+
|
| 642 |
+
class NamedMetaData(object):
|
| 643 |
+
"""
|
| 644 |
+
A named metadata node.
|
| 645 |
+
|
| 646 |
+
Do not instantiate directly, use Module.add_named_metadata() instead.
|
| 647 |
+
"""
|
| 648 |
+
|
| 649 |
+
def __init__(self, parent):
|
| 650 |
+
self.parent = parent
|
| 651 |
+
self.operands = []
|
| 652 |
+
|
| 653 |
+
def add(self, md):
|
| 654 |
+
self.operands.append(md)
|
| 655 |
+
|
| 656 |
+
|
| 657 |
+
class MDValue(NamedValue):
|
| 658 |
+
"""
|
| 659 |
+
A metadata node's value, consisting of a sequence of elements ("operands").
|
| 660 |
+
|
| 661 |
+
Do not instantiate directly, use Module.add_metadata() instead.
|
| 662 |
+
"""
|
| 663 |
+
name_prefix = '!'
|
| 664 |
+
|
| 665 |
+
def __init__(self, parent, values, name):
|
| 666 |
+
super(MDValue, self).__init__(parent,
|
| 667 |
+
types.MetaDataType(),
|
| 668 |
+
name=name)
|
| 669 |
+
self.operands = tuple(values)
|
| 670 |
+
parent.metadata.append(self)
|
| 671 |
+
|
| 672 |
+
def descr(self, buf):
|
| 673 |
+
operands = []
|
| 674 |
+
for op in self.operands:
|
| 675 |
+
if isinstance(op.type, types.MetaDataType):
|
| 676 |
+
if isinstance(op, Constant) and op.constant is None:
|
| 677 |
+
operands.append("null")
|
| 678 |
+
else:
|
| 679 |
+
operands.append(op.get_reference())
|
| 680 |
+
else:
|
| 681 |
+
operands.append("{0} {1}".format(op.type, op.get_reference()))
|
| 682 |
+
operands = ', '.join(operands)
|
| 683 |
+
buf += ("!{{ {0} }}".format(operands), "\n")
|
| 684 |
+
|
| 685 |
+
def _get_reference(self):
|
| 686 |
+
return self.name_prefix + str(self.name)
|
| 687 |
+
|
| 688 |
+
def __eq__(self, other):
|
| 689 |
+
if isinstance(other, MDValue):
|
| 690 |
+
return self.operands == other.operands
|
| 691 |
+
else:
|
| 692 |
+
return False
|
| 693 |
+
|
| 694 |
+
def __ne__(self, other):
|
| 695 |
+
return not self.__eq__(other)
|
| 696 |
+
|
| 697 |
+
def __hash__(self):
|
| 698 |
+
return hash(self.operands)
|
| 699 |
+
|
| 700 |
+
|
| 701 |
+
class DIToken:
|
| 702 |
+
"""
|
| 703 |
+
A debug information enumeration value that should appear bare in
|
| 704 |
+
the emitted metadata.
|
| 705 |
+
|
| 706 |
+
Use this to wrap known constants, e.g. the DW_* enumerations.
|
| 707 |
+
"""
|
| 708 |
+
|
| 709 |
+
def __init__(self, value):
|
| 710 |
+
self.value = value
|
| 711 |
+
|
| 712 |
+
|
| 713 |
+
class DIValue(NamedValue):
|
| 714 |
+
"""
|
| 715 |
+
A debug information descriptor, containing key-value pairs.
|
| 716 |
+
|
| 717 |
+
Do not instantiate directly, use Module.add_debug_info() instead.
|
| 718 |
+
"""
|
| 719 |
+
name_prefix = '!'
|
| 720 |
+
|
| 721 |
+
def __init__(self, parent, is_distinct, kind, operands, name):
|
| 722 |
+
super(DIValue, self).__init__(parent,
|
| 723 |
+
types.MetaDataType(),
|
| 724 |
+
name=name)
|
| 725 |
+
self.is_distinct = is_distinct
|
| 726 |
+
self.kind = kind
|
| 727 |
+
self.operands = tuple(operands)
|
| 728 |
+
parent.metadata.append(self)
|
| 729 |
+
|
| 730 |
+
def descr(self, buf):
|
| 731 |
+
if self.is_distinct:
|
| 732 |
+
buf += ("distinct ",)
|
| 733 |
+
operands = []
|
| 734 |
+
for key, value in self.operands:
|
| 735 |
+
if value is None:
|
| 736 |
+
strvalue = "null"
|
| 737 |
+
elif value is True:
|
| 738 |
+
strvalue = "true"
|
| 739 |
+
elif value is False:
|
| 740 |
+
strvalue = "false"
|
| 741 |
+
elif isinstance(value, DIToken):
|
| 742 |
+
strvalue = value.value
|
| 743 |
+
elif isinstance(value, str):
|
| 744 |
+
strvalue = '"{}"'.format(_escape_string(value))
|
| 745 |
+
elif isinstance(value, int):
|
| 746 |
+
strvalue = str(value)
|
| 747 |
+
elif isinstance(value, NamedValue):
|
| 748 |
+
strvalue = value.get_reference()
|
| 749 |
+
else:
|
| 750 |
+
raise TypeError("invalid operand type for debug info: %r"
|
| 751 |
+
% (value,))
|
| 752 |
+
operands.append("{0}: {1}".format(key, strvalue))
|
| 753 |
+
operands = ', '.join(operands)
|
| 754 |
+
buf += ("!", self.kind, "(", operands, ")\n")
|
| 755 |
+
|
| 756 |
+
def _get_reference(self):
|
| 757 |
+
return self.name_prefix + str(self.name)
|
| 758 |
+
|
| 759 |
+
def __eq__(self, other):
|
| 760 |
+
if isinstance(other, DIValue):
|
| 761 |
+
return self.is_distinct == other.is_distinct and \
|
| 762 |
+
self.kind == other.kind and \
|
| 763 |
+
self.operands == other.operands
|
| 764 |
+
else:
|
| 765 |
+
return False
|
| 766 |
+
|
| 767 |
+
def __ne__(self, other):
|
| 768 |
+
return not self.__eq__(other)
|
| 769 |
+
|
| 770 |
+
def __hash__(self):
|
| 771 |
+
return hash((self.is_distinct, self.kind, self.operands))
|
| 772 |
+
|
| 773 |
+
|
| 774 |
+
class GlobalValue(NamedValue, _ConstOpMixin, _HasMetadata):
|
| 775 |
+
"""
|
| 776 |
+
A global value.
|
| 777 |
+
"""
|
| 778 |
+
name_prefix = '@'
|
| 779 |
+
deduplicate_name = False
|
| 780 |
+
|
| 781 |
+
def __init__(self, *args, **kwargs):
|
| 782 |
+
super(GlobalValue, self).__init__(*args, **kwargs)
|
| 783 |
+
self.linkage = ''
|
| 784 |
+
self.storage_class = ''
|
| 785 |
+
self.section = ''
|
| 786 |
+
self.metadata = {}
|
| 787 |
+
|
| 788 |
+
|
| 789 |
+
class GlobalVariable(GlobalValue):
|
| 790 |
+
"""
|
| 791 |
+
A global variable.
|
| 792 |
+
"""
|
| 793 |
+
|
| 794 |
+
def __init__(self, module, typ, name, addrspace=0):
|
| 795 |
+
assert isinstance(typ, types.Type)
|
| 796 |
+
super(GlobalVariable, self).__init__(module, typ.as_pointer(addrspace),
|
| 797 |
+
name=name)
|
| 798 |
+
self.value_type = typ
|
| 799 |
+
self.initializer = None
|
| 800 |
+
self.unnamed_addr = False
|
| 801 |
+
self.global_constant = False
|
| 802 |
+
self.addrspace = addrspace
|
| 803 |
+
self.align = None
|
| 804 |
+
self.parent.add_global(self)
|
| 805 |
+
|
| 806 |
+
def descr(self, buf):
|
| 807 |
+
if self.global_constant:
|
| 808 |
+
kind = 'constant'
|
| 809 |
+
else:
|
| 810 |
+
kind = 'global'
|
| 811 |
+
|
| 812 |
+
if not self.linkage:
|
| 813 |
+
# Default to external linkage
|
| 814 |
+
linkage = 'external' if self.initializer is None else ''
|
| 815 |
+
else:
|
| 816 |
+
linkage = self.linkage
|
| 817 |
+
|
| 818 |
+
if linkage:
|
| 819 |
+
buf.append(linkage + " ")
|
| 820 |
+
if self.storage_class:
|
| 821 |
+
buf.append(self.storage_class + " ")
|
| 822 |
+
if self.unnamed_addr:
|
| 823 |
+
buf.append("unnamed_addr ")
|
| 824 |
+
if self.addrspace != 0:
|
| 825 |
+
buf.append('addrspace({0:d}) '.format(self.addrspace))
|
| 826 |
+
|
| 827 |
+
buf.append("{kind} {type}" .format(kind=kind, type=self.value_type))
|
| 828 |
+
|
| 829 |
+
if self.initializer is not None:
|
| 830 |
+
if self.initializer.type != self.value_type:
|
| 831 |
+
raise TypeError("got initializer of type %s "
|
| 832 |
+
"for global value type %s"
|
| 833 |
+
% (self.initializer.type, self.value_type))
|
| 834 |
+
buf.append(" " + self.initializer.get_reference())
|
| 835 |
+
elif linkage not in ('external', 'extern_weak'):
|
| 836 |
+
# emit 'undef' for non-external linkage GV
|
| 837 |
+
buf.append(" " + self.value_type(Undefined).get_reference())
|
| 838 |
+
|
| 839 |
+
if self.section:
|
| 840 |
+
buf.append(", section \"%s\"" % (self.section,))
|
| 841 |
+
|
| 842 |
+
if self.align is not None:
|
| 843 |
+
buf.append(", align %d" % (self.align,))
|
| 844 |
+
|
| 845 |
+
if self.metadata:
|
| 846 |
+
buf.append(self._stringify_metadata(leading_comma=True))
|
| 847 |
+
|
| 848 |
+
buf.append("\n")
|
| 849 |
+
|
| 850 |
+
|
| 851 |
+
class AttributeSet(set):
|
| 852 |
+
"""A set of string attribute.
|
| 853 |
+
Only accept items listed in *_known*.
|
| 854 |
+
|
| 855 |
+
Properties:
|
| 856 |
+
* Iterate in sorted order
|
| 857 |
+
"""
|
| 858 |
+
_known = ()
|
| 859 |
+
|
| 860 |
+
def __init__(self, args=()):
|
| 861 |
+
super().__init__()
|
| 862 |
+
if isinstance(args, str):
|
| 863 |
+
args = [args]
|
| 864 |
+
for name in args:
|
| 865 |
+
self.add(name)
|
| 866 |
+
|
| 867 |
+
def _expand(self, name, typ):
|
| 868 |
+
return name
|
| 869 |
+
|
| 870 |
+
def add(self, name):
|
| 871 |
+
if name not in self._known:
|
| 872 |
+
raise ValueError('unknown attr {!r} for {}'.format(name, self))
|
| 873 |
+
return super(AttributeSet, self).add(name)
|
| 874 |
+
|
| 875 |
+
def _to_list(self, typ):
|
| 876 |
+
return [self._expand(i, typ) for i in sorted(self)]
|
| 877 |
+
|
| 878 |
+
|
| 879 |
+
class FunctionAttributes(AttributeSet):
|
| 880 |
+
_known = frozenset([
|
| 881 |
+
'argmemonly', 'alwaysinline', 'builtin', 'cold',
|
| 882 |
+
'inaccessiblememonly', 'inaccessiblemem_or_argmemonly', 'inlinehint',
|
| 883 |
+
'jumptable', 'minsize', 'naked', 'nobuiltin', 'noduplicate',
|
| 884 |
+
'noimplicitfloat', 'noinline', 'nonlazybind', 'norecurse',
|
| 885 |
+
'noredzone', 'noreturn', 'nounwind', 'optnone', 'optsize',
|
| 886 |
+
'readnone', 'readonly', 'returns_twice', 'sanitize_address',
|
| 887 |
+
'sanitize_memory', 'sanitize_thread', 'ssp',
|
| 888 |
+
'sspreg', 'sspstrong', 'uwtable'])
|
| 889 |
+
|
| 890 |
+
def __init__(self, args=()):
|
| 891 |
+
self._alignstack = 0
|
| 892 |
+
self._personality = None
|
| 893 |
+
super(FunctionAttributes, self).__init__(args)
|
| 894 |
+
|
| 895 |
+
def add(self, name):
|
| 896 |
+
if ((name == 'alwaysinline' and 'noinline' in self) or
|
| 897 |
+
(name == 'noinline' and 'alwaysinline' in self)):
|
| 898 |
+
raise ValueError("Can't have alwaysinline and noinline")
|
| 899 |
+
|
| 900 |
+
super().add(name)
|
| 901 |
+
|
| 902 |
+
@property
|
| 903 |
+
def alignstack(self):
|
| 904 |
+
return self._alignstack
|
| 905 |
+
|
| 906 |
+
@alignstack.setter
|
| 907 |
+
def alignstack(self, val):
|
| 908 |
+
assert val >= 0
|
| 909 |
+
self._alignstack = val
|
| 910 |
+
|
| 911 |
+
@property
|
| 912 |
+
def personality(self):
|
| 913 |
+
return self._personality
|
| 914 |
+
|
| 915 |
+
@personality.setter
|
| 916 |
+
def personality(self, val):
|
| 917 |
+
assert val is None or isinstance(val, GlobalValue)
|
| 918 |
+
self._personality = val
|
| 919 |
+
|
| 920 |
+
def _to_list(self, ret_type):
|
| 921 |
+
attrs = super()._to_list(ret_type)
|
| 922 |
+
if self.alignstack:
|
| 923 |
+
attrs.append('alignstack({0:d})'.format(self.alignstack))
|
| 924 |
+
if self.personality:
|
| 925 |
+
attrs.append('personality {persty} {persfn}'.format(
|
| 926 |
+
persty=self.personality.type,
|
| 927 |
+
persfn=self.personality.get_reference()))
|
| 928 |
+
return attrs
|
| 929 |
+
|
| 930 |
+
|
| 931 |
+
class Function(GlobalValue):
|
| 932 |
+
"""Represent a LLVM Function but does uses a Module as parent.
|
| 933 |
+
Global Values are stored as a set of dependencies (attribute `depends`).
|
| 934 |
+
"""
|
| 935 |
+
|
| 936 |
+
def __init__(self, module, ftype, name):
|
| 937 |
+
assert isinstance(ftype, types.Type)
|
| 938 |
+
super(Function, self).__init__(module, ftype.as_pointer(), name=name)
|
| 939 |
+
self.ftype = ftype
|
| 940 |
+
self.scope = _utils.NameScope()
|
| 941 |
+
self.blocks = []
|
| 942 |
+
self.attributes = FunctionAttributes()
|
| 943 |
+
self.args = tuple([Argument(self, t)
|
| 944 |
+
for t in ftype.args])
|
| 945 |
+
self.return_value = ReturnValue(self, ftype.return_type)
|
| 946 |
+
self.parent.add_global(self)
|
| 947 |
+
self.calling_convention = ''
|
| 948 |
+
|
| 949 |
+
@property
|
| 950 |
+
def module(self):
|
| 951 |
+
return self.parent
|
| 952 |
+
|
| 953 |
+
@property
|
| 954 |
+
def entry_basic_block(self):
|
| 955 |
+
return self.blocks[0]
|
| 956 |
+
|
| 957 |
+
@property
|
| 958 |
+
def basic_blocks(self):
|
| 959 |
+
return self.blocks
|
| 960 |
+
|
| 961 |
+
def append_basic_block(self, name=''):
|
| 962 |
+
blk = Block(parent=self, name=name)
|
| 963 |
+
self.blocks.append(blk)
|
| 964 |
+
return blk
|
| 965 |
+
|
| 966 |
+
def insert_basic_block(self, before, name=''):
|
| 967 |
+
"""Insert block before
|
| 968 |
+
"""
|
| 969 |
+
blk = Block(parent=self, name=name)
|
| 970 |
+
self.blocks.insert(before, blk)
|
| 971 |
+
return blk
|
| 972 |
+
|
| 973 |
+
def descr_prototype(self, buf):
|
| 974 |
+
"""
|
| 975 |
+
Describe the prototype ("head") of the function.
|
| 976 |
+
"""
|
| 977 |
+
state = "define" if self.blocks else "declare"
|
| 978 |
+
ret = self.return_value
|
| 979 |
+
args = ", ".join(str(a) for a in self.args)
|
| 980 |
+
name = self.get_reference()
|
| 981 |
+
attrs = ' ' + ' '.join(self.attributes._to_list(
|
| 982 |
+
self.ftype.return_type)) if self.attributes else ''
|
| 983 |
+
if any(self.args):
|
| 984 |
+
vararg = ', ...' if self.ftype.var_arg else ''
|
| 985 |
+
else:
|
| 986 |
+
vararg = '...' if self.ftype.var_arg else ''
|
| 987 |
+
linkage = self.linkage
|
| 988 |
+
cconv = self.calling_convention
|
| 989 |
+
prefix = " ".join(str(x) for x in [state, linkage, cconv, ret] if x)
|
| 990 |
+
metadata = self._stringify_metadata()
|
| 991 |
+
metadata = ' {}'.format(metadata) if metadata else ''
|
| 992 |
+
section = ' section "{}"'.format(self.section) if self.section else ''
|
| 993 |
+
pt_str = "{prefix} {name}({args}{vararg}){attrs}{section}{metadata}\n"
|
| 994 |
+
prototype = pt_str.format(prefix=prefix, name=name, args=args,
|
| 995 |
+
vararg=vararg, attrs=attrs, section=section,
|
| 996 |
+
metadata=metadata)
|
| 997 |
+
buf.append(prototype)
|
| 998 |
+
|
| 999 |
+
def descr_body(self, buf):
|
| 1000 |
+
"""
|
| 1001 |
+
Describe of the body of the function.
|
| 1002 |
+
"""
|
| 1003 |
+
for blk in self.blocks:
|
| 1004 |
+
blk.descr(buf)
|
| 1005 |
+
|
| 1006 |
+
def descr(self, buf):
|
| 1007 |
+
self.descr_prototype(buf)
|
| 1008 |
+
if self.blocks:
|
| 1009 |
+
buf.append("{\n")
|
| 1010 |
+
self.descr_body(buf)
|
| 1011 |
+
buf.append("}\n")
|
| 1012 |
+
|
| 1013 |
+
def __str__(self):
|
| 1014 |
+
buf = []
|
| 1015 |
+
self.descr(buf)
|
| 1016 |
+
return "".join(buf)
|
| 1017 |
+
|
| 1018 |
+
@property
|
| 1019 |
+
def is_declaration(self):
|
| 1020 |
+
return len(self.blocks) == 0
|
| 1021 |
+
|
| 1022 |
+
|
| 1023 |
+
class ArgumentAttributes(AttributeSet):
|
| 1024 |
+
# List from
|
| 1025 |
+
# https://releases.llvm.org/14.0.0/docs/LangRef.html#parameter-attributes
|
| 1026 |
+
_known = MappingProxyType({
|
| 1027 |
+
# True (emit type),
|
| 1028 |
+
# False (emit name only)
|
| 1029 |
+
'byref': True,
|
| 1030 |
+
'byval': True,
|
| 1031 |
+
'elementtype': True,
|
| 1032 |
+
'immarg': False,
|
| 1033 |
+
'inalloca': True,
|
| 1034 |
+
'inreg': False,
|
| 1035 |
+
'nest': False,
|
| 1036 |
+
'noalias': False,
|
| 1037 |
+
'nocapture': False,
|
| 1038 |
+
'nofree': False,
|
| 1039 |
+
'nonnull': False,
|
| 1040 |
+
'noundef': False,
|
| 1041 |
+
'preallocated': True,
|
| 1042 |
+
'returned': False,
|
| 1043 |
+
'signext': False,
|
| 1044 |
+
'sret': True,
|
| 1045 |
+
'swiftasync': False,
|
| 1046 |
+
'swifterror': False,
|
| 1047 |
+
'swiftself': False,
|
| 1048 |
+
'zeroext': False,
|
| 1049 |
+
})
|
| 1050 |
+
|
| 1051 |
+
def __init__(self, args=()):
|
| 1052 |
+
self._align = 0
|
| 1053 |
+
self._dereferenceable = 0
|
| 1054 |
+
self._dereferenceable_or_null = 0
|
| 1055 |
+
super(ArgumentAttributes, self).__init__(args)
|
| 1056 |
+
|
| 1057 |
+
def _expand(self, name, typ):
|
| 1058 |
+
requires_type = self._known.get(name)
|
| 1059 |
+
if requires_type:
|
| 1060 |
+
return f"{name}({typ.pointee})"
|
| 1061 |
+
else:
|
| 1062 |
+
return name
|
| 1063 |
+
|
| 1064 |
+
@property
|
| 1065 |
+
def align(self):
|
| 1066 |
+
return self._align
|
| 1067 |
+
|
| 1068 |
+
@align.setter
|
| 1069 |
+
def align(self, val):
|
| 1070 |
+
assert isinstance(val, int) and val >= 0
|
| 1071 |
+
self._align = val
|
| 1072 |
+
|
| 1073 |
+
@property
|
| 1074 |
+
def dereferenceable(self):
|
| 1075 |
+
return self._dereferenceable
|
| 1076 |
+
|
| 1077 |
+
@dereferenceable.setter
|
| 1078 |
+
def dereferenceable(self, val):
|
| 1079 |
+
assert isinstance(val, int) and val >= 0
|
| 1080 |
+
self._dereferenceable = val
|
| 1081 |
+
|
| 1082 |
+
@property
|
| 1083 |
+
def dereferenceable_or_null(self):
|
| 1084 |
+
return self._dereferenceable_or_null
|
| 1085 |
+
|
| 1086 |
+
@dereferenceable_or_null.setter
|
| 1087 |
+
def dereferenceable_or_null(self, val):
|
| 1088 |
+
assert isinstance(val, int) and val >= 0
|
| 1089 |
+
self._dereferenceable_or_null = val
|
| 1090 |
+
|
| 1091 |
+
def _to_list(self, typ):
|
| 1092 |
+
attrs = super()._to_list(typ)
|
| 1093 |
+
if self.align:
|
| 1094 |
+
attrs.append('align {0:d}'.format(self.align))
|
| 1095 |
+
if self.dereferenceable:
|
| 1096 |
+
attrs.append('dereferenceable({0:d})'.format(self.dereferenceable))
|
| 1097 |
+
if self.dereferenceable_or_null:
|
| 1098 |
+
dref = 'dereferenceable_or_null({0:d})'
|
| 1099 |
+
attrs.append(dref.format(self.dereferenceable_or_null))
|
| 1100 |
+
return attrs
|
| 1101 |
+
|
| 1102 |
+
|
| 1103 |
+
class _BaseArgument(NamedValue):
|
| 1104 |
+
def __init__(self, parent, typ, name=''):
|
| 1105 |
+
assert isinstance(typ, types.Type)
|
| 1106 |
+
super(_BaseArgument, self).__init__(parent, typ, name=name)
|
| 1107 |
+
self.parent = parent
|
| 1108 |
+
self.attributes = ArgumentAttributes()
|
| 1109 |
+
|
| 1110 |
+
def __repr__(self):
|
| 1111 |
+
return "<ir.%s %r of type %s>" % (self.__class__.__name__, self.name,
|
| 1112 |
+
self.type)
|
| 1113 |
+
|
| 1114 |
+
def add_attribute(self, attr):
|
| 1115 |
+
self.attributes.add(attr)
|
| 1116 |
+
|
| 1117 |
+
|
| 1118 |
+
class Argument(_BaseArgument):
|
| 1119 |
+
"""
|
| 1120 |
+
The specification of a function argument.
|
| 1121 |
+
"""
|
| 1122 |
+
|
| 1123 |
+
def __str__(self):
|
| 1124 |
+
attrs = self.attributes._to_list(self.type)
|
| 1125 |
+
if attrs:
|
| 1126 |
+
return "{0} {1} {2}".format(self.type, ' '.join(attrs),
|
| 1127 |
+
self.get_reference())
|
| 1128 |
+
else:
|
| 1129 |
+
return "{0} {1}".format(self.type, self.get_reference())
|
| 1130 |
+
|
| 1131 |
+
|
| 1132 |
+
class ReturnValue(_BaseArgument):
|
| 1133 |
+
"""
|
| 1134 |
+
The specification of a function's return value.
|
| 1135 |
+
"""
|
| 1136 |
+
|
| 1137 |
+
def __str__(self):
|
| 1138 |
+
attrs = self.attributes._to_list(self.type)
|
| 1139 |
+
if attrs:
|
| 1140 |
+
return "{0} {1}".format(' '.join(attrs), self.type)
|
| 1141 |
+
else:
|
| 1142 |
+
return str(self.type)
|
| 1143 |
+
|
| 1144 |
+
|
| 1145 |
+
class Block(NamedValue):
|
| 1146 |
+
"""
|
| 1147 |
+
A LLVM IR basic block. A basic block is a sequence of
|
| 1148 |
+
instructions whose execution always goes from start to end. That
|
| 1149 |
+
is, a control flow instruction (branch) can only appear as the
|
| 1150 |
+
last instruction, and incoming branches can only jump to the first
|
| 1151 |
+
instruction.
|
| 1152 |
+
"""
|
| 1153 |
+
|
| 1154 |
+
def __init__(self, parent, name=''):
|
| 1155 |
+
super(Block, self).__init__(parent, types.LabelType(), name=name)
|
| 1156 |
+
self.scope = parent.scope
|
| 1157 |
+
self.instructions = []
|
| 1158 |
+
self.terminator = None
|
| 1159 |
+
|
| 1160 |
+
@property
|
| 1161 |
+
def is_terminated(self):
|
| 1162 |
+
return self.terminator is not None
|
| 1163 |
+
|
| 1164 |
+
@property
|
| 1165 |
+
def function(self):
|
| 1166 |
+
return self.parent
|
| 1167 |
+
|
| 1168 |
+
@property
|
| 1169 |
+
def module(self):
|
| 1170 |
+
return self.parent.module
|
| 1171 |
+
|
| 1172 |
+
def descr(self, buf):
|
| 1173 |
+
buf.append("{0}:\n".format(self._format_name()))
|
| 1174 |
+
buf += [" {0}\n".format(instr) for instr in self.instructions]
|
| 1175 |
+
|
| 1176 |
+
def replace(self, old, new):
|
| 1177 |
+
"""Replace an instruction"""
|
| 1178 |
+
if old.type != new.type:
|
| 1179 |
+
raise TypeError("new instruction has a different type")
|
| 1180 |
+
pos = self.instructions.index(old)
|
| 1181 |
+
self.instructions.remove(old)
|
| 1182 |
+
self.instructions.insert(pos, new)
|
| 1183 |
+
|
| 1184 |
+
for bb in self.parent.basic_blocks:
|
| 1185 |
+
for instr in bb.instructions:
|
| 1186 |
+
instr.replace_usage(old, new)
|
| 1187 |
+
|
| 1188 |
+
def _format_name(self):
|
| 1189 |
+
# Per the LLVM Language Ref on identifiers, names matching the following
|
| 1190 |
+
# regex do not need to be quoted: [%@][-a-zA-Z$._][-a-zA-Z$._0-9]*
|
| 1191 |
+
# Otherwise, the identifier must be quoted and escaped.
|
| 1192 |
+
name = self.name
|
| 1193 |
+
if not _SIMPLE_IDENTIFIER_RE.match(name):
|
| 1194 |
+
name = name.replace('\\', '\\5c').replace('"', '\\22')
|
| 1195 |
+
name = '"{0}"'.format(name)
|
| 1196 |
+
return name
|
| 1197 |
+
|
| 1198 |
+
|
| 1199 |
+
class BlockAddress(Value):
|
| 1200 |
+
"""
|
| 1201 |
+
The address of a basic block.
|
| 1202 |
+
"""
|
| 1203 |
+
|
| 1204 |
+
def __init__(self, function, basic_block):
|
| 1205 |
+
assert isinstance(function, Function)
|
| 1206 |
+
assert isinstance(basic_block, Block)
|
| 1207 |
+
self.type = types.IntType(8).as_pointer()
|
| 1208 |
+
self.function = function
|
| 1209 |
+
self.basic_block = basic_block
|
| 1210 |
+
|
| 1211 |
+
def __str__(self):
|
| 1212 |
+
return '{0} {1}'.format(self.type, self.get_reference())
|
| 1213 |
+
|
| 1214 |
+
def get_reference(self):
|
| 1215 |
+
return "blockaddress({0}, {1})".format(
|
| 1216 |
+
self.function.get_reference(),
|
| 1217 |
+
self.basic_block.get_reference())
|
lib/python3.11/site-packages/llvmlite/tests/__init__.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys
|
| 2 |
+
|
| 3 |
+
import unittest
|
| 4 |
+
from unittest import TestCase
|
| 5 |
+
|
| 6 |
+
import faulthandler
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
try:
|
| 10 |
+
# May fail in IPython Notebook with UnsupportedOperation
|
| 11 |
+
faulthandler.enable()
|
| 12 |
+
except BaseException as e:
|
| 13 |
+
msg = "Failed to enable faulthandler due to:\n{err}"
|
| 14 |
+
warnings.warn(msg.format(err=e))
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# Try to inject Numba's unittest customizations.
|
| 18 |
+
from llvmlite.tests import customize
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def discover_tests(startdir):
|
| 22 |
+
"""Discover test under a directory
|
| 23 |
+
"""
|
| 24 |
+
# Avoid importing unittest
|
| 25 |
+
loader = unittest.TestLoader()
|
| 26 |
+
suite = loader.discover(startdir)
|
| 27 |
+
return suite
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def run_tests(suite=None, xmloutput=None, verbosity=1):
|
| 31 |
+
"""
|
| 32 |
+
args
|
| 33 |
+
----
|
| 34 |
+
- suite [TestSuite]
|
| 35 |
+
A suite of all tests to run
|
| 36 |
+
- xmloutput [str or None]
|
| 37 |
+
Path of XML output directory (optional)
|
| 38 |
+
- verbosity [int]
|
| 39 |
+
Verbosity level of tests output
|
| 40 |
+
|
| 41 |
+
Returns the TestResult object after running the test *suite*.
|
| 42 |
+
"""
|
| 43 |
+
if suite is None:
|
| 44 |
+
suite = discover_tests("llvmlite.tests")
|
| 45 |
+
if xmloutput is not None:
|
| 46 |
+
import xmlrunner
|
| 47 |
+
runner = xmlrunner.XMLTestRunner(output=xmloutput)
|
| 48 |
+
else:
|
| 49 |
+
runner = None
|
| 50 |
+
prog = unittest.main(suite=suite, testRunner=runner, exit=False,
|
| 51 |
+
verbosity=verbosity)
|
| 52 |
+
return prog.result
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def main():
|
| 56 |
+
res = run_tests()
|
| 57 |
+
sys.exit(0 if res.wasSuccessful() else 1)
|
lib/python3.11/site-packages/llvmlite/tests/__main__.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from llvmlite.tests import main
|
| 2 |
+
|
| 3 |
+
main()
|
lib/python3.11/site-packages/llvmlite/tests/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (2.3 kB). View file
|
|
|