B
     \J                 @   s.  d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	m
Z
mZ edd	Zed
ZeZdd ZedZedZedZedZdZeeZG dd deZG dd deZG dd deZeeegZee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"e!e"dZ#dd  Z$dS )!z3
Calling conventions for Numba-compiled functions.
    )
namedtupleN)ir)cgutilstypes   )PYOBJECTGENERIC_POINTERStatus)codeis_okis_noneis_erroris_stop_iterationis_python_excis_user_exc
excinfoptr    c             C   s   t t| S )N)r   Constant	errcode_t)r
    r   5lib/python3.7/site-packages/numba/targets/callconv.py
_const_int#   s    r   c               @   sd   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )BaseCallConvc             C   s
   || _ d S )N)context)selfr   r   r   r   __init__5   s    zBaseCallConv.__init__c          	   C   s   |t jkr| | n||kr| jj|||d}t||j}||& | j	||j
|j}| || W d Q R X | | n\t|t js||j
kr| jj||||j
d}| j	||j
|}| || ntd||d S )N)value)ZfromtyZtotyzreturning {0} for {1})r   nonereturn_native_noner   Zmake_helperr   Zas_bool_bitZvalidif_thenZget_return_valuetypedatareturn_value
isinstanceZOptionalcastNotImplementedErrorformat)r   builderrettyZvaltyr   ZoptvalZvalidbitretvalr   r   r   return_optional_value8   s$    


z"BaseCallConv.return_optional_valuec             C   s   |  |t d S )N)_return_errcode_rawRETCODE_NONE)r   r*   r   r   r   r!   U   s    zBaseCallConv.return_native_nonec             C   s   |  |t d S )N)r.   RETCODE_EXC)r   r*   r   r   r   
return_excX   s    zBaseCallConv.return_excc             C   s   |  |t d S )N)r.   RETCODE_STOPIT)r   r*   r   r   r   return_stop_iteration[   s    z"BaseCallConv.return_stop_iterationc             C   s   | j j|  }| S )zQ
        Get the actual type of the return argument for Numba type *ty*.
        )r   Zdata_model_managerget_return_typeZ
as_pointer)r   Ztyrestyper   r   r   r4   ^   s    zBaseCallConv.get_return_typec             C   s   |  |}||_|S )zS
        Initialize and return a call helper object for the given builder.
        )_make_call_helper_BaseCallConv__call_helper)r   r*   Zchr   r   r   init_call_helpere   s    
zBaseCallConv.init_call_helperc             C   s   |j S )N)r7   )r   r*   r   r   r   _get_call_helperm   s    zBaseCallConv._get_call_helperc          
   C   s   |j  }||jN |  ||j}t|t	|| |
| W dQ R X || W dQ R X ||j |d || W dQ R X ||j || W dQ R X |dd || || dS )zT
        Given a non-ok *status*, raise the corresponding Python exception.
        NZPyExc_StopIterationZPyExc_SystemErrorz*unknown error when calling native function)functionZappend_basic_blockr"   r   Z	err_clearZunserializer   r   Z	if_likelyZis_not_nullZraise_objectbranchr   Zerr_set_noner   Zerr_set_stringZposition_at_end)r   r*   ZapistatusZbbendexcr   r   r   raise_errorp   s"    


zBaseCallConv.raise_errorc             C   s    |  |}| |}|||S )z
        Get the decoded (unpacked) Python arguments with *argtypes*
        from LLVM function *func*.  A tuple of LLVM values is returned.
        )get_arguments_get_arg_packerZfrom_arguments)r   r*   argtypesfuncZraw_argsarginfor   r   r   decode_arguments   s    

zBaseCallConv.decode_argumentsc             C   s   | j |S )zF
        Get an argument packer for the given argument types.
        )r   Zget_arg_packer)r   rA   r   r   r   r@      s    zBaseCallConv._get_arg_packerN)__name__
__module____qualname__r   r-   r!   r1   r3   r4   r8   r9   r>   rD   r@   r   r   r   r   r   3   s   	r   c               @   sd   e Zd ZdZdd Zdd ZdddZd	d
 Zdd Zdd Z	dd Z
dddZdd Zdd ZdS )MinimalCallConva  
    A minimal calling convention, suitable for e.g. GPU targets.
    The implemented function signature is:

        retcode_t (<Python return type>*, ... <Python arguments>)

    The return code will be one of the RETCODE_* constants or a
    function-specific user exception id (>= RETCODE_USEREXC).

    Caller is responsible for allocating a slot for the return value
    (passed as a pointer in the first argument).
    c             C   s   t  S )N)_MinimalCallHelper)r   r*   r   r   r   r6      s    z!MinimalCallConv._make_call_helperc             C   sP   |j jd }|j|jjks4tt|jt|jjf||| | |t d S )Nr   )	r:   argsr#   pointeeAssertionErrorstrstorer.   
RETCODE_OK)r   r*   r,   retptrr   r   r   r%      s
    zMinimalCallConv.return_valueNc       
      C   s   |d k	r t |ts td|f |d k	r@t|ts@td|f |d k	rx| }|d kr\|}||j|jf}d |kr|d }nd }| |}|	|||}	| 
|t|	 d S )Nz-exc should be None or exception class, got %rz(exc_args should be None or tuple, got %r)
issubclassBaseException	TypeErrorr&   tuple_raw_function_namefilenameliner9   _add_exceptionr.   r   )
r   r*   r=   exc_argsloc	func_namefnamelocinfoZcall_helperexc_idr   r   r   return_user_exc   s"    


zMinimalCallConv.return_user_excc             C   s   |  ||j d S )N)r.   r
   )r   r*   r<   r   r   r   return_status_propagate   s    z'MinimalCallConv.return_status_propagatec             C   s    t |trt|}|| d S )N)r&   intr   ret)r   r*   r
   r   r   r   r.      s    
z#MinimalCallConv._return_errcode_rawc          
   C   sx   | d|t}| d|t}|||}||}| d|t}| d|t}| d|t}	t||||||	|dd}
|
S )z?
        Given a return *code*, get a Status instance.
        z==z>=N)r
   r   r   r   r   r   r   r   )	icmp_signedrO   r/   or_not_r0   r2   RETCODE_USEREXCr	   )r   r*   r
   normr    okerrr=   r   r   r<   r   r   r   _get_return_status   s     
z"MinimalCallConv._get_return_statusc             C   s4   |  |}t|j}| |}tt|g| }|S )zQ
        Get the implemented Function type for *restype* and *argtypes*.
        )r@   listargument_typesr4   r   FunctionTyper   )r   r5   rA   rC   resptrfntyr   r   r   get_function_type   s
    


z!MinimalCallConv.get_function_typeFc             C   s>   |rt | |}|| |dd |D  d|jd _|S )zA
        Set names and attributes of function arguments.
        c             S   s   g | ]}d | qS )zarg.r   ).0ar   r   r   
<listcomp>   s    z5MinimalCallConv.decorate_function.<locals>.<listcomp>z.retr   )rL   r@   assign_namesr?   rJ   name)r   fnrJ   fe_argtypesnoaliasrC   r   r   r   decorate_function   s    
z!MinimalCallConv.decorate_functionc             C   s   |j dd S )z@
        Get the Python-level arguments of LLVM *func*.
        r   N)rJ   )r   rB   r   r   r   r?     s    zMinimalCallConv.get_argumentsc             C   s   |j d jj}t||}|t|| | |}|||}|gt	| }	|
||	}
| ||
}||}| j|||}||fS )z3
        Call the Numba-compiled *callee*.
        r   )rJ   r#   rK   r   alloca_oncerN   get_null_valuer@   as_argumentsrk   callrj   loadr   get_returned_value)r   r*   calleerestyargtysrJ   r+   	retvaltmprC   realargsr
   r<   r,   outr   r   r   call_function	  s    

zMinimalCallConv.call_function)NNN)F)rE   rF   rG   __doc__r6   r%   r_   r`   r.   rj   rp   ry   r?   r   r   r   r   r   rH      s    


rH   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	rI   z
    A call helper object for the "minimal" calling convention.
    User exceptions are represented as integer codes and stored in
    a mapping for retrieval from the caller.
    c             C   s
   i | _ d S )N)
exceptions)r   r   r   r   r   #  s    z_MinimalCallHelper.__init__c             C   s"   t | jt }|||f| j|< |S )z
        Parameters
        ----------
        exc :
            exception type
        exc_args : None or tuple
            exception args
        locinfo : tuple
            location information
        )lenr   FIRST_USEREXC)r   r=   rY   r]   r^   r   r   r   rX   &  s    z!_MinimalCallHelper._add_exceptionc             C   s2   y
| j | S  tk
r,   d| }t|ffS X d S )Nz#unknown error %d in native function)r   KeyErrorSystemError)r   r^   msgr   r   r   get_exception5  s
    
z _MinimalCallHelper.get_exceptionN)rE   rF   rG   r   r   rX   r   r   r   r   r   rI     s   rI   c               @   s~   e Zd ZdZedZdd Zdd Zddd	Z	d
d Z
dd Zdd Zdd ZdddZdd Zdd Zdd Zdd ZdS )CPUCallConva  
    The calling convention for CPU targets.
    The implemented function signature is:

        retcode_t (<Python return type>*, excinfo **, ... <Python arguments>)

    The return code will be one of the RETCODE_* constants.
    If RETCODE_USEREXC, the exception info pointer will be filled with
    a pointer to a constant struct describing the raised exception.

    Caller is responsible for allocating slots for the return value
    and the exception info pointer (passed as first and second arguments,
    respectively).
    r   c             C   s   d S )Nr   )r   r*   r   r   r   r6   R  s    zCPUCallConv._make_call_helperc             C   sP   |  |j}|j|jjks4tt|jt|jjf||| | |t d S )N)	_get_return_argumentr:   r#   rK   rL   rM   rN   r.   rO   )r   r*   r,   rP   r   r   r   r%   U  s
    zCPUCallConv.return_valueNc             C   s   |d k	r t |ts td|f |d k	r@t|ts@td|f |d krNt }| j|}|d k	r| }|d krv|}||j|j	f}d |krd }nd }|||f}|
|}	| |j}
||	|
 | |t d S )Nz-exc should be None or exception class, got %rz(exc_args should be None or tuple, got %r)rQ   rR   rS   r&   rT   r   Zget_python_apirU   rV   rW   Zserialize_object_get_excinfo_argumentr:   rN   r.   rf   )r   r*   r=   rY   rZ   r[   Zpyapir\   r]   Z	struct_gvexcptrr   r   r   r_   \  s,    



zCPUCallConv.return_user_excc             C   s,   |  |j}||j| | ||j d S )N)r   r:   rN   r   r.   r
   )r   r*   r<   r   r   r   r   r`   }  s    z#CPUCallConv.return_status_propagatec             C   s   | | d S )N)rb   )r   r*   r
   r   r   r   r.     s    zCPUCallConv._return_errcode_rawc          
   C   s   | d|t}| d|t}| d|t}| d|t}|||}||}	| d|t}
||
|t	
tt	j}t|||	|||
||d}|S )zP
        Given a return *code* and *excinfoptr*, get a Status instance.
        z==z>=)r
   r   r   r   r   r   r   r   )rc   rO   r/   r0   r2   rd   re   rf   Zselectr   r   excinfo_ptr_tZ	Undefinedr	   )r   r*   r
   r   rg   r    r=   r   rh   ri   r   r<   r   r   r   rj     s$    
zCPUCallConv._get_return_statusc             C   s<   |  |}t|j}| |}tt|ttg| }|S )zQ
        Get the implemented Function type for *restype* and *argtypes*.
        )	r@   rk   rl   r4   r   rm   r   PointerTyper   )r   r5   rA   rC   rn   ro   r   r   r   rp     s    


zCPUCallConv.get_function_typeFc       	      C   s   |  |}|| |dd |D  | |}d|_|d |d | |}d|_|d |d |r| |}x.|D ]&}t|jt	j
r|d |d qW |S )zU
        Set names of function arguments, and add useful attributes to them.
        c             S   s   g | ]}d | qS )zarg.r   )rq   rr   r   r   r   rs     s    z1CPUCallConv.decorate_function.<locals>.<listcomp>rP   Z	nocapturerx   excinfo)r@   rt   r?   r   ru   Zadd_attributer   r&   r#   r   r   )	r   rv   rJ   rw   rx   rC   ZretargZexcargrr   r   r   r   ry     s$    









zCPUCallConv.decorate_functionc             C   s   |j dd S )z@
        Get the Python-level arguments of LLVM *func*.
           N)rJ   )r   rB   r   r   r   r?     s    zCPUCallConv.get_argumentsc             C   s
   |j d S )Nr   )rJ   )r   rB   r   r   r   r     s    z CPUCallConv._get_return_argumentc             C   s
   |j d S )Nr   )rJ   )r   rB   r   r   r   r     s    z!CPUCallConv._get_excinfo_argumentc             C   s   |  |jj}t||}|t|| tj|tt	dd}| 
|}	t|	||}||g| }
|||
}| ||||}||}| j|||}||fS )z3
        Call the Numba-compiled *callee*.
        r   )ru   )r   Zfunction_typerK   r   rz   rN   r{   r   r   	excinfo_tr@   rk   r|   r}   rj   r~   r   r   )r   r*   r   r   r   rJ   r+   r   r   rC   r   r
   r<   r,   r   r   r   r   r     s    

zCPUCallConv.call_function)NNN)F)rE   rF   rG   r   	itertoolscountZ_status_idsr6   r%   r_   r`   r.   rj   rp   ry   r?   r   r   r   r   r   r   r   r   A  s   
 
 
r   c               @   s   e Zd Zdd ZdddZdS )
ErrorModelc             C   s
   || _ d S )N)	call_conv)r   r   r   r   r   r     s    zErrorModel.__init__Nc             C   s$   | j r| j|t|| dS dS d S )NTF)raise_on_fp_zero_divisionr   r_   ZeroDivisionError)r   r*   rY   rZ   r   r   r   fp_zero_division  s
    zErrorModel.fp_zero_division)NN)rE   rF   rG   r   r   r   r   r   r   r     s   r   c               @   s   e Zd ZdZdZdS )PythonErrorModelzL
    The Python error model.  Any invalid FP input raises an exception.
    TN)rE   rF   rG   r   r   r   r   r   r   r     s   r   c               @   s   e Zd ZdZdZdS )NumpyErrorModela6  
    In the Numpy error model, floating-point errors don't raise an
    exception.  The FPU exception state is inspected by Numpy at the
    end of a ufunc's execution and a warning is raised if appropriate.

    Note there's no easy way to set the FPU exception state from LLVM.
    Instructions known to set an FP exception can be optimized away:
        https://llvm.org/bugs/show_bug.cgi?id=6050
        http://lists.llvm.org/pipermail/llvm-dev/2014-September/076918.html
        http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20140929/237997.html
    FN)rE   rF   rG   r   r   r   r   r   r   r     s   r   )ZpythonZnumpyc             C   s   t |  |jS )zF
    Create an error model instance for the given target context.
    )error_modelsr   )Z
model_namer   r   r   r   create_error_model  s    r   )%r   collectionsr   r   Zllvmliter   Znumbar   r   baser   r   r	   ZIntTypeZint32_tr   r   rO   r0   r/   r2   r   rf   objectr   rH   rI   ZLiteralStructTyper   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s:   
k~!
 '