U
    |e!                     @   s`   d dl mZmZ d dl Zd dlmZmZmZ G dd deZ	G dd deZ
G dd	 d	eZdS )
    )Constant	IRBuilderN)typesconfigcgutilsc                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	_ArgManagerzA
    A utility class to handle argument unboxing and cleanup
    c                 C   s.   || _ || _|| _|| _d| _g | _|| _d S )Nr   )contextbuilderapienv_manager	arg_countcleanupsnextblk)selfr   r	   r
   r   endblknargs r   S/var/www/website-v5/atlas_env/lib/python3.8/site-packages/numba/core/callwrapper.py__init__   s    z_ArgManager.__init__c              	      s   j | tj j jj W 5 Q R X  fdd}j	| j
dj }j| |  jj W 5 Q R X |_ jd7  _ jS )ak  
        Unbox argument and emit code that handles any error during unboxing.
        Args are cleaned up in reverse order of the parameter list, and
        cleanup begins as soon as unboxing of any argument fails. E.g. failure
        on arg2 will result in control flow going through:

            arg2.err -> arg1.err -> arg0.err -> arg.end (returns)
        c                      sH   j  jj  jd k	r&   jjrDjjj	 j d S N)
r
   reflect_native_valuevaluer   cleanupr   
enable_nrtnrtdecrefr	   r   nativer   tyr   r   cleanup_arg&   s
    
z(_ArgManager.add_arg.<locals>.cleanup_argz	arg%d.err   )r
   to_native_valuer   if_unlikelyr	   is_errorbranchr   r   appendappend_basic_blockr   
goto_blockr   )r   objr   r   Z
cleanupblkr   r   r   add_arg   s    
z_ArgManager.add_argc                 C   s   | j D ]
}|  qdS )zR
        Emit the cleanup code after returning from the wrapped function.
        N)r   )r   Zdtorr   r   r   emit_cleanupB   s    
z_ArgManager.emit_cleanupN)__name__
__module____qualname____doc__r   r)   r*   r   r   r   r   r      s   	.r   c                   @   s    e Zd ZdZdd Zdd ZdS )_GilManagerzY
    A utility class to handle releasing the GIL and then re-acquiring it
    again.
    c                 C   s    || _ || _|| _| | _d S r   )r	   r
   argmansave_threadthread_state)r   r	   r
   r0   r   r   r   r   P   s    z_GilManager.__init__c                 C   s   | j | j | j  d S r   )r
   restore_threadr2   r0   r*   )r   r   r   r   r*   V   s    z_GilManager.emit_cleanupN)r+   r,   r-   r.   r   r*   r   r   r   r   r/   J   s   r/   c                   @   s<   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd ZdS )PyCallWrapperc                 C   s(   || _ || _|| _|| _|| _|| _d S r   )r   modulefuncfndescenvrelease_gil)r   r   r5   r6   r7   r8   call_helperr9   r   r   r   r   \   s    zPyCallWrapper.__init__c           
      C   s   | j j}| jtj}tj||||g}tjj	| j
||d}t|d}|j\}}}d|_d|_d|_| j|}	| |	|||| ||	fS )N)nameentryZ
py_closureZpy_argsZpy_kws)r7   llvm_cpython_wrapper_namer   get_argument_typer   pyobjectllvmliteirFunctionTypeFunctionr5   r   r&   argsr;   get_python_apibuild_wrapper)
r   Zwrapnamepyobjwraptywrapperr	   closurerD   kwsr
   r   r   r   builde   s    zPyCallWrapper.buildc              
      s  t | jj} fddt|D } j|| jj||f| }|d|t|jd }	t	
||	 |   W 5 Q R X |d}
||
 |   W 5 Q R X |  |}t| j| ||
|}g }t|| jjD ]<\}}t|tjr|d  q||||}|| q| jr*t| |}| jjj|| j| jj| jj|dd\}}| |d |   | |d |j!|j"d	d
F |!|j#  $  W 5 Q R X | % } &|||}|| W 5 Q R X | jj'| | |   d S )Nc                    s   g | ]}   qS r   )
alloca_obj).0_r
   r   r   
<listcomp>   s     z/PyCallWrapper.build_wrapper.<locals>.<listcomp>z==zarg.end)noinline)attrsz# callwrapper: emit_cleanupz# callwrapper: emit_cleanup endT)likely)(lenr7   argtypesrangeunpack_tuplequalnameicmp_unsignedr   typer   r"   retget_null_objectr&   r'   get_envr   r   zip
isinstancer   Omittedr%   r)   loadr9   r/   	call_convcall_functionr6   restypedebug_printr*   if_thenis_okis_nonereturn_none_simplified_return_typefrom_native_returnraise_error)r   r
   r	   rJ   rD   rK   r   objsZparseokpredr   r   Zcleanup_managerZ	innerargsr(   r   valstatusretvalrettyr   rP   r   rF   ~   sf     


      
zPyCallWrapper.build_wrapperc                 C   s^   | j | j}| j |j|}||}| j ||}|j|d| jjd |	| j
||}|S )zpGet the Environment object which is declared as a global
        in the module of the wrapped function.
        T)return_pyobject	debug_msg)r   get_env_namer7   declare_env_globalr5   rb   get_env_bodyemit_environment_sentryenv_nameget_env_managerr8   )r   r
   r	   envnameZgvptrenvptrenv_bodyr   r   r   r   r^      s    
zPyCallWrapper.get_envc                 C   s"   | j j}t|tjr|jS |S dS )z
        The NPM callconv has already converted simplified optional types.
        We can simply use the value type from it.
        N)r7   re   r`   r   Optionalr[   )r   re   r   r   r   rk      s    z%PyCallWrapper._simplified_return_typec                 C   s   t jr| j|d| d S )NzDEBUGJIT: {0})r   	DEBUG_JITr   rf   format)r   r	   msgr   r   r   rf      s    zPyCallWrapper.debug_printN)	r+   r,   r-   r   rL   rF   r^   rk   rf   r   r   r   r   r4   [   s   	Gr4   )llvmlite.irr   r   r@   
numba.corer   r   r   objectr   r/   r4   r   r   r   r   <module>   s
   C