U
    ?hi                     @   sN  d Z ddlZddlmZmZ ddlZddlmZ ddlm	Z	m
Z
mZmZ ddlZedZedZedZee	jZe ZedZedZedZedZd	d
 ZdddZdd Zi ZdddZi fddZ G dd de!Z"G dd de"Z#G dd de"Z$G dd de!Z%dddZ&d d! Z'dd"d#Z(d$d% Z)d&d' Z*d(d) Z+dd*d+Z,d,d- Z-d.d/ Z.d0d1 Z/d2d3 Z0d4d5 Z1d6d7 Z2d8d9 Z3d:d; Z4e5d<d=Z6edd>d?Z7eddAdBZ8edCdD Z9eddFdGZ:edHdI Z;ddJdKZ<dLdM Z=ddNdOZ>ddPdQZ?ddRdSZ@ddTdUZAdVdW ZBdXdY ZCdZd[ ZDd\d] ZEeDZFeCZGd^d_ ZHeed`dadbZIdcdd ZJdedf ZKddgdhZLeddidjZMeKZNdkdl ZOdmdn ZPdodp ZQdqdr ZRdsdt ZSddudvZTdwdx ZUdydz ZVdd|d}ZWd~d ZXdd ZYdd ZZdd Z[dddZ\dddZ]dd Z^dd Z_dd Z`dd Zadd Zbdd Zcdd Zddd ZedS )z+
Generic helpers for LLVM code generation.
    N)contextmanager	ExitStack)ir)utilstypesconfig	debuginfo          c                 C   s   |  d||dS )N!=r   )icmp_unsignedtypebuildervalue r   D/var/www/html/venv/lib/python3.8/site-packages/numba/core/cgutils.pyas_bool_bit   s    r   c                 C   sJ   |dkrt dd |D }|t j}t|D ]\}}| |||}q.|S )zH
    Create an anonymous struct containing the given LLVM *values*.
    Nc                 S   s   g | ]
}|j qS r   r   .0vr   r   r   
<listcomp>%   s     z)make_anonymous_struct.<locals>.<listcomp>r   ZLiteralStructType	Undefined	enumerateinsert_value)r   valuesZstruct_typeZ
struct_valir   r   r   r   make_anonymous_struct    s    
r    c                 C   s*   t | }t|}tttd||S )z0
    Make a byte array constant from *buf*.
    r
   )	bytearraylenr   Constant	ArrayTypeIntType)bufbnr   r   r   make_bytearray,   s    r)   r   c                 C   sb   | |f}t |}|dkr^ttd| }|jd t|  }|f}t| d}t|||}|t |< |S )zK
    Returns a specialized StructProxy subclass for the given fe_type.
    N)r   data_)_fe_type)_struct_proxy_cachegetValueStructProxyDataStructProxy__name__strdictr   )Zfe_typekind	cache_keyresbaseZclsnamebasesZ
clsmembersr   r   r   create_struct_proxy8   s    

r9   c                 C   sV   |  }|jjD ]"}||t||}t| || q| D ]\}}t| || q<| S )zJ
    Copy structure from *src* to *dst* with replacement from *repl*.
    )copy
_datamodel_fieldspopgetattrsetattritems)dstsrcreplkr   r   r   r   copy_structK   s    rE   c                       s   e Zd ZdZdZd!ddZdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Z fddZdd Zdd Zdd Zdd Zdd Zdd  Z  ZS )"_StructProxyz
    Creates a `Structure` like interface that is constructed with information
    from DataModel instance.  FE type must have a data model that is a
    subclass of StructModel.
    Nc                 C   s   || _ | j j| j | _t| jtjjjs8t	d
| j|| _| | j| _t| jrZt| |\}}|jj| jkrtd| j |jf |d k	r|j|jjkrtd|jj|jf | j|| || _|| _d S )NzNot a structure model: {0}z!bad ref type: expected %s, got %sz#bad value type: expected %s, got %s)_contextZdata_model_managerr,   r;   
isinstancenumbacore	datamodelZStructModel	TypeErrorformat_builder_get_be_type_be_type
is_pointerAssertionError
_make_refsr   pointee
as_pointerstore_value
_outer_ref)selfcontextr   r   refZ	outer_refr   r   r   __init__c   s,    
z_StructProxy.__init__c                 C   s"   |dkrt | j| jdd}||fS )z
        Return an (outer ref, value ref) pair.  By default, these are
        the same pointers, but a derived class may override this.
        NTzfill)alloca_oncerN   rP   )rY   r[   r   r   r   rS   |   s    z_StructProxy._make_refsc                 C   s   t d S NNotImplementedErrorrY   rK   r   r   r   rO      s    z_StructProxy._get_be_typec                 C   s   t d S r`   ra   rY   indexvalr   r   r   _cast_member_to_value   s    z"_StructProxy._cast_member_to_valuec                 C   s   t d S r`   ra   rd   r   r   r   _cast_member_from_value   s    z$_StructProxy._cast_member_from_valuec                 C   s   t | j| jd|S Nr   )gep_inboundsrN   rW   rY   re   r   r   r   _get_ptr_by_index   s    z_StructProxy._get_ptr_by_indexc                 C   s   | j |}| |S r`   )r;   get_field_positionrl   )rY   attrnamere   r   r   r   _get_ptr_by_name   s    z_StructProxy._get_ptr_by_namec                 C   s&   | ds| | j| S t|dS z;
        Load the LLVM value of the named *field*.
        r+   N)
startswithr;   rm   AttributeErrorrY   fieldr   r   r   __getattr__   s    
z_StructProxy.__getattr__c                    s0   | drtt| ||S || | j|< dS z@
        Store the LLVM *value* into the named *field*.
        r+   N)rq   superrF   __setattr__r;   rm   rY   rt   r   	__class__r   r   rx      s    
z_StructProxy.__setattr__c                 C   s   | j | |}| ||S z>
        Load the LLVM value of the field at *index*.
        )rN   loadrl   rg   )rY   re   Z
member_valr   r   r   __getitem__   s    z_StructProxy.__getitem__c                 C   s   |  |}| ||}|j|jjkr|t|jrft|jjrf|jj|jjjkrf| j| j||jjj}nt	dj
||| |d| j|| dS )C
        Store the LLVM *value* into the field at *index*.
        zjInvalid store of {value.type} to {ptr.type.pointee} in {self._datamodel} (trying to write member #{index}))r   ptrrY   re   N)rl   rh   r   rT   rQ   rG   ZaddrspacecastrN   	addrspacerL   rM   rV   )rY   re   r   r   r   r   r   __setitem__   s"    

  z_StructProxy.__setitem__c                 C   s   | j jS z.
        Return the number of fields.
        )r;   Zfield_countrY   r   r   r   __len__   s    z_StructProxy.__len__c                 C   s   | j S zF
        Return the LLVM pointer to the underlying structure.
        )rX   r   r   r   r   _getpointer   s    z_StructProxy._getpointerc                 C   s   | j | jS zM
        Load and return the value of the underlying LLVM structure.
        )rN   r}   rX   r   r   r   r   	_getvalue   s    z_StructProxy._getvaluec                 C   s>   t |jrt|j| jks*t|j| jf| j|| j dS )z4
        Store the value in this structure.
        N)rQ   r   rR   rP   rN   rV   rW   rY   r   r   r   r   	_setvalue   s    z_StructProxy._setvalue)NN)r1   
__module____qualname____doc__r,   r\   rS   rO   rg   rh   rl   ro   ru   rx   r~   r   r   r   r   r   __classcell__r   r   rz   r   rF   Z   s"   
		rF   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r/   zl
    Create a StructProxy suitable for accessing regular values
    (e.g. LLVM values or alloca slots).
    c                 C   s   |  S r`   )Zget_value_typerc   r   r   r   rO      s    zValueStructProxy._get_be_typec                 C   s   |S r`   r   rd   r   r   r   rg      s    z&ValueStructProxy._cast_member_to_valuec                 C   s   |S r`   r   rd   r   r   r   rh      s    z(ValueStructProxy._cast_member_from_valueNr1   r   r   r   rO   rg   rh   r   r   r   r   r/      s   r/   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r0   zO
    Create a StructProxy suitable for accessing data persisted in memory.
    c                 C   s   |  S r`   )Zget_data_typerc   r   r   r   rO      s    zDataStructProxy._get_be_typec                 C   s   | j |}|| j|S r`   )r;   	get_model	from_datarN   rY   re   rf   modelr   r   r   rg      s    z%DataStructProxy._cast_member_to_valuec                 C   s   | j |}|| j|S r`   )r;   r   Zas_datarN   r   r   r   r   rh      s    z'DataStructProxy._cast_member_from_valueNr   r   r   r   r   r0      s   r0   c                       sr   e Zd ZdZdddZdd Zdd	 Zd
d Z fddZdd Z	dd Z
dd Zdd Zdd Zdd Z  ZS )	Structurezs
    A high-level object wrapping a alloca'ed LLVM structure, including
    named fields and attribute access.
    NFc           
      C   s0  | | | _|| _|| _|d krtt|| jdd| _|d k	rt|jrHt|j| jksdt|j| jf|	|| j n\|d kstt|jst| j|jj
kr|r||| j }ntd|jj
| jf || _i | _g | _g | _td}t| jD ]6\}\}}	|| j|< | j|t|f | j|	 qd S )NTr]   z-mismatching pointer type: got %s, expected %sr   )Zget_struct_type_typerG   rN   r_   rW   rQ   r   rR   rV   rT   bitcastrU   rL   _namemap_fdmapZ_typemapint32_tr   r<   append)
rY   rZ   r   r   r[   Zcast_refr7   r   rD   tpr   r   r   r\     s8    
zStructure.__init__c                 C   s   | j j| j| j| dd}|S )NT)inbounds)rN   geprW   r   )rY   re   r   r   r   r   rl   $  s    zStructure._get_ptr_by_indexc                 C   s   |  | j| S r`   )rl   r   )rY   rn   r   r   r   ro   (  s    zStructure._get_ptr_by_namec                 C   s$   | ds| | j|  S t|dS rp   )rq   r   rr   rs   r   r   r   ru   +  s    
zStructure.__getattr__c                    s.   | drtt| ||S || | j| < dS rv   )rq   rw   r   rx   r   ry   rz   r   r   rx   4  s    
zStructure.__setattr__c                 C   s   | j | |S r|   )rN   r}   rl   rk   r   r   r   r~   <  s    zStructure.__getitem__c                 C   sN   |  |}|jj|jkr<d}t||t|jjt|jf | j|| dS )r   z:Type mismatch: __setitem__(%d, ...) expected %r but got %rN)rl   r   rT   rR   r2   rN   rV   )rY   re   r   r   fmtr   r   r   r   C  s    

zStructure.__setitem__c                 C   s
   t | jS r   )r"   r   r   r   r   r   r   O  s    zStructure.__len__c                 C   s   | j S r   )rW   r   r   r   r   r   U  s    zStructure._getpointerc                 C   s   | j | jS r   )rN   r}   rW   r   r   r   r   r   [  s    zStructure._getvaluec                 C   s>   t |jrt|j| jks*t|j| jf| j|| j dS )z!Store the value in this structureN)rQ   r   rR   r   rN   rV   rW   r   r   r   r   r   a  s    zStructure._setvalue)NNF)r1   r   r   r   r\   rl   ro   ru   rx   r~   r   r   r   r   r   r   r   r   rz   r   r      s   
	r    Fc              
   C   s   t |trtt|}t| ^ |  & | j|||d}| 	|d| W 5 Q R X |rn| 	|j
d| |W  5 Q R  S Q R X dS )a  Allocate stack memory at the entry block of the current function
    pointed by ``builder`` with llvm type ``ty``.  The optional ``size`` arg
    set the number of element to allocate.  The default is 1.  The optional
    ``name`` arg set the symbol name inside the llvm IR for debugging.
    If ``zfill`` is set, fill the memory with zeros at the current
    use-site location.  Note that the memory is always zero-filled after the
    ``alloca`` at init-site (the entry block).
    )sizenameN)rH   intr   r#   intp_tr   Zsuspend_emissionZgoto_entry_blockZallocarV   r   rT   )r   tyr   r   r^   r   r   r   r   r_   j  s    	

r_   c                 C   s$   |d}| tdg}| |tS )zCompute sizeof using GEP
    Nr	   )r   r   ptrtointr   )r   Zptr_typenulloffsetr   r   r   sizeof  s    r   c                 C   s    t | |j|d}| || |S )z
    Like alloca_once(), but passing a *value* instead of a type.  The
    type is inferred and the allocated slot is also initialized with the
    given value.
    r]   )r_   r   rV   )r   r   r   r^   Zstorager   r   r   alloca_once_value  s    r   c                 C   s(   t | ||}|jd |jd |S )z_
    Insert a pure function (in the functional programming sense) in the
    given module.
    readonlyZnounwind)get_or_insert_function
attributesaddmodulefntyr   fnr   r   r   insert_pure_function  s    r   c                 C   s(   | j |d}|dkr$t| ||}|S )zm
    Get the function named *name* with type *fnty* from *module*, or insert it
    if it doesn't exist.
    N)globalsr.   r   Functionr   r   r   r   r     s    r   c                 C   s0   z|  |W S  tk
r*   | | Y S X d S r`   )Zget_named_metadataKeyErrorZadd_named_metadata)r   r   r   r   r   get_or_insert_named_metadata  s    r   c                 C   s   |  |}t| |||S r`   )Zget_unique_namer   ZGlobalVariable)r   r   r   r   Zunique_namer   r   r   add_global_variable  s    
r   c                 C   s   | j }|jd kr| | d S r`   )basic_block
terminatorbranch)r   bbendZbbr   r   r   	terminate  s    
r   c                 C   s   | d S r`   r   )Zltyper   r   r   get_null_value  s    r   c                 C   s   t |j}| d||S )N==r   r   r   r   rf   r   r   r   r   is_null  s    
r   c                 C   s   t |j}| d||S )Nr   r   r   r   r   r   is_not_null  s    
r   c                 C   s   | j |ddS )NFlikelyif_thenr   predr   r   r   if_unlikely  s    r   c                 C   s   | j |ddS )NTr   r   r   r   r   r   	if_likely  s    r   c                 C   s   |  | |S r`   )r   not_r   r   r   r   ifnot  s    r   c                 C   s   | d}| j||dgdS )z#
    Increment an index *val*.
    r	   Znsw)flags)r   r   )r   rf   oner   r   r   increment_index  s    
r   Loop)re   do_breakc              	   #   s   |dkr|j }|dkr|d}|}d}d}d  fdd}j}| |0 j|dd	}	d
|	|}
|
|  W 5 Q R X |, t|	|V  j}t	|	}t
| W 5 Q R X |	|| |	||   dS )a  
    Generate LLVM IR for a for-loop in [start, count).
    *start* is equal to 0 by default.

    Yields a Loop namedtuple with the following members:
    - `index` is the loop index's value
    - `do_break` is a no-argument callable to break out of the loop
    Nr   for.condfor.bodyfor.endc                      s      d S r`   )r   r   r   r   r   r   r     s    zfor_range.<locals>.do_break
loop.indexr   <)r   append_basic_blockr   r   
goto_blockphiicmp_signedcbranchr   r   r   add_incomingposition_at_end)r   countstartintpstopbbcondbbbodyr   bbstartre   r   incrr   r   r   	for_range  s.    





r   Tc              	   c   s*  |dkr|j }| d}| d}| d}| j}	| | | |R | j|dd}
| j|dd}|rx| d|
|}n| d	|
|}| ||| W 5 Q R X | |6 |
|fV  | j}| |
|}t	| |}t
| | W 5 Q R X |
||	 |
|| |t|d
|	 ||| | | dS )a[  
    Generate LLVM IR for a for-loop based on a slice.  Yields a
    (index, count) tuple where `index` is the slice index's value
    inside the loop, and `count` the iteration count.

    Parameters
    -------------
    builder : object
        IRBuilder object
    start : int
        The beginning value of the slice
    stop : int
        The end value of the slice
    step : int
        The step value of the slice
    intp :
        The data type
    inc : boolean, optional
        Signals whether the step is positive (True) or negative (False).

    Returns
    -----------
        None
    Nr   r   r   r   r   z
loop.countr   >r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r#   r   )r   r   r   stepr   incr   r   r   r   re   r   r   r   Z
next_countr   r   r   for_range_slice  s2    





r   c              	   c   s   |j }| d|t|d}t| ||||dd}t| ||||dd}tdd }| j|dd \}	}
||	|||
|fV  W 5 Q R X d	S )
a  
    A helper wrapper for for_range_slice().  This is a context manager which
    yields two for_range_slice()-alike context managers, the first for
    the positive step case, the second for the negative step case.

    Use:
        with for_range_slice_generic(...) as (pos_range, neg_range):
            with pos_range as (idx, count):
                ...
            with neg_range as (idx, count):
                ...
    >=r   T)r   Fc              
   s   s*   |  |}|V  W 5 Q R X W 5 Q R X d S r`   r   )condZinner_cmr   r   r   r   cm_cond`  s    z(for_range_slice_generic.<locals>.cm_condr   N)r   r   r   r#   r   r   if_else)r   r   r   r   r   Zis_pos_stepZpos_for_rangeZneg_for_ranger   then	otherwiser   r   r   for_range_slice_genericL  s    
r   Cc              	   c   sp   |dkst |sdV  nT|dkr*dd }ndd }t| |||$}t|t|ksXt ||V  W 5 Q R X dS )a  
    Generate a loop nest walking a N-dimensional array.
    Yields a tuple of N indices for use in the inner loop body,
    iterating over the *shape* space.

    If *order* is 'C' (the default), indices are incremented inside-out
    (i.e. (0,0), (0,1), (0,2), (1,0) etc.).
    If *order* is 'F', they are incremented outside-in
    (i.e. (0,0), (1,0), (2,0), (0,1) etc.).
    This has performance implications when walking an array as it impacts
    the spatial locality of memory accesses.
    CFr   Fc                 S   s   | d d d S )Nr   xr   r   r   <lambda>~      zloop_nest.<locals>.<lambda>c                 S   s   | S r`   r   r   r   r   r   r     r   N)rR   
_loop_nestr"   )r   shaper   orderZ_swapindicesr   r   r   	loop_nestj  s    
r  c              
   c   sh   t | |d |dL}t|dkrPt| |dd  |}|jf| V  W 5 Q R X n
|jfV  W 5 Q R X d S )Nr   r   r	   )r   r"   r   re   )r   r   r   loopr   r   r   r   r     s
    r   c                 C   sP   t |}|dkr|d j}t||tj}t|D ]\}}| |||}q4|S )z
    Pack a sequence of values in a LLVM array.  *ty* should be given
    if the array may be empty, in which case the type can't be inferred
    from the values.
    Nr   )r"   r   r   r$   r   r   r   )r   r   r   r(   aryr   r   r   r   r   
pack_array  s    
r  c                 C   sB   t dd |D }|t j}t|D ]\}}| |||}q&|S )z7
    Pack a sequence of values into a LLVM struct.
    c                 S   s   g | ]
}|j qS r   r   r   r   r   r   r     s     zpack_struct.<locals>.<listcomp>r   )r   r   Zstructtystr   r   r   r   r   pack_struct  s
    
r  c                    s0   |dkrt jj} fddt|D }|S )zH
    Unpack an array or structure of values, return a Python tuple.
    Nc                    s   g | ]}  |qS r   )extract_value)r   r   r   tupr   r   r     s   z unpack_tuple.<locals>.<listcomp>)r"   r   elementsrange)r   r
  r   valsr   r	  r   unpack_tuple  s    r  c           	      C   sB   t ||j|jd}t ||j|jd}t| ||j|||j|||d	S )N)r   )r*   r   strideslayoutinds
wraparoundboundscheck)r  r   ndimr  get_item_pointer2r*   r  )	rZ   r   Zarytyr  r  r  r  Zshapesr  r   r   r   get_item_pointer  s       r  c           	   	      s    fdd}d} d}t|$ tjr<|  | jt|f W 5 Q R X  dd}t|$ tjr|  | jt|f W 5 Q R X d S )Nc                      sL    d k	r:t  tr(td  qHtd  ntd d S )NzFdebug: IndexError: index %d is out of bounds for axis {} with size %d
zFdebug: IndexError: index %d is out of bounds for axis %d with size %d
z9debug: IndexError: index %d is out of bounds for size %d
)rH   r   printfrM   r   axisr   dimlenindr   r   _dbg  s$    
   zdo_boundscheck.<locals>._dbgzindex is out of boundsr   r   r   )r   r   r   ZFULL_TRACEBACKS	call_convreturn_user_exc
IndexErrorr   )	rZ   r   r  r  r  r  msgZout_of_bounds_upperZout_of_bounds_lowerr   r  r   do_boundscheck  s    r!  c	                    s  |rVg }	t ||D ]@\}
} d|
|
d} ||
} |||
}|	| qn|}	|rtt |	|D ]\}\}
}t|  |
|| ql|	s |t	dgS |	d j}|dkrg }|dkr
t
t|D ]8}|d}||d d  D ]} ||}q|| qnZ|dkr\t
t|D ]8}|d}|d | D ]} ||}q8|| q ntd|d}t |	|D ]"\}} ||} ||}qv ||g}|S  fdd	t ||	D }t j|}t ||S d S )
Nr   r   r   r   r	   r   Zunreachablec                    s   g | ]\}}  ||qS r   )mul)r   sr   r   r   r   r     s     z%get_item_pointer2.<locals>.<listcomp>)zipr   r   r   selectr   r   r!  r   r   r  r"   r"  	Exception	functoolsreducepointer_add)rZ   r   r*   r   r  r  r  r  r  r   r  r  negativewrappedselectedr  r   Zstepsr   lastjlocr#  tmpr   Zdimoffsr   r   r$  r   r    sL    



r  c                 C   s\   | d}t|j tjtjfr*|||}n.t|j tjrH| |||}ntd|j f |S )Nr   zunexpected value type %s)r   rH   r   Z	FloatTypeZ
DoubleTyper%   r   rL   )r   r   ZfpredZicondZnullvalZisnullr   r   r   _scalar_pred_against_zero  s    
r2  c                 C   s   t | |t| jddS )zK
    Return a predicate representing whether *value* is equal to zero.
    r   r2  r(  partialZfcmp_orderedr   r   r   r   is_scalar_zero%  s       r5  c                 C   s   t | |t| jddS )z
    Return a predicate representing whether a *value* is not equal to zero.
    (not exactly "not is_scalar_zero" because of nans)
    r   r2  r(  r4  Zfcmp_unorderedr   r   r   r   is_not_scalar_zero-  s       r7  c                 C   s   t | |t| jddS )z]
    Return a predicate representing whether *value* is equal to either zero
    or NaN.
    r   r6  r   r   r   r   is_scalar_zero_or_nan6  s       r8  c                 C   s   t | |t| jddS )z:
    Is *value* negative?  Assumes *value* is signed.
    r   r3  r   r   r   r   is_scalar_negC  s       r9  )stackc              	   c   s<   | | j|dd\}}| dV  W 5 Q R X | | dS )a  
    The Python code::

        with contextlib.ExitStack() as stack:
            with early_exit_if(builder, stack, cond):
                cleanup()
            body()

    emits the code::

        if (cond) {
            <cleanup>
        }
        else {
            <body>
        }

    This can be useful for generating code with lots of early exits, without
    having to increase the indentation each time.
    Fr   N)enter_contextr   )r   r:  r   r   r   r   r   r   early_exit_ifK  s    r<  c                 C   s   t | |t| |S )z
    A convenience wrapper for :func:`early_exit_if`, for the common case where
    the CPython API indicates an error by returning ``NULL``.
    )r<  r   )r   r:  objr   r   r   early_exit_if_nullg  s    r>  c              	   C   sL   |j t||dd. |d }|dd p,d}| j||| W 5 Q R X dS )zu
    Guard against *value* being null or zero.
    *exc_tuple* should be a (exception type, arguments...) tuple.
    Fr   r   r	   N)r   r5  r  r  )rZ   r   r   	exc_tupleexcexc_argsr   r   r   
guard_nullo  s    rB  c              	   C   sZ   t |jtjst|j|r"|fnd}|jt||dd | j|t	| W 5 Q R X dS )zG
    Guard against *pointer* being NULL (and raise a MemoryError).
    r   Fr   N)
rH   r   r   PointerTyperR   r   r   r  r  MemoryError)rZ   r   Zpointerr   rA  r   r   r   guard_memory_errorz  s    rE  c              	   c   s*   | j t| ||d dV  W 5 Q R X dS )z>
    Execute the given block if the scalar value is zero.
    r   N)r   r5  )r   r   r   r   r   r   if_zero  s    rF  c                 C   s   t | tjS )z7
    Whether the LLVM type *typ* is a struct type.
    )rH   r   rC  )Zltypr   r   r   rQ     s    rQ   c                 C   s.   t | |d|}t|jjrt| || S ri   )rj   rQ   r   rT   rR   r   rU   )r   recordr   typZpvalr   r   r   get_record_member  s    rI  c                 C   s   |  d||dS )Nr   r   )r   r   )r   rf   r   r   r   
is_neg_int  s    rJ  c                 O   s   t | |f|ddi|S )z8
    Same as *gep*, but add the `inbounds` keyword.
    r   T)r   )r   r   r  kwsr   r   r   rj     s    rj   c           	      O   sb   | dd}| dd}|r tg }|D ]&}t|tr@t|}n|}|| q(| j||||dS )z
    Emit a getelementptr instruction for the given pointer and indices.
    The indices can be LLVM values or Python int constants.
    r   r   r   F)r   r   )r=   rR   rH   r   r   r   r   )	r   r   r  rK  r   r   idxr   r  r   r   r   r     s    

r   c                 C   s<   |  |t}t|trt|}| ||}| ||p8|jS )z
    Add an integral *offset* to pointer *ptr*, and return a pointer
    of *return_type* (or, if omitted, the same type as *ptr*).

    Note the computation is done in bytes, and ignores the width of
    the pointed item type.
    )r   r   rH   r   r   Zinttoptrr   )r   r   r   return_typeZintptrr   r   r   r*    s
    
r*  c                 C   sN   | j dt|jf}| |t}t|tr2t|}| ||||t	dg dS )z=
    Fill *size* bytes starting from *ptr* with *value*.
    zllvm.memsetr   N)
r   declare_intrinsic	voidptr_tr   r   rH   r   int8_tcallbool_t)r   r   r   r   r   r   r   r   memset  s
    
rS  c                 C   s0   |  |}t| |t| |jd | || dS )z7
    Fill padding bytes of the pointee with zeros.
    r   N)r}   rS  r   r   rV   )r   r   rf   r   r   r   memset_padding  s    
rT  internalc                 C   s<   t | tjr| }n| j}t||j|}||_d|_||_|S )zO
    Get or create a (LLVM module-)global constant with *name* or *value*.
    T)	rH   r   Moduler   r   r   linkageglobal_constantZinitializer)Zbuilder_or_moduler   r   rW  r   r*   r   r   r   rX    s    rX  c           
   
   C   s   |dkst ||}|d}t| |j}| t| |n\}}| | ||}| || W 5 Q R X |2 | ||}| ||}| | ||| W 5 Q R X W 5 Q R X | 	|}| || 
||}	||	fS )a  
    Compute the (quotient, remainder) of *val* divided by the constant
    positive *divisor*.  The semantics reflects those of Python integer
    floor division, rather than C's / LLVM's signed division and modulo.
    The difference lies with a negative *val*.
    r   r	   )rR   r   r_   r   rJ  ZsdivrV   r   subr}   r"  )
r   rf   Zdivisorr   quotZif_negZif_posZquot_valZval_plus_oneZrem_valr   r   r   divmod_by_constant  s    

(
r[  c                 C   s&   |  d}| ||| | | |S )z
    Branch conditionally or continue.

    Note: a new block is created and builder is moved to the end of the new
          block.
    z	.continue)r   r   r   )r   r   ZbbtrueZbbcontr   r   r   cbranch_or_continue  s    

r\  c              	   C   sb   |j |j kstt| ||j d8}| ||jg}| ||jg}| | || W 5 Q R X dS )z
    Emit a memcpy to the builder.

    Copies each element of dst to src. Unlike the C equivalent, each element
    can be any LLVM type.

    Assumes
    -------
    * dst.type == src.type
    * count is positive
    r  N)r   rR   r   r   re   rV   r}   )r   rA   rB   r   r  Zout_ptrZin_ptrr   r   r   memcpy  s
    r]  c           
   	   C   sd   |j }t|trt||}| j|tt|g}t}	| 	|| 
|t| 
|t| |||	g d S r`   )r   rH   r   r   r#   r   rN  rO  	false_bitrQ  r   r"  )
r   	func_namerA   rB   r   itemsizealignZsize_tr]  Zis_volatiler   r   r   _raw_memcpy1  s    


rb  c                 C   s   t | d|||||S )za
    Emit a raw memcpy() call for `count` items of size `itemsize`
    from `src` to `dest`.
    zllvm.memcpyrb  r   rA   rB   r   r`  ra  r   r   r   
raw_memcpy?  s    re  c                 C   s   t | d|||||S )zb
    Emit a raw memmove() call for `count` items of size `itemsize`
    from `src` to `dest`.
    zllvm.memmoverc  rd  r   r   r   raw_memmoveG  s     rf  c           
      C   sX   |  ||}| |d}| |d}| ||}| |d}| || |d}	||	fS )zq
    Compute (a * b + c) and return a (result, overflow bit) pair.
    The operands must be signed integers.
    r   r	   )Zsmul_with_overflowr  Zsadd_with_overflowor_)
r   ar'   cpprodZprod_ovfr#  r6   Zovfr   r   r   muladd_with_overflowP  s    rl  c           
      G   s   t |tst| j}t}t|d d}t|d|}tj	t
|gdd}z|d}W n$ tk
rz   tj||dd}Y nX | ||}	| ||	gt| S )a  
    Calls printf().
    Argument `format` is expected to be a Python string.
    Values to be printed are listed in `args`.

    Note: There is no checking to ensure there is correct number of values
    in `args` and there type matches the declaration in the format string.
     asciiZprintf_formatTZvar_argr  r   )rH   r2   rR   r   rO  r)   encoderX  r   FunctionTyper   
get_globalr   r   r   rQ  list)
r   rM   argsmodcstring	fmt_bytes
global_fmtr   r   ptr_fmtr   r   r   r  ^  s    	r  c                 G   s   t |tst| j}t}t|d d}t|d|}tj	t
|t|gdd}	d}
tjr^d|
 }
z||
}W n$ tk
r   tj||	|
d}Y nX | ||}| ||||gt| S )	z8Calls libc snprintf(buffer, bufsz, format, ...args)
    rm  rn  Zsnprintf_formatTro  snprintfr+   r   )rH   r2   rR   r   rO  r)   rp  rX  r   rq  r   r   r   ZIS_WIN32rr  r   r   r   rQ  rs  )r   bufferbufszrM   rt  ru  rv  rw  rx  r   symbolr   ry  r   r   r   rz  x  s&      rz  c                 G   sV   t |tstttd|}t| |dd}| |t}t	| |t
||f|  |S )z{Similar to `snprintf()` but the buffer is stack allocated to size
    *bufsz*.

    Returns the buffer pointer as i8*.
    r
   Tr]   )rH   r   rR   r   r$   r%   r_   r   rO  rz  r   )r   r|  rM   rt  Zspacetyspacer{  r   r   r   snprintf_stackbuffer  s    r  c                 C   s   |  ddS )zk
    Normalize the given string to latin1 compatible encoding that is
    suitable for use in LLVM IR.
    utf8latin1)rp  decode)textr   r   r   normalize_ir_text  s    r  c           
   
   C   s   d}|  |t}t| d|| td}| || }t| |p}| |j	t|}| 
d|td}| | t| d W 5 Q R X | ||j	g}| |}	t| d|	 W 5 Q R X t| d dS )	zIDebug print the memory region in *ptr* to *ptr + nbytes*
    as hex.
       zhexdump p=%p n=%zur
   r   r   
z %02xN)Zzextr   r  r   r%   r   rU   r   Zuremre   r   r   r   r}   )
r   r   nbytesZbytes_per_lineZbyte_trL  Zdiv_byZdo_new_liner   rf   r   r   r   hexdump  s"     

r  c                 C   s    | dkpt | tjpt | tjS )z returns if 'ty' is none N)rH   r   ZNoneTypeZOmitted)r   r   r   r   is_nonelike  s
    

r  c                 C   s   t t | t||S )z
    Create an LLVM-constant of a fixed-length array from Python values.

    The type provided is the type of the elements.
    )r   r#   r$   r"   )r   rf   r   r   r   create_constant_array  s    r  )N)r   )Nr   F)r   F)r   )NN)NT)r   )N)N)FF)N)FF)N)F)N)rU  )r	   )r	   )fr   collections
contextlibr   r   r(  Zllvmliter   Z
numba.corer   r   r   r   Znumba.core.datamodelrI   r%   rR  rP  r   ZMACHINE_BITSr   rU   rO  Ztrue_bitr^  Z	true_byteZ
false_byter   r    r)   r-   r9   rE   objectrF   r/   r0   r   r_   r   r   r   r   r   r   r   r   r   r   r   r   r   r   
namedtupler   r   r   r   r  r   r  r  r  r  r!  r  r2  r5  r7  r8  Zis_trueZis_falser9  r<  r>  rB  rE  rF  Z
guard_zerorQ   rI  rJ  rj   r   r*  rS  rT  rX  r[  r\  r]  rb  re  rf  rl  r  rz  r  r  r  r  r  r   r   r   r   <module>   s   



	
 l


+9

	

  

   
:		





			