llvmlite 0.46.0b1__cp312-cp312-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/METADATA +145 -0
  41. llvmlite-0.46.0b1.dist-info/RECORD +45 -0
  42. llvmlite-0.46.0b1.dist-info/WHEEL +5 -0
  43. llvmlite-0.46.0b1.dist-info/licenses/LICENSE +24 -0
  44. llvmlite-0.46.0b1.dist-info/licenses/LICENSE.thirdparty +225 -0
  45. llvmlite-0.46.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,920 @@
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(['convergent', 'noreturn', 'nounwind', 'readonly',
56
+ 'readnone', '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='', typ=None):
435
+ if typ is None:
436
+ if isinstance(ptr, AllocaInstr):
437
+ typ = ptr.allocated_type
438
+ # For compatibility with typed pointers. Eventually this should
439
+ # probably be removed (when typed pointers are fully removed).
440
+ elif not ptr.type.is_opaque:
441
+ typ = ptr.type.pointee
442
+ else:
443
+ raise ValueError("Load lacks type.")
444
+ super(LoadInstr, self).__init__(parent, typ, "load", [ptr], name=name)
445
+ self.align = None
446
+
447
+ def descr(self, buf):
448
+ [val] = self.operands
449
+ if self.align is not None:
450
+ align = ', align %d' % (self.align)
451
+ else:
452
+ align = ''
453
+ buf.append("load {0}, {1} {2}{3}{4}\n".format(
454
+ self.type,
455
+ val.type,
456
+ val.get_reference(),
457
+ align,
458
+ self._stringify_metadata(leading_comma=True),
459
+ ))
460
+
461
+
462
+ class StoreInstr(Instruction):
463
+ def __init__(self, parent, val, ptr):
464
+ super(StoreInstr, self).__init__(parent, types.VoidType(), "store",
465
+ [val, ptr])
466
+
467
+ def descr(self, buf):
468
+ val, ptr = self.operands
469
+ if self.align is not None:
470
+ align = ', align %d' % (self.align)
471
+ else:
472
+ align = ''
473
+ buf.append("store {0} {1}, {2} {3}{4}{5}\n".format(
474
+ val.type,
475
+ val.get_reference(),
476
+ ptr.type,
477
+ ptr.get_reference(),
478
+ align,
479
+ self._stringify_metadata(leading_comma=True),
480
+ ))
481
+
482
+
483
+ class LoadAtomicInstr(Instruction):
484
+ def __init__(self, parent, ptr, ordering, align, name='', typ=None):
485
+ if typ is None:
486
+ if isinstance(ptr, AllocaInstr):
487
+ typ = ptr.allocated_type
488
+ # For compatibility with typed pointers. Eventually this should
489
+ # probably be removed (when typed pointers are fully removed).
490
+ elif not ptr.type.is_opaque:
491
+ typ = ptr.type.pointee
492
+ else:
493
+ raise ValueError("Load atomic lacks type.")
494
+ super(LoadAtomicInstr, self).__init__(parent, typ, "load atomic",
495
+ [ptr], name=name)
496
+ self.ordering = ordering
497
+ self.align = align
498
+
499
+ def descr(self, buf):
500
+ [val] = self.operands
501
+ buf.append("load atomic {0}, {1} {2} {3}, align {4}{5}\n".format(
502
+ self.type,
503
+ val.type,
504
+ val.get_reference(),
505
+ self.ordering,
506
+ self.align,
507
+ self._stringify_metadata(leading_comma=True),
508
+ ))
509
+
510
+
511
+ class StoreAtomicInstr(Instruction):
512
+ def __init__(self, parent, val, ptr, ordering, align):
513
+ super(StoreAtomicInstr, self).__init__(parent, types.VoidType(),
514
+ "store atomic", [val, ptr])
515
+ self.ordering = ordering
516
+ self.align = align
517
+
518
+ def descr(self, buf):
519
+ val, ptr = self.operands
520
+ buf.append("store atomic {0} {1}, {2} {3} {4}, align {5}{6}\n".format(
521
+ val.type,
522
+ val.get_reference(),
523
+ ptr.type,
524
+ ptr.get_reference(),
525
+ self.ordering,
526
+ self.align,
527
+ self._stringify_metadata(leading_comma=True),
528
+ ))
529
+
530
+
531
+ class AllocaInstr(Instruction):
532
+ def __init__(self, parent, typ, count, name):
533
+ operands = [count] if count else ()
534
+ super(AllocaInstr, self).__init__(parent, typ.as_pointer(), "alloca",
535
+ operands, name)
536
+ self.allocated_type = typ
537
+ self.align = None
538
+
539
+ def descr(self, buf):
540
+ buf.append("{0} {1}".format(self.opname, self.allocated_type))
541
+ if self.operands:
542
+ op, = self.operands
543
+ buf.append(", {0} {1}".format(op.type, op.get_reference()))
544
+ if self.align is not None:
545
+ buf.append(", align {0}".format(self.align))
546
+ if self.metadata:
547
+ buf.append(self._stringify_metadata(leading_comma=True))
548
+
549
+
550
+ class GEPInstr(Instruction):
551
+ def __init__(self, parent, ptr, indices, inbounds, name,
552
+ source_etype=None):
553
+ if source_etype is not None:
554
+ typ = ptr.type
555
+ self.source_etype = source_etype
556
+ # For compatibility with typed pointers. Eventually this should
557
+ # probably be removed (when typed pointers are fully removed).
558
+ elif not ptr.type.is_opaque:
559
+ typ = ptr.type
560
+ lasttyp = None
561
+ lastaddrspace = 0
562
+ for i in indices:
563
+ lasttyp, typ = typ, typ.gep(i)
564
+ # inherit the addrspace from the last seen pointer
565
+ if isinstance(lasttyp, types.PointerType):
566
+ lastaddrspace = lasttyp.addrspace
567
+
568
+ if (not isinstance(typ, types.PointerType) and
569
+ isinstance(lasttyp, types.PointerType)):
570
+ typ = lasttyp
571
+ else:
572
+ typ = typ.as_pointer(lastaddrspace)
573
+ self.source_etype = ptr.type.pointee
574
+ else:
575
+ raise ValueError("GEP lacks type.")
576
+ super(GEPInstr, self).__init__(parent, typ, "getelementptr",
577
+ [ptr] + list(indices), name=name)
578
+ self.pointer = ptr
579
+ self.indices = indices
580
+ self.inbounds = inbounds
581
+
582
+ def descr(self, buf):
583
+ indices = ['{0} {1}'.format(i.type, i.get_reference())
584
+ for i in self.indices]
585
+ op = "getelementptr inbounds" if self.inbounds else "getelementptr"
586
+ buf.append("{0} {1}, {2} {3}, {4} {5}\n".format(
587
+ op,
588
+ self.source_etype,
589
+ self.pointer.type,
590
+ self.pointer.get_reference(),
591
+ ', '.join(indices),
592
+ self._stringify_metadata(leading_comma=True),
593
+ ))
594
+
595
+
596
+ class PhiInstr(Instruction):
597
+ def __init__(self, parent, typ, name, flags=()):
598
+ super(PhiInstr, self).__init__(parent, typ, "phi", (), name=name,
599
+ flags=flags)
600
+ self.incomings = []
601
+
602
+ def descr(self, buf):
603
+ incs = ', '.join('[{0}, {1}]'.format(v.get_reference(),
604
+ b.get_reference())
605
+ for v, b in self.incomings)
606
+ buf.append("phi {0} {1} {2} {3}\n".format(
607
+ ' '.join(self.flags),
608
+ self.type,
609
+ incs,
610
+ self._stringify_metadata(leading_comma=True),
611
+ ))
612
+
613
+ def add_incoming(self, value, block):
614
+ assert isinstance(block, Block)
615
+ self.incomings.append((value, block))
616
+
617
+ def replace_usage(self, old, new):
618
+ self.incomings = [((new if val is old else val), blk)
619
+ for (val, blk) in self.incomings]
620
+
621
+
622
+ class ExtractElement(Instruction):
623
+ def __init__(self, parent, vector, index, name=''):
624
+ if not isinstance(vector.type, types.VectorType):
625
+ raise TypeError("vector needs to be of VectorType.")
626
+ if not isinstance(index.type, types.IntType):
627
+ raise TypeError("index needs to be of IntType.")
628
+ typ = vector.type.element
629
+ super(ExtractElement, self).__init__(parent, typ, "extractelement",
630
+ [vector, index], name=name)
631
+
632
+ def descr(self, buf):
633
+ operands = ", ".join("{0} {1}".format(
634
+ op.type, op.get_reference()) for op in self.operands)
635
+ buf.append("{opname} {operands}\n".format(
636
+ opname=self.opname, operands=operands))
637
+
638
+
639
+ class InsertElement(Instruction):
640
+ def __init__(self, parent, vector, value, index, name=''):
641
+ if not isinstance(vector.type, types.VectorType):
642
+ raise TypeError("vector needs to be of VectorType.")
643
+ if not value.type == vector.type.element:
644
+ raise TypeError(
645
+ "value needs to be of type {} not {}.".format(
646
+ vector.type.element, value.type))
647
+ if not isinstance(index.type, types.IntType):
648
+ raise TypeError("index needs to be of IntType.")
649
+ typ = vector.type
650
+ super(InsertElement, self).__init__(parent, typ, "insertelement",
651
+ [vector, value, index], name=name)
652
+
653
+ def descr(self, buf):
654
+ operands = ", ".join("{0} {1}".format(
655
+ op.type, op.get_reference()) for op in self.operands)
656
+ buf.append("{opname} {operands}\n".format(
657
+ opname=self.opname, operands=operands))
658
+
659
+
660
+ class ShuffleVector(Instruction):
661
+ def __init__(self, parent, vector1, vector2, mask, name=''):
662
+ if not isinstance(vector1.type, types.VectorType):
663
+ raise TypeError("vector1 needs to be of VectorType.")
664
+ if vector2 != Undefined:
665
+ if vector2.type != vector1.type:
666
+ raise TypeError("vector2 needs to be " +
667
+ "Undefined or of the same type as vector1.")
668
+ if (not isinstance(mask, Constant) or
669
+ not isinstance(mask.type, types.VectorType) or
670
+ not (isinstance(mask.type.element, types.IntType) and
671
+ mask.type.element.width == 32)):
672
+ raise TypeError("mask needs to be a constant i32 vector.")
673
+ typ = types.VectorType(vector1.type.element, mask.type.count)
674
+ index_range = range(vector1.type.count
675
+ if vector2 == Undefined
676
+ else 2 * vector1.type.count)
677
+ if not all(ii.constant in index_range for ii in mask.constant):
678
+ raise IndexError(
679
+ "mask values need to be in {0}".format(index_range),
680
+ )
681
+ super(ShuffleVector, self).__init__(parent, typ, "shufflevector",
682
+ [vector1, vector2, mask], name=name)
683
+
684
+ def descr(self, buf):
685
+ buf.append("shufflevector {0} {1}\n".format(
686
+ ", ".join("{0} {1}".format(op.type, op.get_reference())
687
+ for op in self.operands),
688
+ self._stringify_metadata(leading_comma=True),
689
+ ))
690
+
691
+
692
+ class ExtractValue(Instruction):
693
+ def __init__(self, parent, agg, 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
+
702
+ super(ExtractValue, self).__init__(parent, typ, "extractvalue",
703
+ [agg], name=name)
704
+
705
+ self.aggregate = agg
706
+ self.indices = indices
707
+
708
+ def descr(self, buf):
709
+ indices = [str(i) for i in self.indices]
710
+
711
+ buf.append("extractvalue {0} {1}, {2} {3}\n".format(
712
+ self.aggregate.type,
713
+ self.aggregate.get_reference(),
714
+ ', '.join(indices),
715
+ self._stringify_metadata(leading_comma=True),
716
+ ))
717
+
718
+
719
+ class InsertValue(Instruction):
720
+ def __init__(self, parent, agg, elem, indices, name=''):
721
+ typ = agg.type
722
+ try:
723
+ for i in indices:
724
+ typ = typ.elements[i]
725
+ except (AttributeError, IndexError):
726
+ raise TypeError("Can't index at %r in %s"
727
+ % (list(indices), agg.type))
728
+ if elem.type != typ:
729
+ raise TypeError("Can only insert %s at %r in %s: got %s"
730
+ % (typ, list(indices), agg.type, elem.type))
731
+ super(InsertValue, self).__init__(parent, agg.type, "insertvalue",
732
+ [agg, elem], name=name)
733
+
734
+ self.aggregate = agg
735
+ self.value = elem
736
+ self.indices = indices
737
+
738
+ def descr(self, buf):
739
+ indices = [str(i) for i in self.indices]
740
+
741
+ buf.append("insertvalue {0} {1}, {2} {3}, {4} {5}\n".format(
742
+ self.aggregate.type, self.aggregate.get_reference(),
743
+ self.value.type, self.value.get_reference(),
744
+ ', '.join(indices),
745
+ self._stringify_metadata(leading_comma=True),
746
+ ))
747
+
748
+
749
+ class Unreachable(Instruction):
750
+ def __init__(self, parent):
751
+ super(Unreachable, self).__init__(parent, types.VoidType(),
752
+ "unreachable", (), name='')
753
+
754
+ def descr(self, buf):
755
+ buf += (self.opname, "\n")
756
+
757
+
758
+ class InlineAsm(object):
759
+ def __init__(self, ftype, asm, constraint, side_effect=False):
760
+ self.type = ftype.return_type
761
+ self.function_type = ftype
762
+ self.asm = asm
763
+ self.constraint = constraint
764
+ self.side_effect = side_effect
765
+
766
+ def descr(self, buf):
767
+ sideeffect = 'sideeffect' if self.side_effect else ''
768
+ fmt = 'asm {sideeffect} "{asm}", "{constraint}"\n'
769
+ buf.append(fmt.format(sideeffect=sideeffect, asm=self.asm,
770
+ constraint=self.constraint))
771
+
772
+ def get_reference(self):
773
+ buf = []
774
+ self.descr(buf)
775
+ return "".join(buf)
776
+
777
+ def __str__(self):
778
+ return "{0} {1}".format(self.type, self.get_reference())
779
+
780
+
781
+ class AtomicRMW(Instruction):
782
+ def __init__(self, parent, op, ptr, val, ordering, name):
783
+ super(AtomicRMW, self).__init__(parent, val.type, "atomicrmw",
784
+ (ptr, val), name=name)
785
+ self.operation = op
786
+ self.ordering = ordering
787
+
788
+ def descr(self, buf):
789
+ ptr, val = self.operands
790
+ fmt = ("atomicrmw {op} {ptrty} {ptr}, {valty} {val} {ordering} "
791
+ "{metadata}\n")
792
+ buf.append(fmt.format(op=self.operation,
793
+ ptrty=ptr.type,
794
+ ptr=ptr.get_reference(),
795
+ valty=val.type,
796
+ val=val.get_reference(),
797
+ ordering=self.ordering,
798
+ metadata=self._stringify_metadata(
799
+ leading_comma=True),
800
+ ))
801
+
802
+
803
+ class CmpXchg(Instruction):
804
+ """This instruction has changed since llvm3.5. It is not compatible with
805
+ older llvm versions.
806
+ """
807
+
808
+ def __init__(self, parent, ptr, cmp, val, ordering, failordering, name):
809
+ outtype = types.LiteralStructType([val.type, types.IntType(1)])
810
+ super(CmpXchg, self).__init__(parent, outtype, "cmpxchg",
811
+ (ptr, cmp, val), name=name)
812
+ self.ordering = ordering
813
+ self.failordering = failordering
814
+
815
+ def descr(self, buf):
816
+ ptr, cmpval, val = self.operands
817
+ fmt = "cmpxchg {ptrty} {ptr}, {ty} {cmp}, {ty} {val} {ordering} " \
818
+ "{failordering} {metadata}\n"
819
+ buf.append(fmt.format(ptrty=ptr.type,
820
+ ptr=ptr.get_reference(),
821
+ ty=cmpval.type,
822
+ cmp=cmpval.get_reference(),
823
+ val=val.get_reference(),
824
+ ordering=self.ordering,
825
+ failordering=self.failordering,
826
+ metadata=self._stringify_metadata(
827
+ leading_comma=True),
828
+ ))
829
+
830
+
831
+ class _LandingPadClause(object):
832
+ def __init__(self, value):
833
+ self.value = value
834
+
835
+ def __str__(self):
836
+ return "{kind} {type} {value}".format(
837
+ kind=self.kind,
838
+ type=self.value.type,
839
+ value=self.value.get_reference())
840
+
841
+
842
+ class CatchClause(_LandingPadClause):
843
+ kind = 'catch'
844
+
845
+
846
+ class FilterClause(_LandingPadClause):
847
+ kind = 'filter'
848
+
849
+ def __init__(self, value):
850
+ assert isinstance(value, Constant)
851
+ assert isinstance(value.type, types.ArrayType)
852
+ super(FilterClause, self).__init__(value)
853
+
854
+
855
+ class LandingPadInstr(Instruction):
856
+ def __init__(self, parent, typ, name='', cleanup=False):
857
+ super(LandingPadInstr, self).__init__(parent, typ, "landingpad", [],
858
+ name=name)
859
+ self.cleanup = cleanup
860
+ self.clauses = []
861
+
862
+ def add_clause(self, clause):
863
+ assert isinstance(clause, _LandingPadClause)
864
+ self.clauses.append(clause)
865
+
866
+ def descr(self, buf):
867
+ fmt = "landingpad {type}{cleanup}{clauses}\n"
868
+ buf.append(fmt.format(type=self.type,
869
+ cleanup=' cleanup' if self.cleanup else '',
870
+ clauses=''.join(["\n {0}".format(clause)
871
+ for clause in self.clauses]),
872
+ ))
873
+
874
+
875
+ class Fence(Instruction):
876
+ """
877
+ The `fence` instruction.
878
+
879
+ As of LLVM 5.0.1:
880
+
881
+ fence [syncscope("<target-scope>")] <ordering> ; yields void
882
+ """
883
+
884
+ VALID_FENCE_ORDERINGS = {"acquire", "release", "acq_rel", "seq_cst"}
885
+
886
+ def __init__(self, parent, ordering, targetscope=None, name=''):
887
+ super(Fence, self).__init__(parent, types.VoidType(), "fence", (),
888
+ name=name)
889
+ if ordering not in self.VALID_FENCE_ORDERINGS:
890
+ msg = "Invalid fence ordering \"{0}\"! Should be one of {1}."
891
+ raise ValueError(msg .format(ordering,
892
+ ", ".join(self.VALID_FENCE_ORDERINGS)))
893
+ self.ordering = ordering
894
+ self.targetscope = targetscope
895
+
896
+ def descr(self, buf):
897
+ if self.targetscope is None:
898
+ syncscope = ""
899
+ else:
900
+ syncscope = 'syncscope("{0}") '.format(self.targetscope)
901
+
902
+ fmt = "fence {syncscope}{ordering}\n"
903
+ buf.append(fmt.format(syncscope=syncscope,
904
+ ordering=self.ordering,
905
+ ))
906
+
907
+
908
+ class Comment(Instruction):
909
+ """
910
+ A line comment.
911
+ """
912
+
913
+ def __init__(self, parent, text):
914
+ super(Comment, self).__init__(parent, types.VoidType(), ";", (),
915
+ name='')
916
+ assert "\n" not in text, "Comment cannot contain new line"
917
+ self.text = text
918
+
919
+ def descr(self, buf):
920
+ buf.append(f"; {self.text}")