llvmlite 0.46.0b1__cp310-cp310-macosx_11_0_universal2.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.

Files changed (45) hide show
  1. llvmlite/__init__.py +11 -0
  2. llvmlite/_version.py +11 -0
  3. llvmlite/binding/__init__.py +18 -0
  4. llvmlite/binding/analysis.py +69 -0
  5. llvmlite/binding/common.py +34 -0
  6. llvmlite/binding/config.py +143 -0
  7. llvmlite/binding/context.py +31 -0
  8. llvmlite/binding/dylib.py +45 -0
  9. llvmlite/binding/executionengine.py +330 -0
  10. llvmlite/binding/ffi.py +395 -0
  11. llvmlite/binding/initfini.py +85 -0
  12. llvmlite/binding/libllvmlite.dylib +0 -0
  13. llvmlite/binding/linker.py +20 -0
  14. llvmlite/binding/module.py +349 -0
  15. llvmlite/binding/newpassmanagers.py +1049 -0
  16. llvmlite/binding/object_file.py +82 -0
  17. llvmlite/binding/options.py +17 -0
  18. llvmlite/binding/orcjit.py +342 -0
  19. llvmlite/binding/targets.py +462 -0
  20. llvmlite/binding/typeref.py +267 -0
  21. llvmlite/binding/value.py +632 -0
  22. llvmlite/ir/__init__.py +11 -0
  23. llvmlite/ir/_utils.py +80 -0
  24. llvmlite/ir/builder.py +1120 -0
  25. llvmlite/ir/context.py +20 -0
  26. llvmlite/ir/instructions.py +920 -0
  27. llvmlite/ir/module.py +256 -0
  28. llvmlite/ir/transforms.py +64 -0
  29. llvmlite/ir/types.py +730 -0
  30. llvmlite/ir/values.py +1217 -0
  31. llvmlite/tests/__init__.py +57 -0
  32. llvmlite/tests/__main__.py +3 -0
  33. llvmlite/tests/customize.py +407 -0
  34. llvmlite/tests/refprune_proto.py +330 -0
  35. llvmlite/tests/test_binding.py +3155 -0
  36. llvmlite/tests/test_ir.py +3095 -0
  37. llvmlite/tests/test_refprune.py +574 -0
  38. llvmlite/tests/test_valuerepr.py +60 -0
  39. llvmlite/utils.py +29 -0
  40. llvmlite-0.46.0b1.dist-info/LICENSE +24 -0
  41. llvmlite-0.46.0b1.dist-info/LICENSE.thirdparty +225 -0
  42. llvmlite-0.46.0b1.dist-info/METADATA +137 -0
  43. llvmlite-0.46.0b1.dist-info/RECORD +45 -0
  44. llvmlite-0.46.0b1.dist-info/WHEEL +5 -0
  45. 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
+ """