llvmlite 0.46.0b1__cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of llvmlite might be problematic. Click here for more details.
- llvmlite/__init__.py +11 -0
- llvmlite/_version.py +11 -0
- llvmlite/binding/__init__.py +18 -0
- llvmlite/binding/analysis.py +69 -0
- llvmlite/binding/common.py +34 -0
- llvmlite/binding/config.py +143 -0
- llvmlite/binding/context.py +31 -0
- llvmlite/binding/dylib.py +45 -0
- llvmlite/binding/executionengine.py +330 -0
- llvmlite/binding/ffi.py +395 -0
- llvmlite/binding/initfini.py +85 -0
- llvmlite/binding/libllvmlite.so +0 -0
- llvmlite/binding/linker.py +20 -0
- llvmlite/binding/module.py +349 -0
- llvmlite/binding/newpassmanagers.py +1049 -0
- llvmlite/binding/object_file.py +82 -0
- llvmlite/binding/options.py +17 -0
- llvmlite/binding/orcjit.py +342 -0
- llvmlite/binding/targets.py +462 -0
- llvmlite/binding/typeref.py +267 -0
- llvmlite/binding/value.py +632 -0
- llvmlite/ir/__init__.py +11 -0
- llvmlite/ir/_utils.py +80 -0
- llvmlite/ir/builder.py +1120 -0
- llvmlite/ir/context.py +20 -0
- llvmlite/ir/instructions.py +920 -0
- llvmlite/ir/module.py +256 -0
- llvmlite/ir/transforms.py +64 -0
- llvmlite/ir/types.py +730 -0
- llvmlite/ir/values.py +1217 -0
- llvmlite/tests/__init__.py +57 -0
- llvmlite/tests/__main__.py +3 -0
- llvmlite/tests/customize.py +407 -0
- llvmlite/tests/refprune_proto.py +330 -0
- llvmlite/tests/test_binding.py +3155 -0
- llvmlite/tests/test_ir.py +3095 -0
- llvmlite/tests/test_refprune.py +574 -0
- llvmlite/tests/test_valuerepr.py +60 -0
- llvmlite/utils.py +29 -0
- llvmlite-0.46.0b1.dist-info/METADATA +145 -0
- llvmlite-0.46.0b1.dist-info/RECORD +45 -0
- llvmlite-0.46.0b1.dist-info/WHEEL +6 -0
- llvmlite-0.46.0b1.dist-info/licenses/LICENSE +24 -0
- llvmlite-0.46.0b1.dist-info/licenses/LICENSE.thirdparty +225 -0
- llvmlite-0.46.0b1.dist-info/top_level.txt +1 -0
llvmlite/ir/builder.py
ADDED
|
@@ -0,0 +1,1120 @@
|
|
|
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, typ=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, typ=typ)
|
|
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 not ptr.type.is_opaque and 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='', typ=None):
|
|
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, typ=typ)
|
|
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='', source_etype=None):
|
|
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
|
+
source_etype=source_etype)
|
|
930
|
+
self._insert(instr)
|
|
931
|
+
return instr
|
|
932
|
+
|
|
933
|
+
# Vector Operations APIs
|
|
934
|
+
|
|
935
|
+
def extract_element(self, vector, idx, name=''):
|
|
936
|
+
"""
|
|
937
|
+
Returns the value at position idx.
|
|
938
|
+
"""
|
|
939
|
+
instr = instructions.ExtractElement(self.block, vector, idx, name=name)
|
|
940
|
+
self._insert(instr)
|
|
941
|
+
return instr
|
|
942
|
+
|
|
943
|
+
def insert_element(self, vector, value, idx, name=''):
|
|
944
|
+
"""
|
|
945
|
+
Returns vector with vector[idx] replaced by value.
|
|
946
|
+
The result is undefined if the idx is larger or equal the vector length.
|
|
947
|
+
"""
|
|
948
|
+
instr = instructions.InsertElement(self.block, vector, value, idx,
|
|
949
|
+
name=name)
|
|
950
|
+
self._insert(instr)
|
|
951
|
+
return instr
|
|
952
|
+
|
|
953
|
+
def shuffle_vector(self, vector1, vector2, mask, name=''):
|
|
954
|
+
"""
|
|
955
|
+
Constructs a permutation of elements from *vector1* and *vector2*.
|
|
956
|
+
Returns a new vector in the same length of *mask*.
|
|
957
|
+
|
|
958
|
+
* *vector1* and *vector2* must have the same element type.
|
|
959
|
+
* *mask* must be a constant vector of integer types.
|
|
960
|
+
"""
|
|
961
|
+
instr = instructions.ShuffleVector(self.block, vector1, vector2, mask,
|
|
962
|
+
name=name)
|
|
963
|
+
self._insert(instr)
|
|
964
|
+
return instr
|
|
965
|
+
|
|
966
|
+
# Aggregate APIs
|
|
967
|
+
|
|
968
|
+
def extract_value(self, agg, idx, name=''):
|
|
969
|
+
"""
|
|
970
|
+
Extract member number *idx* from aggregate.
|
|
971
|
+
"""
|
|
972
|
+
if not isinstance(idx, (tuple, list)):
|
|
973
|
+
idx = [idx]
|
|
974
|
+
instr = instructions.ExtractValue(self.block, agg, idx, name=name)
|
|
975
|
+
self._insert(instr)
|
|
976
|
+
return instr
|
|
977
|
+
|
|
978
|
+
def insert_value(self, agg, value, idx, name=''):
|
|
979
|
+
"""
|
|
980
|
+
Insert *value* into member number *idx* from aggregate.
|
|
981
|
+
"""
|
|
982
|
+
if not isinstance(idx, (tuple, list)):
|
|
983
|
+
idx = [idx]
|
|
984
|
+
instr = instructions.InsertValue(self.block, agg, value, idx, name=name)
|
|
985
|
+
self._insert(instr)
|
|
986
|
+
return instr
|
|
987
|
+
|
|
988
|
+
# PHI APIs
|
|
989
|
+
|
|
990
|
+
def phi(self, typ, name='', flags=()):
|
|
991
|
+
inst = instructions.PhiInstr(self.block, typ, name=name, flags=flags)
|
|
992
|
+
self._insert(inst)
|
|
993
|
+
return inst
|
|
994
|
+
|
|
995
|
+
# Special API
|
|
996
|
+
|
|
997
|
+
def unreachable(self):
|
|
998
|
+
inst = instructions.Unreachable(self.block)
|
|
999
|
+
self._set_terminator(inst)
|
|
1000
|
+
return inst
|
|
1001
|
+
|
|
1002
|
+
def atomic_rmw(self, op, ptr, val, ordering, name=''):
|
|
1003
|
+
inst = instructions.AtomicRMW(
|
|
1004
|
+
self.block, op, ptr, val, ordering, name=name)
|
|
1005
|
+
self._insert(inst)
|
|
1006
|
+
return inst
|
|
1007
|
+
|
|
1008
|
+
def cmpxchg(self, ptr, cmp, val, ordering, failordering=None, name=''):
|
|
1009
|
+
"""
|
|
1010
|
+
Atomic compared-and-set:
|
|
1011
|
+
atomic {
|
|
1012
|
+
old = *ptr
|
|
1013
|
+
success = (old == cmp)
|
|
1014
|
+
if (success)
|
|
1015
|
+
*ptr = val
|
|
1016
|
+
}
|
|
1017
|
+
name = { old, success }
|
|
1018
|
+
|
|
1019
|
+
If failordering is `None`, the value of `ordering` is used.
|
|
1020
|
+
"""
|
|
1021
|
+
failordering = ordering if failordering is None else failordering
|
|
1022
|
+
inst = instructions.CmpXchg(self.block, ptr, cmp, val, ordering,
|
|
1023
|
+
failordering, name=name)
|
|
1024
|
+
self._insert(inst)
|
|
1025
|
+
return inst
|
|
1026
|
+
|
|
1027
|
+
def landingpad(self, typ, name='', cleanup=False):
|
|
1028
|
+
inst = instructions.LandingPadInstr(self.block, typ, name, cleanup)
|
|
1029
|
+
self._insert(inst)
|
|
1030
|
+
return inst
|
|
1031
|
+
|
|
1032
|
+
def assume(self, cond):
|
|
1033
|
+
"""
|
|
1034
|
+
Optimizer hint: assume *cond* is always true.
|
|
1035
|
+
"""
|
|
1036
|
+
fn = self.module.declare_intrinsic("llvm.assume")
|
|
1037
|
+
return self.call(fn, [cond])
|
|
1038
|
+
|
|
1039
|
+
def fence(self, ordering, targetscope=None, name=''):
|
|
1040
|
+
"""
|
|
1041
|
+
Add a memory barrier, preventing certain reorderings of load and/or
|
|
1042
|
+
store accesses with
|
|
1043
|
+
respect to other processors and devices.
|
|
1044
|
+
"""
|
|
1045
|
+
inst = instructions.Fence(self.block, ordering, targetscope, name=name)
|
|
1046
|
+
self._insert(inst)
|
|
1047
|
+
return inst
|
|
1048
|
+
|
|
1049
|
+
def comment(self, text):
|
|
1050
|
+
"""
|
|
1051
|
+
Puts a single-line comment into the generated IR. This will be ignored
|
|
1052
|
+
by LLVM, but can be useful for debugging the output of a compiler. Adds
|
|
1053
|
+
a comment to the source file.
|
|
1054
|
+
|
|
1055
|
+
* *text* is a string that does not contain new line characters.
|
|
1056
|
+
"""
|
|
1057
|
+
inst = instructions.Comment(self.block, text)
|
|
1058
|
+
self._insert(inst)
|
|
1059
|
+
return inst
|
|
1060
|
+
|
|
1061
|
+
@_uniop_intrinsic_int("llvm.bswap")
|
|
1062
|
+
def bswap(self, cond):
|
|
1063
|
+
"""
|
|
1064
|
+
Used to byte swap integer values with an even number of bytes (positive
|
|
1065
|
+
multiple of 16 bits)
|
|
1066
|
+
"""
|
|
1067
|
+
|
|
1068
|
+
@_uniop_intrinsic_int("llvm.bitreverse")
|
|
1069
|
+
def bitreverse(self, cond):
|
|
1070
|
+
"""
|
|
1071
|
+
Reverse the bitpattern of an integer value; for example 0b10110110
|
|
1072
|
+
becomes 0b01101101.
|
|
1073
|
+
"""
|
|
1074
|
+
|
|
1075
|
+
@_uniop_intrinsic_int("llvm.ctpop")
|
|
1076
|
+
def ctpop(self, cond):
|
|
1077
|
+
"""
|
|
1078
|
+
Counts the number of bits set in a value.
|
|
1079
|
+
"""
|
|
1080
|
+
|
|
1081
|
+
@_uniop_intrinsic_with_flag("llvm.ctlz")
|
|
1082
|
+
def ctlz(self, cond, flag):
|
|
1083
|
+
"""
|
|
1084
|
+
Counts leading zero bits in *value*. Boolean *flag* indicates whether
|
|
1085
|
+
the result is defined for ``0``.
|
|
1086
|
+
"""
|
|
1087
|
+
|
|
1088
|
+
@_uniop_intrinsic_with_flag("llvm.cttz")
|
|
1089
|
+
def cttz(self, cond, flag):
|
|
1090
|
+
"""
|
|
1091
|
+
Counts trailing zero bits in *value*. Boolean *flag* indicates whether
|
|
1092
|
+
the result is defined for ``0``.
|
|
1093
|
+
"""
|
|
1094
|
+
|
|
1095
|
+
@_triop_intrinsic("llvm.fma")
|
|
1096
|
+
def fma(self, a, b, c):
|
|
1097
|
+
"""
|
|
1098
|
+
Perform the fused multiply-add operation.
|
|
1099
|
+
"""
|
|
1100
|
+
|
|
1101
|
+
def convert_from_fp16(self, a, to=None, name=''):
|
|
1102
|
+
"""
|
|
1103
|
+
Convert from an i16 to the given FP type
|
|
1104
|
+
"""
|
|
1105
|
+
if not to:
|
|
1106
|
+
raise TypeError("expected a float return type")
|
|
1107
|
+
if not isinstance(to, (types.FloatType, types.DoubleType)):
|
|
1108
|
+
raise TypeError("expected a float type, got %s" % to)
|
|
1109
|
+
if not (isinstance(a.type, types.IntType) and a.type.width == 16):
|
|
1110
|
+
raise TypeError("expected an i16 type, got %s" % a.type)
|
|
1111
|
+
|
|
1112
|
+
opname = 'llvm.convert.from.fp16'
|
|
1113
|
+
fn = self.module.declare_intrinsic(opname, [to])
|
|
1114
|
+
return self.call(fn, [a], name)
|
|
1115
|
+
|
|
1116
|
+
@_uniop_intrinsic_float("llvm.convert.to.fp16")
|
|
1117
|
+
def convert_to_fp16(self, a):
|
|
1118
|
+
"""
|
|
1119
|
+
Convert the given FP number to an i16
|
|
1120
|
+
"""
|