B
    Ꮚ\v                 @   s   d dl mZmZ d dlZd dlZddlmZmZmZ ddddd	d
dZ	ej
fddZej
fddZej
fddZdd Zdd Zdd ZejfddZdd ZG dd deZdS )    )print_functionabsolute_importN   )instructionstypesvaluesgtlteqnegele)><z==z!=z>=z<=c                s    fdd}|S )Nc                s   t | d fdd	}|S )N  c                sH   |j |j kr td|j |j f  | j|j ||f||}| | |S )Nz,Operands must be the same type, got (%s, %s))type
ValueErrorblock_insert)selflhsrhsnameflagsinstr)clsopnamer   2lib/python3.7/site-packages/llvmlite/ir/builder.pywrapped   s    
z%_binop.<locals>.wrap.<locals>.wrapped)r   r   )	functoolswraps)fnr   )r   r   r   r   wrap   s    z_binop.<locals>.wrapr   )r   r   r#   r   )r   r   r   _binop   s    r$   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c       
         s   |j |j kr td|j |j f |j }t|tjs@td|f td}| j}tt||g||g}|	d f |g|}| j
|||g|d}	|	S )Nz,Operands must be the same type, got (%s, %s)z expected an integer type, got %sr   zllvm.%s.with.overflow)r   )r   r   
isinstancer   IntType	TypeErrormoduleFunctionTypeZLiteralStructTypedeclare_intrinsiccall)
r   r   r   r   ZtyZbool_tymodZfntyr"   ret)r   r   r   r   $   s    


z3_binop_with_overflow.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r#   #   s    z"_binop_with_overflow.<locals>.wrapr   )r   r   r#   r   )r   r   _binop_with_overflow"   s    r.   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c                s$    | j |j|g|}| | |S )N)r   r   r   )r   operandr   r   )r   r   r   r   r   =   s    
z%_uniop.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r   r#   <   s    z_uniop.<locals>.wrapr   )r   r   r#   r   )r   r   r   _uniop;   s    	r0   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c                s>   t |jtjstd|j | j |jg}| ||g|S )Nz expected an integer type, got %s)r%   r   r   r&   r'   r(   r*   r+   )r   r/   r   r"   )r   r   r   r   J   s    z/_uniop_intrinsic.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r#   I   s    z_uniop_intrinsic.<locals>.wrapr   )r   r#   r   )r   r   _uniop_intrinsicH   s    
r1   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c                sb   t |jtjstd|j |jtdkr:td|j | j |j|jg}| |||g|S )Nz expected an integer type, got %sr   zexpected an i1 type, got %s)r%   r   r   r&   r'   r(   r*   r+   )r   r/   flagr   r"   )r   r   r   r   X   s    z9_uniop_intrinsic_with_flag.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r#   W   s    z(_uniop_intrinsic_with_flag.<locals>.wrapr   )r   r#   r   )r   r   _uniop_intrinsic_with_flagV   s    r3   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c                s   |j |j ks|j |j kr2td|j |j |j f n"t|j tjtjfsTtd|j  | j |j |j |j g}| ||||g|S )Nz-expected types to be the same, got %s, %s, %sz'expected an floating point type, got %s)	r   r'   r%   r   Z	FloatTypeZ
DoubleTyper(   r*   r+   )r   abcr   r"   )r   r   r   r   h   s    z/_triop_intrinsic.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r#   g   s    z_triop_intrinsic.<locals>.wrapr   )r   r#   r   )r   r   _triop_intrinsicf   s    r7   c                s    fdd}|S )Nc                s   t | d fdd	}|S )Nr   c                s.   |j |kr|S  | j|||}| | |S )N)r   r   r   )r   valtypr   r   )r   r   r   r   r   |   s
    

z&_castop.<locals>.wrap.<locals>.wrapped)r   )r    r!   )r"   r   )r   r   r   r   r#   {   s    z_castop.<locals>.wrapr   )r   r   r#   r   )r   r   r   _castopz   s    r:   c             C   s4   t | dkr(d}d| d| d|gS | | S dS )zReturns (label + suffix) or a truncated version if it's too long.
    Parameters
    ----------
    label : str
        Label name
    suffix : str
        Label suffix
    2      r   Nz..)lenjoin)ZlabelsuffixZnheadr   r   r   _label_suffix   s    	r@   c               @   s  e Zd ZdddZedd ZeZedd Zedd	 Zd
d Z	dd Z
dd Zdd ZdddZejdd Zejdd Zejdd ZejdddZejdddZdd  Zd!d" Zed#dd$d%Zed&dd'd(Zed)dd*d+Zed,dd-d.Zed/dd0d1Zed2dd3d4Zed5dd6d7Zed8dd9d:Zed;dd<d=Z ed>dd?d@Z!edAd dBdCZ"edDddEdFZ#edGddHdIZ$edJddKdLZ%edMddNdOZ&edPddQdRZ'edSddTdUZ(edVddWdXZ)e*dYddZd[Z+e*d\d	d]d^Z,e*d_d
d`daZ-e*dbddcddZ.e*deddfdgZ/e*dhddidjZ0ddkdlZ1ddmdnZ2dodp Z3ddqdrZ4ddsdtZ5dg fdudvZ6dg fdwdxZ7ddydzZ8e9d{dd|d}Z:e9d~dddZ;e9ddddZ<e9ddddZ=e9ddddZ>e9ddddZ?e9ddddZ@e9ddddZAe9ddddZBe9ddddZCe9ddddZDe9ddddZEe9ddddZFd ddZGd!ddZHd"ddZId#ddZJdd ZKdd ZLdd ZMdd ZNdd ZOdd ZPdd ZQdd ZRd$ddZSd%ddZTd&ddZUd'ddÄZVd(ddńZWd)ddǄZXd*ddɄZYd+dd˄ZZd,dd̈́Z[d-ddτZ\d.ddфZ]d/ddӄZ^ddՄ Z_d0ddׄZ`d1ddلZad2ddۄZbdd݄ Zcd3dd߄Zdeeddd Zfeeddd Zgeeddd Zheiddd Zjeiddd Zkelddd ZmdS (4  	IRBuilderNc             C   s$   || _ |rt|jnd| _d | _d S )Nr   )_blockr=   r   _anchordebug_metadata)r   r   r   r   r   __init__   s    zIRBuilder.__init__c             C   s   | j S )z*
        The current basic block.
        )rB   )r   r   r   r   r      s    zIRBuilder.blockc             C   s   | j jS )z'
        The current function.
        )r   parent)r   r   r   r   function   s    zIRBuilder.functionc             C   s
   | j jjS )z%
        The current module.
        )r   rF   r(   )r   r   r   r   r(      s    zIRBuilder.modulec             C   s   |j | _| jj|| _dS )z
        Position immediately before the given instruction.  The current block
        is also changed to the instruction's basic block.
        N)rF   rB   r   indexrC   )r   r   r   r   r   position_before   s    zIRBuilder.position_beforec             C   s    |j | _| jj|d | _dS )z
        Position immediately after the given instruction.  The current block
        is also changed to the instruction's basic block.
        r   N)rF   rB   r   rH   rC   )r   r   r   r   r   position_after   s    zIRBuilder.position_afterc             C   s   || _ d| _dS )z=
        Position at the start of the basic *block*.
        r   N)rB   rC   )r   r   r   r   r   position_at_start   s    zIRBuilder.position_at_startc             C   s   || _ t|j| _dS )z;
        Position at the end of the basic *block*.
        N)rB   r=   r   rC   )r   r   r   r   r   position_at_end   s    zIRBuilder.position_at_endr   c             C   s   | j |S )z
        Append a basic block, with the given optional *name*, to the current
        function.  The current block is not changed.  The new block is returned.
        )rG   append_basic_block)r   r   r   r   r   rM      s    zIRBuilder.append_basic_blockc          	   c   sF   | j }|j}|dk	r | | n
| | z
dV  W d| | X dS )z
        A context manager which temporarily positions the builder at the end
        of basic block *bb* (but before any terminator).
        N)basic_block
terminatorrI   rL   )r   r   Z	old_blocktermr   r   r   
goto_block   s    

zIRBuilder.goto_blockc          	   c   s$   |  | jj dV  W dQ R X dS )z}
        A context manager which temporarily positions the builder at the
        end of the function's entry block.
        N)rQ   rG   Zentry_basic_block)r   r   r   r   goto_entry_block   s    zIRBuilder.goto_entry_blockc             c   s*   |  | |V  | jjd kr&| | d S )N)rL   rN   rO   branch)r   ZbbenterZbbexitr   r   r   _branch_helper   s    
zIRBuilder._branch_helperc          	   c   s   | j }| jt|jdd}| jt|jdd}| |||}|dk	r^||rTddgnddg | || |V  W dQ R X | | dS )a  
        A context manager which sets up a conditional basic block based
        on the given predicate (a i1 value).  If the conditional block
        is not explicitly terminated, a branch will be added to the next
        block.
        If *likely* is given, its boolean value indicates whether the
        predicate is likely to be true or not, and metadata is issued
        for LLVM's optimizers to account for that.
        z.if)r   z.endifNc   r   )rN   rM   r@   r   cbranchset_weightsrT   rL   )r   predlikelybbbbifbbendbrr   r   r   if_then   s    zIRBuilder.if_thenc       
      c   s   | j }| jt|jdd}| jt|jdd}| jt|jdd}| |||}|dk	rr||rhddgnddg | ||}| ||}	||	fV  | | dS )a@  
        A context manager which sets up two conditional basic blocks based
        on the given predicate (a i1 value).
        A tuple of context managers is yield'ed.  Each context manager
        acts as a if_then() block.
        *likely* has the same meaning as in if_then().

        Typical use::
            with builder.if_else(pred) as (then, otherwise):
                with then:
                    # emit instructions for when the predicate is true
                with otherwise:
                    # emit instructions for when the predicate is false
        z.if)r   z.elsez.endifNrU   r   )rN   rM   r@   r   rV   rW   rT   rL   )
r   rX   rY   rZ   r[   Zbbelser\   r]   ZthenZ	otherwiser   r   r   if_else  s    
zIRBuilder.if_elsec             C   sD   | j d k	r d|jkr | j |jd< | jj| j| |  jd7  _d S )NZdbgr   )rD   ZmetadatarB   r   insertrC   )r   r   r   r   r   r   2  s    zIRBuilder._insertc             C   s"   | j jrt| | || j _|S )N)r   Zis_terminatedAssertionErrorr   rO   )r   rP   r   r   r   _set_terminator8  s    
zIRBuilder._set_terminatorshlc             C   s   dS )zC
        Left integer shift:
            name = lhs << rhs
        Nr   )r   r   r   r   r   r   r   rc   B  s    zIRBuilder.shllshrc             C   s   dS )zW
        Logical (unsigned) right integer shift:
            name = lhs >> rhs
        Nr   )r   r   r   r   r   r   r   rd   I  s    zIRBuilder.lshrashrc             C   s   dS )zX
        Arithmetic (signed) right integer shift:
            name = lhs >> rhs
        Nr   )r   r   r   r   r   r   r   re   P  s    zIRBuilder.ashraddc             C   s   dS )z@
        Integer addition:
            name = lhs + rhs
        Nr   )r   r   r   r   r   r   r   rf   W  s    zIRBuilder.addfaddc             C   s   dS )zG
        Floating-point addition:
            name = lhs + rhs
        Nr   )r   r   r   r   r   r   r   rg   ^  s    zIRBuilder.faddsubc             C   s   dS )zC
        Integer subtraction:
            name = lhs - rhs
        Nr   )r   r   r   r   r   r   r   rh   e  s    zIRBuilder.subfsubc             C   s   dS )zJ
        Floating-point subtraction:
            name = lhs - rhs
        Nr   )r   r   r   r   r   r   r   ri   l  s    zIRBuilder.fsubmulc             C   s   dS )zF
        Integer multiplication:
            name = lhs * rhs
        Nr   )r   r   r   r   r   r   r   rj   s  s    zIRBuilder.mulfmulc             C   s   dS )zM
        Floating-point multiplication:
            name = lhs * rhs
        Nr   )r   r   r   r   r   r   r   rk   z  s    zIRBuilder.fmuludivc             C   s   dS )zI
        Unsigned integer division:
            name = lhs / rhs
        Nr   )r   r   r   r   r   r   r   rl     s    zIRBuilder.udivsdivc             C   s   dS )zG
        Signed integer division:
            name = lhs / rhs
        Nr   )r   r   r   r   r   r   r   rm     s    zIRBuilder.sdivfdivc             C   s   dS )zG
        Floating-point division:
            name = lhs / rhs
        Nr   )r   r   r   r   r   r   r   rn     s    zIRBuilder.fdivuremc             C   s   dS )zJ
        Unsigned integer remainder:
            name = lhs % rhs
        Nr   )r   r   r   r   r   r   r   ro     s    zIRBuilder.uremsremc             C   s   dS )zH
        Signed integer remainder:
            name = lhs % rhs
        Nr   )r   r   r   r   r   r   r   rp     s    zIRBuilder.sremfremc             C   s   dS )zH
        Floating-point remainder:
            name = lhs % rhs
        Nr   )r   r   r   r   r   r   r   rq     s    zIRBuilder.fremorc             C   s   dS )zB
        Bitwise integer OR:
            name = lhs | rhs
        Nr   )r   r   r   r   r   r   r   or_  s    zIRBuilder.or_andc             C   s   dS )zC
        Bitwise integer AND:
            name = lhs & rhs
        Nr   )r   r   r   r   r   r   r   and_  s    zIRBuilder.and_xorc             C   s   dS )zC
        Bitwise integer XOR:
            name = lhs ^ rhs
        Nr   )r   r   r   r   r   r   r   rv     s    zIRBuilder.xorZsaddc             C   s   dS )zn
        Signed integer addition with overflow:
            name = {result, overflow bit} = lhs + rhs
        Nr   )r   r   r   r   r   r   r   sadd_with_overflow  s    zIRBuilder.sadd_with_overflowZsmulc             C   s   dS )zt
        Signed integer multiplication with overflow:
            name = {result, overflow bit} = lhs * rhs
        Nr   )r   r   r   r   r   r   r   smul_with_overflow  s    zIRBuilder.smul_with_overflowZssubc             C   s   dS )zq
        Signed integer subtraction with overflow:
            name = {result, overflow bit} = lhs - rhs
        Nr   )r   r   r   r   r   r   r   ssub_with_overflow  s    zIRBuilder.ssub_with_overflowZuaddc             C   s   dS )zp
        Unsigned integer addition with overflow:
            name = {result, overflow bit} = lhs + rhs
        Nr   )r   r   r   r   r   r   r   uadd_with_overflow  s    zIRBuilder.uadd_with_overflowZumulc             C   s   dS )zv
        Unsigned integer multiplication with overflow:
            name = {result, overflow bit} = lhs * rhs
        Nr   )r   r   r   r   r   r   r   umul_with_overflow  s    zIRBuilder.umul_with_overflowZusubc             C   s   dS )zs
        Unsigned integer subtraction with overflow:
            name = {result, overflow bit} = lhs - rhs
        Nr   )r   r   r   r   r   r   r   usub_with_overflow  s    zIRBuilder.usub_with_overflowc             C   sD   t |jtjr&t|jd|jj }nt|jd}| j|||dS )zG
        Bitwise integer complement:
            name = ~value
        )r}   )r   )r%   r   r   Z
VectorTyper   Constantcountrv   )r   valuer   r   r   r   r   not_  s    zIRBuilder.not_c             C   s   | j t|jd||dS )z=
        Integer negative:
            name = -value
        r   )r   )rh   r   r~   r   )r   r   r   r   r   r   neg  s    zIRBuilder.negc             C   sd   yt | }W n" tk
r.   td|f Y nX |dkr@|| }tj| j||||d}| | |S )Nzinvalid comparison %r for icmp)z==z!=)r   )_CMP_MAPKeyErrorr   r   Z	ICMPInstrr   r   )r   prefixcmpopr   r   r   opr   r   r   r   _icmp  s    
zIRBuilder._icmpc             C   s   |  d||||S )z
        Signed integer comparison:
            name = lhs <cmpop> rhs

        where cmpop can be '==', '!=', '<', '<=', '>', '>='
        s)r   )r   r   r   r   r   r   r   r   icmp_signed  s    zIRBuilder.icmp_signedc             C   s   |  d||||S )z
        Unsigned integer (or pointer) comparison:
            name = lhs <cmpop> rhs

        where cmpop can be '==', '!=', '<', '<=', '>', '>='
        u)r   )r   r   r   r   r   r   r   r   icmp_unsigned  s    zIRBuilder.icmp_unsignedc             C   s@   |t krdt |  }n|}tj| j|||||d}| | |S )z
        Floating-point ordered comparison:
            name = lhs <cmpop> rhs

        where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
        o)r   r   )r   r   	FCMPInstrr   r   )r   r   r   r   r   r   r   r   r   r   r   fcmp_ordered!  s    
zIRBuilder.fcmp_orderedc             C   s@   |t krdt |  }n|}tj| j|||||d}| | |S )z
        Floating-point unordered comparison:
            name = lhs <cmpop> rhs

        where cmpop can be '==', '!=', '<', '<=', '>', '>=', 'ord', 'uno'
        r   )r   r   )r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   fcmp_unordered0  s    
zIRBuilder.fcmp_unorderedc             C   s$   t j| j||||d}| | |S )zN
        Ternary select operator:
            name = cond ? lhs : rhs
        )r   )r   ZSelectInstrr   r   )r   condr   r   r   r   r   r   r   select?  s    
zIRBuilder.selecttruncc             C   s   dS )z_
        Truncating integer downcast to a smaller type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   L  s    zIRBuilder.trunczextc             C   s   dS )z`
        Zero-extending integer upcast to a larger type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   S  s    zIRBuilder.zextsextc             C   s   dS )z`
        Sign-extending integer upcast to a larger type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   Z  s    zIRBuilder.sextfptruncc             C   s   dS )z`
        Floating-point downcast to a less precise type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   a  s    zIRBuilder.fptruncfpextc             C   s   dS )z^
        Floating-point upcast to a more precise type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   h  s    zIRBuilder.fpextbitcastc             C   s   dS )zZ
        Pointer cast to a different pointer type:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   o  s    zIRBuilder.bitcastaddrspacecastc             C   s   dS )z[
        Pointer cast to a different address space:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   v  s    zIRBuilder.addrspacecastfptouic             C   s   dS )z\
        Convert floating-point to unsigned integer:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r   }  s    zIRBuilder.fptouiuitofpc             C   s   dS )z\
        Convert unsigned integer to floating-point:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r     s    zIRBuilder.uitofpfptosic             C   s   dS )zZ
        Convert floating-point to signed integer:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r     s    zIRBuilder.fptosisitofpc             C   s   dS )zZ
        Convert signed integer to floating-point:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r     s    zIRBuilder.sitofpptrtointc             C   s   dS )zI
        Cast pointer to integer:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r     s    zIRBuilder.ptrtointinttoptrc             C   s   dS )zI
        Cast integer to pointer:
            name = (typ) value
        Nr   )r   r   r9   r   r   r   r   r     s    zIRBuilder.inttoptrc             C   sb   |dkr
n8t |tjtjfr0t |jtjsBtnttd|}t	| j
|||}| | |S )zl
        Stack-allocate a slot for *size* elements of the given type.
        (default one element)
        N    )r%   r   ZValuer~   r   r   r&   ra   r   ZAllocaInstrr   r   )r   r9   sizer   Zalr   r   r   alloca  s    
zIRBuilder.allocac             C   sH   t |jtjs$td|jt|f t| j||}||_	| 
| |S )zf
        Load value from pointer, with optional guaranteed alignment:
            name = *ptr
        z5cannot load from value of type %s (%r): not a pointer)r%   r   r   PointerTyper'   strr   Z	LoadInstrr   alignr   )r   ptrr   r   ldr   r   r   load  s    
zIRBuilder.loadc             C   sj   t |jtjs$td|jt|f |jj|jkrFtd|j|jf t| j	||}||_
| | |S )ze
        Store value to pointer, with optional guaranteed alignment:
            *ptr = name
        z4cannot store to value of type %s (%r): not a pointerz(cannot store %s to %s: mismatching types)r%   r   r   r   r'   r   pointeer   Z
StoreInstrr   r   r   )r   r   r   r   str   r   r   store  s    
zIRBuilder.storec             C   sF   t |jtjs$td|jt|f t| j||||}| 	| |S )zf
        Load value from pointer, with optional guaranteed alignment:
            name = *ptr
        z5cannot load from value of type %s (%r): not a pointer)
r%   r   r   r   r'   r   r   ZLoadAtomicInstrr   r   )r   r   orderingr   r   r   r   r   r   load_atomic  s    
zIRBuilder.load_atomicc             C   sh   t |jtjs$td|jt|f |jj|jkrFtd|j|jf t| j	||||}| 
| |S )ze
        Store value to pointer, with optional guaranteed alignment:
            *ptr = name
        z4cannot store to value of type %s (%r): not a pointerz(cannot store %s to %s: mismatching types)r%   r   r   r   r'   r   r   r   ZStoreAtomicInstrr   r   )r   r   r   r   r   r   r   r   r   store_atomic  s    
zIRBuilder.store_atomicc             C   s    t | jd||}| | |S )zF
        Create a switch-case with a single *default* target.
        switch)r   ZSwitchInstrr   rb   )r   r   defaultZswtr   r   r   r     s    
zIRBuilder.switchc             C   s    t | jd|g}| | |S )z3
        Unconditional branch to *target*.
        r]   )r   Branchr   rb   )r   targetr]   r   r   r   rS     s    
zIRBuilder.branchc             C   s$   t | jd|||g}| | |S )zV
        Conditional branch to *truebr* if *cond* is true, else to *falsebr*.
        r]   )r   ZConditionalBranchr   rb   )r   r   ZtruebrZfalsebrr]   r   r   r   rV   
  s    

zIRBuilder.cbranchc             C   s   t | jd|}| | |S )z3
        Indirect branch to target *addr*.
        Z
indirectbr)r   ZIndirectBranchr   rb   )r   Zaddrr]   r   r   r   branch_indirect  s    
zIRBuilder.branch_indirectc             C   s   |  t| jdS )z7
        Return from function without a value.
        zret void)rb   r   Retr   )r   r   r   r   ret_void  s    zIRBuilder.ret_voidc             C   s   |  t| jd|S )z>
        Return from function with the given *value*.
        r-   )rb   r   r   r   )r   r   r   r   r   r-   "  s    zIRBuilder.retc             C   s    t | jd|g}| | |S )z0
        Resume an in-flight exception.
        resume)r   r   r   rb   )r   
landingpadr]   r   r   r   r   )  s    
zIRBuilder.resumeFr   c          	   C   s(   t j| j||||||d}| | |S )zP
        Call function *fn* with *args*:
            name = fn(args...)
        )r   cconvtailfastmath)r   Z	CallInstrr   r   )r   r"   argsr   r   r   r   instr   r   r   r+   3  s    
zIRBuilder.callc             C   s   t ||||}| |||S )z#
        Inline assembler.
        )r   Z	InlineAsmr+   )r   ftypeasmZ
constraintr   Zside_effectr   r   r   r   r   =  s    zIRBuilder.asmc             C   s$   t |g }| |dd| g d|S )zo
        Load a register value into an LLVM value.
          Example: v = load_reg(IntType(32), "eax")
        r   z={%s}F)r   r)   r   )r   reg_typereg_namer   r   r   r   r   load_regD  s    zIRBuilder.load_regc             C   s,   t t  |g}| |dd| |gd|S )z
        Store an LLVM value inside a register
          Example: store_reg(Constant(IntType(32), 0xAAAAAAAA), IntType(32), "eax")
        r   z{%s}T)r   r)   ZVoidTyper   )r   r   r   r   r   r   r   r   r   	store_regL  s    zIRBuilder.store_regc       	   	   C   s(   t j| j||||||d}| | |S )N)r   r   )r   ZInvokeInstrr   rb   )	r   r"   r   Z	normal_toZ	unwind_tor   r   r   r   r   r   r   invokeT  s    
zIRBuilder.invokec             C   s$   t j| j||||d}| | |S )zo
        Compute effective address (getelementptr):
            name = getelementptr ptr, <indices...>
        )inboundsr   )r   ZGEPInstrr   r   )r   r   indicesr   r   r   r   r   r   gep\  s    

zIRBuilder.gepc             C   s"   t j| j|||d}| | |S )z4
        Returns the value at position idx.
        )r   )r   ZExtractElementr   r   )r   vectoridxr   r   r   r   r   extract_elementh  s    
zIRBuilder.extract_elementc             C   s$   t j| j||||d}| | |S )z
        Returns vector with vector[idx] replaced by value.
        The result is undefined if the idx is larger or equal the vector length.
        )r   )r   ZInsertElementr   r   )r   r   r   r   r   r   r   r   r   insert_elementp  s    
zIRBuilder.insert_elementc             C   s$   t j| j||||d}| | |S )a  
        Constructs a permutation of elements from *vector1* and *vector2*.
        Returns a new vector in the same length of *mask*.

        * *vector1* and *vector2* must have the same element type.
        * *mask* must be a constant vector of integer types.
        )r   )r   ZShuffleVectorr   r   )r   Zvector1Zvector2maskr   r   r   r   r   shuffle_vectorz  s    
zIRBuilder.shuffle_vectorc             C   s6   t |ttfs|g}tj| j|||d}| | |S )z=
        Extract member number *idx* from aggregate.
        )r   )r%   tuplelistr   ZExtractValuer   r   )r   aggr   r   r   r   r   r   extract_value  s
    
zIRBuilder.extract_valuec             C   s8   t |ttfs|g}tj| j||||d}| | |S )zI
        Insert *value* into member number *idx* from aggregate.
        )r   )r%   r   r   r   ZInsertValuer   r   )r   r   r   r   r   r   r   r   r   insert_value  s
    
zIRBuilder.insert_valuec             C   s    t j| j||d}| | |S )N)r   )r   ZPhiInstrr   r   )r   r9   r   r   r   r   r   phi  s    
zIRBuilder.phic             C   s   t | j}| | |S )N)r   ZUnreachabler   rb   )r   r   r   r   r   unreachable  s    
zIRBuilder.unreachablec             C   s&   t j| j|||||d}| | |S )N)r   )r   Z	AtomicRMWr   r   )r   r   r   r8   r   r   r   r   r   r   
atomic_rmw  s    
zIRBuilder.atomic_rmwc          	   C   s8   |dkr|n|}t j| j||||||d}| | |S )a8  
        Atomic compared-and-set:
            atomic {
                old = *ptr
                success = (old == cmp)
                if (success)
                    *ptr = val
                }
            name = { old, success }

        If failordering is `None`, the value of `ordering` is used.
        N)r   )r   ZCmpXchgr   r   )r   r   Zcmpr8   r   Zfailorderingr   r   r   r   r   cmpxchg  s
    

zIRBuilder.cmpxchgc             C   s    t | j|||}| | |S )N)r   ZLandingPadInstrr   r   )r   r9   r   Zcleanupr   r   r   r   r     s    
zIRBuilder.landingpadc             C   s   | j d}| ||gS )z?
        Optimizer hint: assume *cond* is always true.
        zllvm.assume)r(   r*   r+   )r   r   r"   r   r   r   assume  s    zIRBuilder.assumec             C   s"   t j| j|||d}| | |S )z
        Add a memory barrier, preventing certain reorderings of load and/or store accesses with
        respect to other processors and devices.
        )r   )r   ZFencer   r   )r   r   Ztargetscoper   r   r   r   r   fence  s    
zIRBuilder.fencez
llvm.bswapc             C   s   dS )zn
        Used to byte swap integer values with an even number of bytes (positive multiple of 16 bits)
        Nr   )r   r   r   r   r   bswap  s    zIRBuilder.bswapzllvm.bitreversec             C   s   dS )zh
        Reverse the bitpattern of an integer value; for example 0b10110110 becomes 0b01101101.
        Nr   )r   r   r   r   r   
bitreverse  s    zIRBuilder.bitreversez
llvm.ctpopc             C   s   dS )z;
        Counts the number of bits set in a value.
        Nr   )r   r   r   r   r   ctpop  s    zIRBuilder.ctpopz	llvm.ctlzc             C   s   dS )zC
        Counts the number of leading zeros in a variable.
        Nr   )r   r   r2   r   r   r   ctlz  s    zIRBuilder.ctlzz	llvm.cttzc             C   s   dS )zD
        Counts the number of trailing zeros in a variable.
        Nr   )r   r   r2   r   r   r   cttz  s    zIRBuilder.cttzzllvm.fmac             C   s   dS )z;
        Perform the fused multiply-add operation.
        Nr   )r   r4   r5   r6   r   r   r   fma  s    zIRBuilder.fma)N)r   )N)N)r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )r   )Nr   )r   N)N)r   )r   NFr   )r   )r   )r   )r   NF)Fr   )r   )r   )r   )r   )r   )r   )r   )Nr   )r   F)Nr   )n__name__
__module____qualname__rE   propertyr   rN   rG   r(   rI   rJ   rK   rL   rM   
contextlibcontextmanagerrQ   rR   rT   r^   r_   r   rb   r$   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   rq   rs   ru   rv   r.   rw   rx   ry   rz   r{   r|   r   r   r   r   r   r   r   r   r:   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rS   rV   r   r   r-   r   r+   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r1   r   r   r   r3   r   r   r7   r   r   r   r   r   rA      s  

	

		
	



	rA   )Z
__future__r   r   r   r    r   r   r   r   r   ZInstructionr$   r.   r0   r1   r3   r7   Z	CastInstrr:   r@   objectrA   r   r   r   r   <module>   s$   