reach-vb HF staff commited on
Commit
c65f48d
1 Parent(s): 8caf5eb

662f462e0f601fcce9aec0bf0aceeab3e0c0e219783432fa02431d37567ec282

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. lib/python3.11/site-packages/llvmlite/binding/__pycache__/ffi.cpython-311.pyc +0 -0
  3. lib/python3.11/site-packages/llvmlite/binding/__pycache__/initfini.cpython-311.pyc +0 -0
  4. lib/python3.11/site-packages/llvmlite/binding/__pycache__/linker.cpython-311.pyc +0 -0
  5. lib/python3.11/site-packages/llvmlite/binding/__pycache__/module.cpython-311.pyc +0 -0
  6. lib/python3.11/site-packages/llvmlite/binding/__pycache__/object_file.cpython-311.pyc +0 -0
  7. lib/python3.11/site-packages/llvmlite/binding/__pycache__/options.cpython-311.pyc +0 -0
  8. lib/python3.11/site-packages/llvmlite/binding/__pycache__/orcjit.cpython-311.pyc +0 -0
  9. lib/python3.11/site-packages/llvmlite/binding/__pycache__/passmanagers.cpython-311.pyc +0 -0
  10. lib/python3.11/site-packages/llvmlite/binding/__pycache__/targets.cpython-311.pyc +0 -0
  11. lib/python3.11/site-packages/llvmlite/binding/__pycache__/transforms.cpython-311.pyc +0 -0
  12. lib/python3.11/site-packages/llvmlite/binding/__pycache__/value.cpython-311.pyc +0 -0
  13. lib/python3.11/site-packages/llvmlite/binding/analysis.py +69 -0
  14. lib/python3.11/site-packages/llvmlite/binding/common.py +34 -0
  15. lib/python3.11/site-packages/llvmlite/binding/context.py +29 -0
  16. lib/python3.11/site-packages/llvmlite/binding/dylib.py +45 -0
  17. lib/python3.11/site-packages/llvmlite/binding/executionengine.py +322 -0
  18. lib/python3.11/site-packages/llvmlite/binding/ffi.py +388 -0
  19. lib/python3.11/site-packages/llvmlite/binding/initfini.py +73 -0
  20. lib/python3.11/site-packages/llvmlite/binding/libllvmlite.dylib +3 -0
  21. lib/python3.11/site-packages/llvmlite/binding/linker.py +20 -0
  22. lib/python3.11/site-packages/llvmlite/binding/module.py +349 -0
  23. lib/python3.11/site-packages/llvmlite/binding/object_file.py +82 -0
  24. lib/python3.11/site-packages/llvmlite/binding/options.py +17 -0
  25. lib/python3.11/site-packages/llvmlite/binding/orcjit.py +342 -0
  26. lib/python3.11/site-packages/llvmlite/binding/passmanagers.py +923 -0
  27. lib/python3.11/site-packages/llvmlite/binding/targets.py +450 -0
  28. lib/python3.11/site-packages/llvmlite/binding/transforms.py +151 -0
  29. lib/python3.11/site-packages/llvmlite/binding/value.py +624 -0
  30. lib/python3.11/site-packages/llvmlite/ir/__init__.py +11 -0
  31. lib/python3.11/site-packages/llvmlite/ir/__pycache__/__init__.cpython-311.pyc +0 -0
  32. lib/python3.11/site-packages/llvmlite/ir/__pycache__/_utils.cpython-311.pyc +0 -0
  33. lib/python3.11/site-packages/llvmlite/ir/__pycache__/builder.cpython-311.pyc +0 -0
  34. lib/python3.11/site-packages/llvmlite/ir/__pycache__/context.cpython-311.pyc +0 -0
  35. lib/python3.11/site-packages/llvmlite/ir/__pycache__/instructions.cpython-311.pyc +0 -0
  36. lib/python3.11/site-packages/llvmlite/ir/__pycache__/module.cpython-311.pyc +0 -0
  37. lib/python3.11/site-packages/llvmlite/ir/__pycache__/transforms.cpython-311.pyc +0 -0
  38. lib/python3.11/site-packages/llvmlite/ir/__pycache__/types.cpython-311.pyc +0 -0
  39. lib/python3.11/site-packages/llvmlite/ir/__pycache__/values.cpython-311.pyc +0 -0
  40. lib/python3.11/site-packages/llvmlite/ir/_utils.py +80 -0
  41. lib/python3.11/site-packages/llvmlite/ir/builder.py +1119 -0
  42. lib/python3.11/site-packages/llvmlite/ir/context.py +20 -0
  43. lib/python3.11/site-packages/llvmlite/ir/instructions.py +893 -0
  44. lib/python3.11/site-packages/llvmlite/ir/module.py +246 -0
  45. lib/python3.11/site-packages/llvmlite/ir/transforms.py +64 -0
  46. lib/python3.11/site-packages/llvmlite/ir/types.py +614 -0
  47. lib/python3.11/site-packages/llvmlite/ir/values.py +1217 -0
  48. lib/python3.11/site-packages/llvmlite/tests/__init__.py +57 -0
  49. lib/python3.11/site-packages/llvmlite/tests/__main__.py +3 -0
  50. 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