1import contextlib
2import functools
3
4from 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
16def _binop(opname, cls=instructions.Instruction):
17    def wrap(fn):
18        @functools.wraps(fn)
19        def wrapped(self, lhs, rhs, name='', flags=()):
20            if lhs.type != rhs.type:
21                raise ValueError("Operands must be the same type, got (%s, %s)"
22                                 % (lhs.type, rhs.type))
23            instr = cls(self.block, lhs.type, opname, (lhs, rhs), name, flags)
24            self._insert(instr)
25            return instr
26
27        return wrapped
28
29    return wrap
30
31
32def _binop_with_overflow(opname, cls=instructions.Instruction):
33    def wrap(fn):
34        @functools.wraps(fn)
35        def wrapped(self, lhs, rhs, name=''):
36            if lhs.type != rhs.type:
37                raise ValueError("Operands must be the same type, got (%s, %s)"
38                                 % (lhs.type, rhs.type))
39            ty = lhs.type
40            if not isinstance(ty, types.IntType):
41                raise TypeError("expected an integer type, got %s" % (ty,))
42            bool_ty = types.IntType(1)
43
44            mod = self.module
45            fnty = types.FunctionType(types.LiteralStructType([ty, bool_ty]),
46                                      [ty, ty])
47            fn = mod.declare_intrinsic("llvm.%s.with.overflow" % (opname,),
48                                       [ty], fnty)
49            ret = self.call(fn, [lhs, rhs], name=name)
50            return ret
51
52        return wrapped
53
54    return wrap
55
56
57def _uniop(opname, cls=instructions.Instruction):
58    def wrap(fn):
59        @functools.wraps(fn)
60        def wrapped(self, operand, name=''):
61            instr = cls(self.block, operand.type, opname, [operand], name)
62            self._insert(instr)
63            return instr
64
65        return wrapped
66
67    return wrap
68
69
70def _uniop_intrinsic_int(opname):
71    def wrap(fn):
72        @functools.wraps(fn)
73        def wrapped(self, operand, name=''):
74            if not isinstance(operand.type, types.IntType):
75                raise TypeError(
76                    "expected an integer type, got %s" %
77                    operand.type)
78            fn = self.module.declare_intrinsic(opname, [operand.type])
79            return self.call(fn, [operand], name)
80
81        return wrapped
82
83    return wrap
84
85
86def _uniop_intrinsic_float(opname):
87    def wrap(fn):
88        @functools.wraps(fn)
89        def wrapped(self, operand, name=''):
90            if not isinstance(
91                    operand.type, (types.FloatType, types.DoubleType)):
92                raise TypeError("expected a float type, got %s" % operand.type)
93            fn = self.module.declare_intrinsic(opname, [operand.type])
94            return self.call(fn, [operand], name)
95
96        return wrapped
97
98    return wrap
99
100
101def _uniop_intrinsic_with_flag(opname):
102    def wrap(fn):
103        @functools.wraps(fn)
104        def wrapped(self, operand, flag, name=''):
105            if not isinstance(operand.type, types.IntType):
106                raise TypeError(
107                    "expected an integer type, got %s" %
108                    operand.type)
109            if not(isinstance(flag.type, types.IntType) and
110                   flag.type.width == 1):
111                raise TypeError("expected an i1 type, got %s" % flag.type)
112            fn = self.module.declare_intrinsic(
113                opname, [operand.type, flag.type])
114            return self.call(fn, [operand, flag], name)
115
116        return wrapped
117
118    return wrap
119
120
121def _triop_intrinsic(opname):
122    def wrap(fn):
123        @functools.wraps(fn)
124        def wrapped(self, a, b, c, name=''):
125            if a.type != b.type or b.type != c.type:
126                raise TypeError(
127                    "expected types to be the same, got %s, %s, %s" % (
128                        a.type,
129                        b.type,
130                        c.type))
131            elif not isinstance(
132                    a.type,
133                    (types.HalfType, types.FloatType, types.DoubleType)):
134                raise TypeError(
135                    "expected an floating point type, got %s" %
136                    a.type)
137            fn = self.module.declare_intrinsic(opname, [a.type, b.type, c.type])
138            return self.call(fn, [a, b, c], name)
139
140        return wrapped
141
142    return wrap
143
144
145def _castop(opname, cls=instructions.CastInstr):
146    def wrap(fn):
147        @functools.wraps(fn)
148        def wrapped(self, val, typ, name=''):
149            if val.type == typ:
150                return val
151            instr = cls(self.block, opname, val, typ, name)
152            self._insert(instr)
153            return instr
154
155        return wrapped
156
157    return wrap
158
159
160def _label_suffix(label, suffix):
161    """Returns (label + suffix) or a truncated version if it's too long.
162    Parameters
163    ----------
164    label : str
165        Label name
166    suffix : str
167        Label suffix
168    """
169    if len(label) > 50:
170        nhead = 25
171        return ''.join([label[:nhead], '..', suffix])
172    else:
173        return label + suffix
174
175
176class IRBuilder(object):
177    def __init__(self, block=None):
178        self._block = block
179        self._anchor = len(block.instructions) if block else 0
180        self.debug_metadata = None
181
182    @property
183    def block(self):
184        """
185        The current basic block.
186        """
187        return self._block
188
189    basic_block = block
190
191    @property
192    def function(self):
193        """
194        The current function.
195        """
196        return self.block.parent
197
198    @property
199    def module(self):
200        """
201        The current module.
202        """
203        return self.block.parent.module
204
205    def position_before(self, instr):
206        """
207        Position immediately before the given instruction.  The current block
208        is also changed to the instruction's basic block.
209        """
210        self._block = instr.parent
211        self._anchor = self._block.instructions.index(instr)
212
213    def position_after(self, instr):
214        """
215        Position immediately after the given instruction.  The current block
216        is also changed to the instruction's basic block.
217        """
218        self._block = instr.parent
219        self._anchor = self._block.instructions.index(instr) + 1
220
221    def position_at_start(self, block):
222        """
223        Position at the start of the basic *block*.
224        """
225        self._block = block
226        self._anchor = 0
227
228    def position_at_end(self, block):
229        """
230        Position at the end of the basic *block*.
231        """
232        self._block = block
233        self._anchor = len(block.instructions)
234
235    def append_basic_block(self, name=''):
236        """
237        Append a basic block, with the given optional *name*, to the current
238        function.  The current block is not changed.  The new block is returned.
239        """
240        return self.function.append_basic_block(name)
241
242    def remove(self, instr):
243        """Remove the given instruction."""
244        idx = self._block.instructions.index(instr)
245        del self._block.instructions[idx]
246        if self._block.terminator == instr:
247            self._block.terminator = None
248        if self._anchor > idx:
249            self._anchor -= 1
250
251    @contextlib.contextmanager
252    def goto_block(self, block):
253        """
254        A context manager which temporarily positions the builder at the end
255        of basic block *bb* (but before any terminator).
256        """
257        old_block = self.basic_block
258        term = block.terminator
259        if term is not None:
260            self.position_before(term)
261        else:
262            self.position_at_end(block)
263        try:
264            yield
265        finally:
266            self.position_at_end(old_block)
267
268    @contextlib.contextmanager
269    def goto_entry_block(self):
270        """
271        A context manager which temporarily positions the builder at the
272        end of the function's entry block.
273        """
274        with self.goto_block(self.function.entry_basic_block):
275            yield
276
277    @contextlib.contextmanager
278    def _branch_helper(self, bbenter, bbexit):
279        self.position_at_end(bbenter)
280        yield bbexit
281        if self.basic_block.terminator is None:
282            self.branch(bbexit)
283
284    @contextlib.contextmanager
285    def if_then(self, pred, likely=None):
286        """
287        A context manager which sets up a conditional basic block based
288        on the given predicate (a i1 value).  If the conditional block
289        is not explicitly terminated, a branch will be added to the next
290        block.
291        If *likely* is given, its boolean value indicates whether the
292        predicate is likely to be true or not, and metadata is issued
293        for LLVM's optimizers to account for that.
294        """
295        bb = self.basic_block
296        bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
297        bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
298        br = self.cbranch(pred, bbif, bbend)
299        if likely is not None:
300            br.set_weights([99, 1] if likely else [1, 99])
301
302        with self._branch_helper(bbif, bbend):
303            yield bbend
304
305        self.position_at_end(bbend)
306
307    @contextlib.contextmanager
308    def if_else(self, pred, likely=None):
309        """
310        A context manager which sets up two conditional basic blocks based
311        on the given predicate (a i1 value).
312        A tuple of context managers is yield'ed.  Each context manager
313        acts as a if_then() block.
314        *likely* has the same meaning as in if_then().
315
316        Typical use::
317            with builder.if_else(pred) as (then, otherwise):
318                with then:
319                    # emit instructions for when the predicate is true
320                with otherwise:
321                    # emit instructions for when the predicate is false
322        """
323        bb = self.basic_block
324        bbif = self.append_basic_block(name=_label_suffix(bb.name, '.if'))
325        bbelse = self.append_basic_block(name=_label_suffix(bb.name, '.else'))
326        bbend = self.append_basic_block(name=_label_suffix(bb.name, '.endif'))
327        br = self.cbranch(pred, bbif, bbelse)
328        if likely is not None:
329            br.set_weights([99, 1] if likely else [1, 99])
330
331        then = self._branch_helper(bbif, bbend)
332        otherwise = self._branch_helper(bbelse, bbend)
333
334        yield then, otherwise
335
336        self.position_at_end(bbend)
337
338    def _insert(self, instr):
339        if self.debug_metadata is not None and 'dbg' not in instr.metadata:
340            instr.metadata['dbg'] = self.debug_metadata
341        self._block.instructions.insert(self._anchor, instr)
342        self._anchor += 1
343
344    def _set_terminator(self, term):
345        assert not self.block.is_terminated
346        self._insert(term)
347        self.block.terminator = term
348        return term
349
350    #
351    # Arithmetic APIs
352    #
353
354    @_binop('shl')
355    def shl(self, lhs, rhs, name=''):
356        """
357        Left integer shift:
358            name = lhs << rhs
359        """
360
361    @_binop('lshr')
362    def lshr(self, lhs, rhs, name=''):
363        """
364        Logical (unsigned) right integer shift:
365            name = lhs >> rhs
366        """
367
368    @_binop('ashr')
369    def ashr(self, lhs, rhs, name=''):
370        """
371        Arithmetic (signed) right integer shift:
372            name = lhs >> rhs
373        """
374
375    @_binop('add')
376    def add(self, lhs, rhs, name=''):
377        """
378        Integer addition:
379            name = lhs + rhs
380        """
381
382    @_binop('fadd')
383    def fadd(self, lhs, rhs, name=''):
384        """
385        Floating-point addition:
386            name = lhs + rhs
387        """
388
389    @_binop('sub')
390    def sub(self, lhs, rhs, name=''):
391        """
392        Integer subtraction:
393            name = lhs - rhs
394        """
395
396    @_binop('fsub')
397    def fsub(self, lhs, rhs, name=''):
398        """
399        Floating-point subtraction:
400            name = lhs - rhs
401        """
402
403    @_binop('mul')
404    def mul(self, lhs, rhs, name=''):
405        """
406        Integer multiplication:
407            name = lhs * rhs
408        """
409
410    @_binop('fmul')
411    def fmul(self, lhs, rhs, name=''):
412        """
413        Floating-point multiplication:
414            name = lhs * rhs
415        """
416
417    @_binop('udiv')
418    def udiv(self, lhs, rhs, name=''):
419        """
420        Unsigned integer division:
421            name = lhs / rhs
422        """
423
424    @_binop('sdiv')
425    def sdiv(self, lhs, rhs, name=''):
426        """
427        Signed integer division:
428            name = lhs / rhs
429        """
430
431    @_binop('fdiv')
432    def fdiv(self, lhs, rhs, name=''):
433        """
434        Floating-point division:
435            name = lhs / rhs
436        """
437
438    @_binop('urem')
439    def urem(self, lhs, rhs, name=''):
440        """
441        Unsigned integer remainder:
442            name = lhs % rhs
443        """
444
445    @_binop('srem')
446    def srem(self, lhs, rhs, name=''):
447        """
448        Signed integer remainder:
449            name = lhs % rhs
450        """
451
452    @_binop('frem')
453    def frem(self, lhs, rhs, name=''):
454        """
455        Floating-point remainder:
456            name = lhs % rhs
457        """
458
459    @_binop('or')
460    def or_(self, lhs, rhs, name=''):
461        """
462        Bitwise integer OR:
463            name = lhs | rhs
464        """
465
466    @_binop('and')
467    def and_(self, lhs, rhs, name=''):
468        """
469        Bitwise integer AND:
470            name = lhs & rhs
471        """
472
473    @_binop('xor')
474    def xor(self, lhs, rhs, name=''):
475        """
476        Bitwise integer XOR:
477            name = lhs ^ rhs
478        """
479
480    @_binop_with_overflow('sadd')
481    def sadd_with_overflow(self, lhs, rhs, name=''):
482        """
483        Signed integer addition with overflow:
484            name = {result, overflow bit} = lhs + rhs
485        """
486
487    @_binop_with_overflow('smul')
488    def smul_with_overflow(self, lhs, rhs, name=''):
489        """
490        Signed integer multiplication with overflow:
491            name = {result, overflow bit} = lhs * rhs
492        """
493
494    @_binop_with_overflow('ssub')
495    def ssub_with_overflow(self, lhs, rhs, name=''):
496        """
497        Signed integer subtraction with overflow:
498            name = {result, overflow bit} = lhs - rhs
499        """
500
501    @_binop_with_overflow('uadd')
502    def uadd_with_overflow(self, lhs, rhs, name=''):
503        """
504        Unsigned integer addition with overflow:
505            name = {result, overflow bit} = lhs + rhs
506        """
507
508    @_binop_with_overflow('umul')
509    def umul_with_overflow(self, lhs, rhs, name=''):
510        """
511        Unsigned integer multiplication with overflow:
512            name = {result, overflow bit} = lhs * rhs
513        """
514
515    @_binop_with_overflow('usub')
516    def usub_with_overflow(self, lhs, rhs, name=''):
517        """
518        Unsigned integer subtraction with overflow:
519            name = {result, overflow bit} = lhs - rhs
520        """
521
522    #
523    # Unary APIs
524    #
525
526    def not_(self, value, name=''):
527        """
528        Bitwise integer complement:
529            name = ~value
530        """
531        if isinstance(value.type, types.VectorType):
532            rhs = values.Constant(value.type, (-1,) * value.type.count)
533        else:
534            rhs = values.Constant(value.type, -1)
535        return self.xor(value, rhs, name=name)
536
537    def neg(self, value, name=''):
538        """
539        Integer negative:
540            name = -value
541        """
542        return self.sub(values.Constant(value.type, 0), value, name=name)
543
544    #
545    # Comparison APIs
546    #
547
548    def _icmp(self, prefix, cmpop, lhs, rhs, name):
549        try:
550            op = _CMP_MAP[cmpop]
551        except KeyError:
552            raise ValueError("invalid comparison %r for icmp" % (cmpop,))
553        if cmpop not in ('==', '!='):
554            op = prefix + op
555        instr = instructions.ICMPInstr(self.block, op, lhs, rhs, name=name)
556        self._insert(instr)
557        return instr
558
559    def icmp_signed(self, cmpop, lhs, rhs, name=''):
560        """
561        Signed integer comparison:
562            name = lhs <cmpop> rhs
563
564        where cmpop can be '==', '!=', '<', '<=', '>', '>='
565        """
566        return self._icmp('s', cmpop, lhs, rhs, name)
567
568    def icmp_unsigned(self, cmpop, lhs, rhs, name=''):
569        """
570        Unsigned integer (or pointer) comparison:
571            name = lhs <cmpop> rhs
572
573        where cmpop can be '==', '!=', '<', '<=', '>', '>='
574        """
575        return self._icmp('u', cmpop, lhs, rhs, name)
576
577    def fcmp_ordered(self, cmpop, lhs, rhs, name='', flags=[]):
578        """
579        Floating-point ordered comparison:
580            name = lhs <cmpop> rhs
581
582        where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
583        """
584        if cmpop in _CMP_MAP:
585            op = 'o' + _CMP_MAP[cmpop]
586        else:
587            op = cmpop
588        instr = instructions.FCMPInstr(
589            self.block, op, lhs, rhs, name=name, flags=flags)
590        self._insert(instr)
591        return instr
592
593    def fcmp_unordered(self, cmpop, lhs, rhs, name='', flags=[]):
594        """
595        Floating-point unordered comparison:
596            name = lhs <cmpop> rhs
597
598        where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
599        """
600        if cmpop in _CMP_MAP:
601            op = 'u' + _CMP_MAP[cmpop]
602        else:
603            op = cmpop
604        instr = instructions.FCMPInstr(
605            self.block, op, lhs, rhs, name=name, flags=flags)
606        self._insert(instr)
607        return instr
608
609    def select(self, cond, lhs, rhs, name=''):
610        """
611        Ternary select operator:
612            name = cond ? lhs : rhs
613        """
614        instr = instructions.SelectInstr(self.block, cond, lhs, rhs, name=name)
615        self._insert(instr)
616        return instr
617
618    #
619    # Cast APIs
620    #
621
622    @_castop('trunc')
623    def trunc(self, value, typ, name=''):
624        """
625        Truncating integer downcast to a smaller type:
626            name = (typ) value
627        """
628
629    @_castop('zext')
630    def zext(self, value, typ, name=''):
631        """
632        Zero-extending integer upcast to a larger type:
633            name = (typ) value
634        """
635
636    @_castop('sext')
637    def sext(self, value, typ, name=''):
638        """
639        Sign-extending integer upcast to a larger type:
640            name = (typ) value
641        """
642
643    @_castop('fptrunc')
644    def fptrunc(self, value, typ, name=''):
645        """
646        Floating-point downcast to a less precise type:
647            name = (typ) value
648        """
649
650    @_castop('fpext')
651    def fpext(self, value, typ, name=''):
652        """
653        Floating-point upcast to a more precise type:
654            name = (typ) value
655        """
656
657    @_castop('bitcast')
658    def bitcast(self, value, typ, name=''):
659        """
660        Pointer cast to a different pointer type:
661            name = (typ) value
662        """
663
664    @_castop('addrspacecast')
665    def addrspacecast(self, value, typ, name=''):
666        """
667        Pointer cast to a different address space:
668            name = (typ) value
669        """
670
671    @_castop('fptoui')
672    def fptoui(self, value, typ, name=''):
673        """
674        Convert floating-point to unsigned integer:
675            name = (typ) value
676        """
677
678    @_castop('uitofp')
679    def uitofp(self, value, typ, name=''):
680        """
681        Convert unsigned integer to floating-point:
682            name = (typ) value
683        """
684
685    @_castop('fptosi')
686    def fptosi(self, value, typ, name=''):
687        """
688        Convert floating-point to signed integer:
689            name = (typ) value
690        """
691
692    @_castop('sitofp')
693    def sitofp(self, value, typ, name=''):
694        """
695        Convert signed integer to floating-point:
696            name = (typ) value
697        """
698
699    @_castop('ptrtoint')
700    def ptrtoint(self, value, typ, name=''):
701        """
702        Cast pointer to integer:
703            name = (typ) value
704        """
705
706    @_castop('inttoptr')
707    def inttoptr(self, value, typ, name=''):
708        """
709        Cast integer to pointer:
710            name = (typ) value
711        """
712
713    #
714    # Memory APIs
715    #
716
717    def alloca(self, typ, size=None, name=''):
718        """
719        Stack-allocate a slot for *size* elements of the given type.
720        (default one element)
721        """
722        if size is None:
723            pass
724        elif isinstance(size, (values.Value, values.Constant)):
725            assert isinstance(size.type, types.IntType)
726        else:
727            # If it is not a Value instance,
728            # assume to be a Python integer.
729            size = values.Constant(types.IntType(32), size)
730
731        al = instructions.AllocaInstr(self.block, typ, size, name)
732        self._insert(al)
733        return al
734
735    def load(self, ptr, name='', align=None):
736        """
737        Load value from pointer, with optional guaranteed alignment:
738            name = *ptr
739        """
740        if not isinstance(ptr.type, types.PointerType):
741            msg = "cannot load from value of type %s (%r): not a pointer"
742            raise TypeError(msg % (ptr.type, str(ptr)))
743        ld = instructions.LoadInstr(self.block, ptr, name)
744        ld.align = align
745        self._insert(ld)
746        return ld
747
748    def store(self, value, ptr, align=None):
749        """
750        Store value to pointer, with optional guaranteed alignment:
751            *ptr = name
752        """
753        if not isinstance(ptr.type, types.PointerType):
754            msg = "cannot store to value of type %s (%r): not a pointer"
755            raise TypeError(msg % (ptr.type, str(ptr)))
756        if ptr.type.pointee != value.type:
757            raise TypeError("cannot store %s to %s: mismatching types"
758                            % (value.type, ptr.type))
759        st = instructions.StoreInstr(self.block, value, ptr)
760        st.align = align
761        self._insert(st)
762        return st
763
764    def load_atomic(self, ptr, ordering, align, name=''):
765        """
766        Load value from pointer, with optional guaranteed alignment:
767            name = *ptr
768        """
769        if not isinstance(ptr.type, types.PointerType):
770            msg = "cannot load from value of type %s (%r): not a pointer"
771            raise TypeError(msg % (ptr.type, str(ptr)))
772        ld = instructions.LoadAtomicInstr(
773            self.block, ptr, ordering, align, name)
774        self._insert(ld)
775        return ld
776
777    def store_atomic(self, value, ptr, ordering, align):
778        """
779        Store value to pointer, with optional guaranteed alignment:
780            *ptr = name
781        """
782        if not isinstance(ptr.type, types.PointerType):
783            msg = "cannot store to value of type %s (%r): not a pointer"
784            raise TypeError(msg % (ptr.type, str(ptr)))
785        if ptr.type.pointee != value.type:
786            raise TypeError("cannot store %s to %s: mismatching types"
787                            % (value.type, ptr.type))
788        st = instructions.StoreAtomicInstr(
789            self.block, value, ptr, ordering, align)
790        self._insert(st)
791        return st
792
793    #
794    # Terminators APIs
795    #
796
797    def switch(self, value, default):
798        """
799        Create a switch-case with a single *default* target.
800        """
801        swt = instructions.SwitchInstr(self.block, 'switch', value, default)
802        self._set_terminator(swt)
803        return swt
804
805    def branch(self, target):
806        """
807        Unconditional branch to *target*.
808        """
809        br = instructions.Branch(self.block, "br", [target])
810        self._set_terminator(br)
811        return br
812
813    def cbranch(self, cond, truebr, falsebr):
814        """
815        Conditional branch to *truebr* if *cond* is true, else to *falsebr*.
816        """
817        br = instructions.ConditionalBranch(self.block, "br",
818                                            [cond, truebr, falsebr])
819        self._set_terminator(br)
820        return br
821
822    def branch_indirect(self, addr):
823        """
824        Indirect branch to target *addr*.
825        """
826        br = instructions.IndirectBranch(self.block, "indirectbr", addr)
827        self._set_terminator(br)
828        return br
829
830    def ret_void(self):
831        """
832        Return from function without a value.
833        """
834        return self._set_terminator(
835            instructions.Ret(self.block, "ret void"))
836
837    def ret(self, value):
838        """
839        Return from function with the given *value*.
840        """
841        return self._set_terminator(
842            instructions.Ret(self.block, "ret", value))
843
844    def resume(self, landingpad):
845        """
846        Resume an in-flight exception.
847        """
848        br = instructions.Branch(self.block, "resume", [landingpad])
849        self._set_terminator(br)
850        return br
851
852    # Call APIs
853
854    def call(self, fn, args, name='', cconv=None, tail=False, fastmath=()):
855        """
856        Call function *fn* with *args*:
857            name = fn(args...)
858        """
859        inst = instructions.CallInstr(self.block, fn, args, name=name,
860                                      cconv=cconv, tail=tail, fastmath=fastmath)
861        self._insert(inst)
862        return inst
863
864    def asm(self, ftype, asm, constraint, args, side_effect, name=''):
865        """
866        Inline assembler.
867        """
868        asm = instructions.InlineAsm(ftype, asm, constraint, side_effect)
869        return self.call(asm, args, name)
870
871    def load_reg(self, reg_type, reg_name, name=''):
872        """
873        Load a register value into an LLVM value.
874          Example: v = load_reg(IntType(32), "eax")
875        """
876        ftype = types.FunctionType(reg_type, [])
877        return self.asm(ftype, "", "={%s}" % reg_name, [], False, name)
878
879    def store_reg(self, value, reg_type, reg_name, name=''):
880        """
881        Store an LLVM value inside a register
882        Example:
883          store_reg(Constant(IntType(32), 0xAAAAAAAA), IntType(32), "eax")
884        """
885        ftype = types.FunctionType(types.VoidType(), [reg_type])
886        return self.asm(ftype, "", "{%s}" % reg_name, [value], True, name)
887
888    def invoke(self, fn, args, normal_to, unwind_to,
889               name='', cconv=None, tail=False):
890        inst = instructions.InvokeInstr(self.block, fn, args, normal_to,
891                                        unwind_to, name=name, cconv=cconv)
892        self._set_terminator(inst)
893        return inst
894
895    # GEP APIs
896
897    def gep(self, ptr, indices, inbounds=False, name=''):
898        """
899        Compute effective address (getelementptr):
900            name = getelementptr ptr, <indices...>
901        """
902        instr = instructions.GEPInstr(self.block, ptr, indices,
903                                      inbounds=inbounds, name=name)
904        self._insert(instr)
905        return instr
906
907    # Vector Operations APIs
908
909    def extract_element(self, vector, idx, name=''):
910        """
911        Returns the value at position idx.
912        """
913        instr = instructions.ExtractElement(self.block, vector, idx, name=name)
914        self._insert(instr)
915        return instr
916
917    def insert_element(self, vector, value, idx, name=''):
918        """
919        Returns vector with vector[idx] replaced by value.
920        The result is undefined if the idx is larger or equal the vector length.
921        """
922        instr = instructions.InsertElement(self.block, vector, value, idx,
923                                           name=name)
924        self._insert(instr)
925        return instr
926
927    def shuffle_vector(self, vector1, vector2, mask, name=''):
928        """
929        Constructs a permutation of elements from *vector1* and *vector2*.
930        Returns a new vector in the same length of *mask*.
931
932        * *vector1* and *vector2* must have the same element type.
933        * *mask* must be a constant vector of integer types.
934        """
935        instr = instructions.ShuffleVector(self.block, vector1, vector2, mask,
936                                           name=name)
937        self._insert(instr)
938        return instr
939
940    # Aggregate APIs
941
942    def extract_value(self, agg, idx, name=''):
943        """
944        Extract member number *idx* from aggregate.
945        """
946        if not isinstance(idx, (tuple, list)):
947            idx = [idx]
948        instr = instructions.ExtractValue(self.block, agg, idx, name=name)
949        self._insert(instr)
950        return instr
951
952    def insert_value(self, agg, value, idx, name=''):
953        """
954        Insert *value* into member number *idx* from aggregate.
955        """
956        if not isinstance(idx, (tuple, list)):
957            idx = [idx]
958        instr = instructions.InsertValue(self.block, agg, value, idx, name=name)
959        self._insert(instr)
960        return instr
961
962    # PHI APIs
963
964    def phi(self, typ, name=''):
965        inst = instructions.PhiInstr(self.block, typ, name=name)
966        self._insert(inst)
967        return inst
968
969    # Special API
970
971    def unreachable(self):
972        inst = instructions.Unreachable(self.block)
973        self._set_terminator(inst)
974        return inst
975
976    def atomic_rmw(self, op, ptr, val, ordering, name=''):
977        inst = instructions.AtomicRMW(
978            self.block, op, ptr, val, ordering, name=name)
979        self._insert(inst)
980        return inst
981
982    def cmpxchg(self, ptr, cmp, val, ordering, failordering=None, name=''):
983        """
984        Atomic compared-and-set:
985            atomic {
986                old = *ptr
987                success = (old == cmp)
988                if (success)
989                    *ptr = val
990                }
991            name = { old, success }
992
993        If failordering is `None`, the value of `ordering` is used.
994        """
995        failordering = ordering if failordering is None else failordering
996        inst = instructions.CmpXchg(self.block, ptr, cmp, val, ordering,
997                                    failordering, name=name)
998        self._insert(inst)
999        return inst
1000
1001    def landingpad(self, typ, name='', cleanup=False):
1002        inst = instructions.LandingPadInstr(self.block, typ, name, cleanup)
1003        self._insert(inst)
1004        return inst
1005
1006    def assume(self, cond):
1007        """
1008        Optimizer hint: assume *cond* is always true.
1009        """
1010        fn = self.module.declare_intrinsic("llvm.assume")
1011        return self.call(fn, [cond])
1012
1013    def fence(self, ordering, targetscope=None, name=''):
1014        """
1015        Add a memory barrier, preventing certain reorderings of load and/or
1016        store accesses with
1017        respect to other processors and devices.
1018        """
1019        inst = instructions.Fence(self.block, ordering, targetscope, name=name)
1020        self._insert(inst)
1021        return inst
1022
1023    @_uniop_intrinsic_int("llvm.bswap")
1024    def bswap(self, cond):
1025        """
1026        Used to byte swap integer values with an even number of bytes (positive
1027        multiple of 16 bits)
1028        """
1029
1030    @_uniop_intrinsic_int("llvm.bitreverse")
1031    def bitreverse(self, cond):
1032        """
1033        Reverse the bitpattern of an integer value; for example 0b10110110
1034        becomes 0b01101101.
1035        """
1036
1037    @_uniop_intrinsic_int("llvm.ctpop")
1038    def ctpop(self, cond):
1039        """
1040        Counts the number of bits set in a value.
1041        """
1042
1043    @_uniop_intrinsic_with_flag("llvm.ctlz")
1044    def ctlz(self, cond, flag):
1045        """
1046        Counts leading zero bits in *value*. Boolean *flag* indicates whether
1047        the result is defined for ``0``.
1048        """
1049
1050    @_uniop_intrinsic_with_flag("llvm.cttz")
1051    def cttz(self, cond, flag):
1052        """
1053        Counts trailing zero bits in *value*. Boolean *flag* indicates whether
1054        the result is defined for ``0``.
1055        """
1056
1057    @_triop_intrinsic("llvm.fma")
1058    def fma(self, a, b, c):
1059        """
1060        Perform the fused multiply-add operation.
1061        """
1062
1063    def convert_from_fp16(self, a, to=None, name=''):
1064        """
1065        Convert from an i16 to the given FP type
1066        """
1067        if not to:
1068            raise TypeError("expected a float return type")
1069        if not isinstance(to, (types.FloatType, types.DoubleType)):
1070            raise TypeError("expected a float type, got %s" % to)
1071        if not (isinstance(a.type, types.IntType) and a.type.width == 16):
1072            raise TypeError("expected an i16 type, got %s" % a.type)
1073
1074        opname = 'llvm.convert.from.fp16'
1075        fn = self.module.declare_intrinsic(opname, [to])
1076        return self.call(fn, [a], name)
1077
1078    @_uniop_intrinsic_float("llvm.convert.to.fp16")
1079    def convert_to_fp16(self, a):
1080        """
1081        Convert the given FP number to an i16
1082        """
1083