o
    8ήcʔ                     @   s6  d Z ddlZddl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 Z/d4d5 Z0d6d7 Z1d8d9 Z2d:d; Z3e4d<d=Z5edd>d?Z6eddAdBZ7edCdD Z8eddFdGZ9edHdI Z:ddJdKZ;dLdM Z<ddNdOZ=		ddPdQZ>ddRdSZ?	ddTdUZ@dVdW ZAdXdY ZBdZd[ ZCd\d] ZDeCZEeBZFd^d_ ZGd`da ZHddbdcZIeddddeZJeHZKdfdg ZLdhdi ZMdjdk ZNdldm ZOdndo ZPddpdqZQdrds ZRdtdu ZSddwdxZTdydz ZUd{d| ZVd}d~ ZWdd ZXdddZYdddZZdd Z[dd Z\dd Z]dd Z^dd Z_dd Z`dd Zadd ZbdS )z+
Generic helpers for LLVM code generation.
    N)contextmanager)ir)utilstypesconfig	debuginfo          c                 C      |  d||dS )N!=r   )icmp_unsignedtypebuildervalue r   9/tmp/pip-target-vg8gfxp4/lib/python/numba/core/cgutils.pyas_bool_bit      r   c                 C   sJ   |du rt dd |D }|t j}t|D ]\}}| |||}q|S )zH
    Create an anonymous struct containing the given LLVM *values*.
    Nc                 S      g | ]}|j qS r   r   .0vr   r   r   
<listcomp>%       z)make_anonymous_struct.<locals>.<listcomp>r   LiteralStructType	Undefined	enumerateinsert_value)r   valuesstruct_type
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u 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   )fe_typekind	cache_keyresbaseclsnamebases
clsmembersr   r   r   create_struct_proxy8   s   

rB   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   rN   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st	d
| j|| _| | j| _t| jr-J | |\}}|jj| jkrGtd| j |jf |d urd|j|jjkr]t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)_contextdata_model_managerr2   rD   
isinstancenumbacore	datamodelStructModel	TypeErrorformat_builder_get_be_type_be_type
is_pointer
_make_refsr   pointeeAssertionError
as_pointerstore_value
_outer_ref)selfcontextr   r   ref	outer_refr   r   r   __init__c   s,   

z_StructProxy.__init__c                 C   s"   |du 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_oncerY   r[   )rd   rf   r   r   r   r]   |   s   z_StructProxy._make_refsc                 C      t NNotImplementedErrorrd   rU   r   r   r   rZ         z_StructProxy._get_be_typec                 C   rl   rm   rn   rd   indexvalr   r   r   _cast_member_to_value   rq   z"_StructProxy._cast_member_to_valuec                 C   rl   rm   rn   rr   r   r   r   _cast_member_from_value   rq   z$_StructProxy._cast_member_from_valuec                 C   s   t | j| jd|S Nr   )gep_inboundsrY   rb   rd   rs   r   r   r   _get_ptr_by_index   s   z_StructProxy._get_ptr_by_indexc                 C   s   | j |}| |S rm   )rD   get_field_positionrz   )rd   attrnamers   r   r   r   _get_ptr_by_name   s   
z_StructProxy._get_ptr_by_namec                 C   s"   | ds| | j| S t|z;
        Load the LLVM value of the named *field*.
        r1   )
startswithrD   r{   AttributeErrorrd   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*.
        r1   N)r   superrO   __setattr__rD   r{   rd   r   r   	__class__r   r   r      s   
z_StructProxy.__setattr__c                 C   s   | j | |}| ||S z>
        Load the LLVM value of the field at *index*.
        )rY   loadrz   ru   )rd   rs   
member_valr   r   r   __getitem__   s   z_StructProxy.__getitem__c                 C   s   |  |}| ||}|j|jjkr>t|jr3t|jjr3|jj|jjjkr3| 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   ptrrd   rs   N)rz   rv   r   r^   r\   rP   addrspacecastrY   	addrspacerW   rX   ra   )rd   rs   r   r   r   r   r   __setitem__   s   

z_StructProxy.__setitem__c                 C   s   | j jS z.
        Return the number of fields.
        )rD   field_countrd   r   r   r   __len__   s   z_StructProxy.__len__c                 C      | j S zF
        Return the LLVM pointer to the underlying structure.
        )rc   r   r   r   r   _getpointer      z_StructProxy._getpointerc                 C      | j | jS zM
        Load and return the value of the underlying LLVM structure.
        )rY   r   rc   r   r   r   r   	_getvalue      z_StructProxy._getvaluec                 C   >   t |jrJ |j| jksJ |j| jf| j|| j dS )z4
        Store the value in this structure.
        N)r\   r   r[   rY   ra   rb   rd   r   r   r   r   	_setvalue   s   z_StructProxy._setvalueNN)r7   
__module____qualname____doc__r2   rh   r]   rZ   ru   rv   rz   r}   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   rO   Z   s$    
		rO   c                   @   (   e Zd ZdZdd Zdd Zdd ZdS )	r5   zl
    Create a StructProxy suitable for accessing regular values
    (e.g. LLVM values or alloca slots).
    c                 C      |  S rm   )get_value_typerp   r   r   r   rZ         zValueStructProxy._get_be_typec                 C      |S rm   r   rr   r   r   r   ru      rq   z&ValueStructProxy._cast_member_to_valuec                 C   r   rm   r   rr   r   r   r   rv      rq   z(ValueStructProxy._cast_member_from_valueNr7   r   r   r   rZ   ru   rv   r   r   r   r   r5      s
    r5   c                   @   r   )	r6   zO
    Create a StructProxy suitable for accessing data persisted in memory.
    c                 C   r   rm   )get_data_typerp   r   r   r   rZ      r   zDataStructProxy._get_be_typec                 C      | j |}|| j|S rm   )rD   	get_model	from_datarY   rd   rs   rt   modelr   r   r   ru         z%DataStructProxy._cast_member_to_valuec                 C   r   rm   )rD   r   as_datarY   r   r   r   r   rv      r   z'DataStructProxy._cast_member_from_valueNr   r   r   r   r   r6      s
    r6   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 u r:t|| jdd| _|d ur9t|jr$J |j| jks2J |j| jf||| j n.|d u s@J t|jsGJ | j|jj	kre|rZ|
|| j }ntd|jj	| jf || _i | _g | _g | _td}t| jD ]\}\}}	|| j|< | j|t|f | j|	 qzd S )NTri   z-mismatching pointer type: got %s, expected %sr   )get_struct_type_typerP   rY   rk   rb   r\   r   ra   r^   bitcastr`   rW   _namemap_fdmap_typemapint32_tr    rE   append)
rd   re   r   r   rf   cast_refr>   r%   rM   tpr   r   r   rh     s<   
zStructure.__init__c                 C   s   | j j| j| j| dd}|S )NT)inbounds)rY   geprb   r   )rd   rs   r   r   r   r   rz   $  s   zStructure._get_ptr_by_indexc                 C   s   |  | j| S rm   )rz   r   )rd   r|   r   r   r   r}   (     zStructure._get_ptr_by_namec                 C   s    | ds| | j|  S t|r~   )r   r   r   r   r   r   r   r   +  s   
zStructure.__getattr__c                    s.   | drtt| ||S || | j| < dS r   )r   r   r   r   r   r   r   r   r   r   4  s   
zStructure.__setattr__c                 C   s   | j | |S r   )rY   r   rz   ry   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)rz   r   r^   r_   r8   rY   ra   )rd   rs   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   r   r   )rb   r   r   r   r   r   U  r   zStructure._getpointerc                 C   r   r   )rY   r   rb   r   r   r   r   r   [  r   zStructure._getvaluec                 C   r   )z!Store the value in this structureN)r\   r   r   rY   ra   rb   r   r   r   r   r   a  s   zStructure._setvalue)NNF)r7   r   r   r   rh   rz   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s    
	r    Fc              	   C   s   t |trtt|}t| : |   | j|||d}| 	|d| W d   n1 s0w   Y  |rA| 	|j
d| |W  d   S 1 sMw   Y  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)rR   intr   r)   intp_tr   suspend_emissiongoto_entry_blockallocara   r   r^   )r   tyr   r   rj   r   r   r   r   rk   j  s   
	
$rk   c                 C   s$   |d}| tdg}| |tS )zCompute sizeof using GEP
    Nr   )r   r   ptrtointr   )r   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.
    ri   )rk   r   ra   )r   r   r   rj   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.
    readonlynounwind)get_or_insert_function
attributesaddmodulefntyr   fnr   r   r   insert_pure_function  s   r   c                 C   s(   | j |d}|du rt| ||}|S )zm
    Get the function named *name* with type *fnty* from *module*, or insert it
    if it doesn't exist.
    N)globalsr4   r   Functionr   r   r   r   r     s   r   c                 C   s*   z|  |W S  ty   | | Y S w rm   )get_named_metadataKeyErroradd_named_metadata)r   r   r   r   r   get_or_insert_named_metadata  s
   r   c                 C   s   |  |}t| |||S rm   )get_unique_namer   GlobalVariable)r   r   r   r   unique_namer   r   r   add_global_variable  s   
r   c                 C   s"   | j }|jd u r| | d S d S rm   )basic_block
terminatorbranch)r   bbendbbr   r   r   	terminate  s   
r   c                 C   s   | d S rm   r   )ltyper   r   r   get_null_value  r   r   c                 C      t |j}| d||S )N==r   r   r   r   rt   r   r   r   r   is_null     
r   c                 C   r   )Nr   r   r   r   r   r   is_not_null  r   r   c                 C      | j |ddS )NFlikelyif_thenr   predr   r   r   if_unlikely     r   c                 C   r   )NTr   r   r   r   r   r   	if_likely  r   r   c                 C   s   |  | |S rm   )r   not_r   r   r   r   ifnot  r   r  c                 C   s   | d}| j||dgdS )z#
    Increment an index *val*.
    r   nsw)flags)r   r   )r   rt   oner   r   r   increment_index  s   
r  Loop)rs   do_breakc                 #   s*   |du r|j }|du r|d}|}d}d}d  fdd}j}| | j|dd	}	d
|	|}
|
|  W d   n1 sUw   Y  | t|	|V  j}t	|	}t
| W d   n1 s}w   Y  |	|| |	||   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 rm   )r   r   r   r   r   r   r    r   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  bbstartrs   r   incrr   r  r   	for_range  s4   





r  Tc                 c   sT   |du r|j }| d}| d}| d}| j}	| | | |. | j|dd}
| j|dd}|r=| d|
|}n| d	|
|}| ||| W d   n1 sUw   Y  | |  |
|fV  | j}| |
|}t	| |}t
| | W d   n1 sw   Y  |
||	 |
|| |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  rs   r  r   r  
next_countr   r   r   for_range_slice  s8   



	

r$  c                 c   s    |j }| d|t|d}t| ||||dd}t| ||||dd}tdd }| j|dd\}	}
||	|||
|fV  W d	   d	S 1 sIw   Y  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   sf    | & |}|V  W d    n1 sw   Y  W d    d S W d    d S 1 s,w   Y  d S rm   r   )cond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  is_pos_steppos_for_rangeneg_for_ranger(  then	otherwiser   r   r   for_range_slice_genericL  s   
"r/  Cc                 c   s    |dv sJ |sdV  dS |dkrdd }ndd }t | |||}t|t|ks.J ||V  W d   dS 1 s>w   Y  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>~  s    zloop_nest.<locals>.<lambda>c                 S   s   | S rm   r   r4  r   r   r   r6    s    N)
_loop_nestr(   )r   shaper  order_swapindicesr   r   r   	loop_nestj  s   

"r<  c              	   c   s    t | |d |d>}t|dkr3t| |dd  |}|jf| V  W d    n1 s-w   Y  n|jfV  W d    d S W d    d S 1 sKw   Y  d S )Nr   r  r   )r  r(   r7  rs   )r   r8  r  loopr;  r   r   r   r7    s   " r7  c                 C   sP   t |}|du r|d j}t||tj}t|D ]\}}| |||}q|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   r   r   r   r   r   r   r   r     r   zpack_struct.<locals>.<listcomp>r   )r   r"   structtystr%   r   r   r   r   pack_struct  s
   
rC  c                    s0   |du 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   rF  r  valsr   rE  r   unpack_tuple  s   rJ  c           	      C   sB   t ||j|jd}t ||j|jd}t| ||j|||j|||d	S )N)r  )r0   r8  strideslayoutinds
wraparoundboundscheck)rJ  r8  ndimrK  get_item_pointer2r0   rL  )	re   r   arytyr?  rM  rN  rO  shapesrK  r   r   r   get_item_pointer  s   rT  c           	         s    fdd}d} d}t| tjr|  | jt|f W d    n1 s1w   Y   dd}t| tjrL|  | jt|f W d    d S 1 s`w   Y  d S )Nc                      sP    d urt  trtd  d S td  d S 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
)rR   r   printfrX   r   axisr   dimlenindr   r   _dbg  s   

zdo_boundscheck.<locals>._dbgzindex is out of boundsr%  r  r   )r  r   r   FULL_TRACEBACKS	call_convreturn_user_exc
IndexErrorr   )	re   r   rY  rX  rW  rZ  msgout_of_bounds_upperout_of_bounds_lowerr   rV  r   do_boundscheck  s   "rb  c	                    s  |r+g }	t ||D ] \}
} d|
|
d} ||
} |||
}|	| q	n|}	|rEtt |	|D ]\}\}
}t|  |
|| q6|	sP |t	dgS |	d j}|dv rg }|dkrt
t|D ]}|d}||d d  D ]} ||}qs|| qen*|dkrt
t|D ]}|d}|d | D ]} ||}q|| qntd|d}t |	|D ]\}} ||} ||}q ||g}|S  fdd	t ||	D }t j|}t ||S )
Nr  r   r1  r0  r   r2  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    rb  r   r   rH  r(   rd  	Exception	functoolsreducepointer_add)re   r   r0   r8  rK  rL  rM  rN  rO  r;  rY  rX  negativewrappedselectedrW  r  stepsr%   lastjlocre  tmpr   dimoffsr   r   rf  r   rQ    sR   
rQ  c                 C   s\   | d}t|j tjtjfr|||}|S t|j tjr&| |||}|S td|j f )Nr   zunexpected value type %s)r   rR   r   	FloatType
DoubleTyper+   r  rW   )r   r   fpredicondnullvalisnullr   r   r   _scalar_pred_against_zero  s   

r|  c                 C      t | |t| jddS )zK
    Return a predicate representing whether *value* is equal to zero.
    r   r|  rj  partialfcmp_orderedr   r   r   r   is_scalar_zero%     r  c                 C   r}  )z
    Return a predicate representing whether a *value* is not equal to zero.
    (not exactly "not is_scalar_zero" because of nans)
    r   r|  rj  r  fcmp_unorderedr   r   r   r   is_not_scalar_zero-     r  c                 C   r}  )z]
    Return a predicate representing whether *value* is equal to either zero
    or NaN.
    r   r  r   r   r   r   is_scalar_zero_or_nan6  r  r  c                 C   r}  )z:
    Is *value* negative?  Assumes *value* is signed.
    r  r~  r   r   r   r   is_scalar_negC  r  r  c                 C   sb   |j t||dd |d }|dd pd}| j||| W d   dS 1 s*w   Y  dS )zu
    Guard against *value* being null or zero.
    *exc_tuple* should be a (exception type, arguments...) tuple.
    Fr   r   r   N)r   r  r\  r]  )re   r   r   	exc_tupleexcexc_argsr   r   r   
guard_nullK  s
   "r  c                 C   sp   t |jtjsJ |j|r|fnd}|jt||dd | j|t| W d   dS 1 s1w   Y  dS )zG
    Guard against *pointer* being NULL (and raise a MemoryError).
    r   Fr   N)	rR   r   r   PointerTyper   r   r\  r]  MemoryError)re   r   pointerr_  r  r   r   r   guard_memory_errorV  s
   "r  c                 c   sB    | j t| ||d dV  W d   dS 1 sw   Y  dS )z>
    Execute the given block if the scalar value is zero.
    r   N)r   r  )r   r   r   r   r   r   if_zero`  s   "r  c                 C   s   t | tjS )z7
    Whether the LLVM type *typ* is a struct type.
    )rR   r   r  )ltypr   r   r   r\   l  s   r\   c                 C   s.   t | |d|}t|jjrJ | || S rw   )rx   r\   r   r^   r   r`   )r   recordr   typpvalr   r   r   get_record_members  s   r  c                 C   r   )Nr  r   )r  r   )r   rt   r   r   r   
is_neg_inty  r   r  c                 O   s   t | |g|R ddi|S )z8
    Same as *gep*, but add the `inbounds` keyword.
    r   T)r   )r   r   rM  kwsr   r   r   rx   }  s   rx   c           	      O   sb   | dd}| dd}|rJ 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   )rF   rR   r   r   r   r   )	r   r   rM  r  r   r   idxr%   rY  r   r   r   r     s   

r   c                 C   s<   |  |t}t|trt|}| ||}| ||p|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   rR   r   r   inttoptrr   )r   r   r   return_typeintptrr   r   r   rl    s
   
rl  c                 C   sN   | j dt|jf}| |t}t|trt|}| ||||t	dg dS )z=
    Fill *size* bytes starting from *ptr* with *value*.
    zllvm.memsetr   N)
r   declare_intrinsic	voidptr_tr   r   rR   r   int8_tcallbool_t)r   r   r   r   r   r   r   r   memset  s
   
r  c                 C   s0   |  |}t| |t| |jd | || dS )z7
    Fill padding bytes of the pointee with zeros.
    r   N)r   r  r   r   ra   )r   r   rt   r   r   r   memset_padding  s   
r  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)	rR   r   Moduler   r   r   linkageglobal_constantinitializer)builder_or_moduler   r   r  r   r0   r   r   r   r    s   r  c           
   	   C   s  |dksJ | |}| d}t| |j }| t| |P\}}| | ||}| || W d   n1 s:w   Y  | | ||}| ||}| | ||| W d   n1 sbw   Y  W d   n1 sqw   Y  | |}| || 	||}	||	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   N)
r   rk   r)  r  sdivra   r   subr   rd  )
r   rt   divisorr  quotif_negif_posquot_valval_plus_one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&  bbtruebbcontr   r   r   cbranch_or_continue  s   

r  c                 C   sx   |j |j ksJ t| ||j d"}| ||jg}| ||jg}| | || W d   dS 1 s5w   Y  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   r  r   rs   ra   r   )r   rJ   rK   r  r>  out_ptr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 rm   )r   rR   r   r   r)   r   r  r  	false_bitr  r   rd  )
r   	func_namerJ   rK   r  itemsizealignsize_tr  is_volatiler   r   r   _raw_memcpy  s   



r  c                 C      t | d|||||S )za
    Emit a raw memcpy() call for `count` items of size `itemsize`
    from `src` to `dest`.
    zllvm.memcpyr  r   rJ   rK   r  r  r  r   r   r   
raw_memcpy  s   r  c                 C   r  )zb
    Emit a raw memmove() call for `count` items of size `itemsize`
    from `src` to `dest`.
    zllvm.memmover  r  r   r   r   raw_memmove#  s   r  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   )smul_with_overflowrD  sadd_with_overflowor_)
r   ar-   cpprodprod_ovfre  r=   ovfr   r   r   muladd_with_overflow,  s   r  c           
      G   s   t |tsJ | j}t}t|d d}t|d|}tjt	|gdd}z|
d}W n ty<   tj||dd}Y nw | ||}	| ||	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.
     asciiprintf_formatTvar_argrU  r  )rR   r8   r   r  r/   encoder  r   FunctionTyper   
get_globalr   r   r   r  list)
r   rX   argsmodcstring	fmt_bytes
global_fmtr   r   ptr_fmtr   r   r   rU  :  s   	rU  c                 G   s   t |tsJ | j}t}t|d d}t|d|}tjt	|t
|gdd}	d}
tjr/d|
 }
z||
}W n tyG   tj||	|
d}Y nw | ||}| ||||gt| S )	z8Calls libc snprintf(buffer, bufsz, format, ...args)
    r  r  snprintf_formatTr  snprintfr1   r  )rR   r8   r   r  r/   r  r  r   r  r   r   r   IS_WIN32r  r   r   r   r  r  )r   bufferbufszrX   r  r  r  r  r  r   symbolr   r  r   r   r   r  T  s$   r  c                 G   sX   t |tsJ ttd|}t| |dd}| |t}t| |t	||g|R   |S )zwSimilar to `snprintf()` but the buffer is stack allocated to size *bufsz*.

    Returns the buffer pointer as i8*.
    r	   Tri   )
rR   r   r   r*   r+   rk   r   r  r  r   )r   r  rX   r  spacetyspacer  r   r   r   snprintf_stackbuffern  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)r  decode)textr   r   r   normalize_ir_text{  s   r  c           
   	   C   s   d}|  |t}t| d|| td}| || }t| |G}| |j	t|}| 
d|td}| | t| d W d   n1 sIw   Y  | ||j	g}| |}	t| d|	 W d   n1 skw   Y  t| d dS )	zIDebug print the memory region in *ptr* to *ptr + nbytes*
    as hex.
       zhexdump p=%p n=%zur	   r   r   
Nz %02x)zextr   rU  r   r+   r   r`   r  uremrs   r   r   r   r   )
r   r   nbytesbytes_per_linebyte_tr  div_bydo_new_liner   rt   r   r   r   hexdump  s$   

	r  c                 C   s    | du pt | tjpt | tjS )z returns if 'ty' is none N)rR   r   NoneType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   rt   r   r   r   create_constant_array  s   r  rm   )r   )Nr   F)r   F)r   r   )NT)r0  )FF)F)r  )r   )cr   collections
contextlibr   rj  llvmliter   
numba.corer   r   r   r   numba.core.datamodelrS   r+   r  r  r   MACHINE_BITSr   r`   r  true_bitr  	true_byte
false_byter   r&   r/   r3   rB   rN   objectrO   r5   r6   r   rk   r   r   r   r   r   r   r   r   r   r   r   r   r  r  
namedtupler  r  r$  r/  r<  r7  r@  rC  rJ  rT  rb  rQ  r|  r  r  r  is_trueis_falser  r  r  r  
guard_zeror\   r  r  rx   r   rl  r  r  r  r  r  r  r  r  r  r  rU  r  r  r  r  r  r  r   r   r   r   <module>   s    



	
 
l

+9


	


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