
    X-Ph'                    @   d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
mZ ddlmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZ eeeef         df         Z eedf         Z!e"eee e!f         ef         Z#d;dZ$d<dZ%d=dZ&d>dZ'd?d!Z(d@d)Z)dAd1Z*dBd3Z+dCd8Z,dDd9Z-d:S )EaY  Transformation for inserting refrecence count inc/dec opcodes.

This transformation happens towards the end of compilation. Before this
transformation, reference count management is not explicitly handled at all.
By postponing this pass, the previous passes are simpler as they don't have
to update reference count opcodes.

The approach is to decrement reference counts soon after a value is no
longer live, to quickly free memory (and call __del__ methods), though
there are no strict guarantees -- other than that local variables are
freed before return from a function.

Function arguments are a little special. They are initially considered
'borrowed' from the caller and their reference counts don't need to be
decremented before returning. An assignment to a borrowed value turns it
into a regular, owned reference that needs to freed before return.
    )annotations)Iterable)AnalysisDictanalyze_borrowed_argumentsanalyze_live_regsanalyze_must_defined_regscleanup_cfgget_cfg)FuncIR
all_values)Assign
BasicBlockBranch	ControlOpDecRefGotoIncRefInteger	KeepAliveLoadAddressOpRegister
RegisterOpValue.irr   returnNonec                   t          | j                  }t          | j        | j                  }d |D             }t	          | j                  }t          | j        |          }t          | j        ||          }t          | j        |||d          }t          |           }i }	| j        	                                D ]}
t          |
j        d         t          t          f          r/t          |
|	| j        |j        |j        |j        |j        |           t#          |
|j        |j        |j        |j                   t%          | j                   dS )zgInsert reference count inc/dec opcodes to a function.

    This is the entry point to this module.
    c                     h | ]}|j         	|S  )is_borrowed).0values     X/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/mypyc/transform/refcount.py	<setcomp>z+insert_ref_count_opcodes.<locals>.<setcomp>B   s     ???%U->????    T)strict_errorsN)r
   blocksr   arg_regssetr   r   r   make_value_orderingcopy
isinstanceopsr   r   insert_branch_inc_and_decrefsbeforeaftertransform_blockr	   )r   cfgvaluesborrowedargsliveborrowdefinedorderingcacheblocks              r$   insert_ref_count_opcodesr>   :   s?   
 ")

CRY//F??6???H2;''DRY,,D'	3AAF'	3fTXYYYG"2&&HE!! V Veimfd^44 
	)		 	 	 	t{DJw}UUUU	r&   post_must_defined
set[Value]srcr   boolc                4    t          |t                    o|| vS N)r.   r   )r?   rA   s     r$   is_maybe_undefinedrE   Z   s    c8$$E4E)EEr&   r/   list[Op]destr:   AnalysisDict[Value]keytuple[BasicBlock, int]c           	         |j         j        rOt          |t                    s<|                     t          |t          ||         |                               d S d S d S )Nis_xdec)typeis_refcountedr.   r   appendr   rE   )r/   rG   r:   rI   s       r$   maybe_append_dec_refrQ   ^   sp     y Qz$'@'@ Q

6$(:73<(N(NOOOPPPPPQ Q Q Qr&   c                f    |j         j        r$|                     t          |                     d S d S rD   )rN   rO   rP   r   )r/   rG   s     r$   maybe_append_inc_refrS   e   s7    y !

6$<<     ! !r&   r=   r   pre_live	post_live
pre_borrowc                ^   | j         }g }t          |          D ]\  }}| |f}	|||	         vsJ t          |t                    r|j        n|}
|                                }t          |          D ]r\  }}|||	         v s|||	         v s||d |         v rMt          ||           |
||	         vr3|
||	         v r)t          |t                    sJ t          ||
||	           st          |t                    s|	                    |           t          |t                    r|                                D ],}|||	         vr |||	         vr||vrt          ||||	           -|
j        s8|
||	         vr.t          |t                    r|
j        st          ||
||	           || _         d S rD   )r/   	enumerater.   r   rG   stolenrS   rQ   r   rP   r   unique_sourcesis_voidr   r!   )r=   rT   rU   rV   r?   old_opsr/   ioprI   rG   rY   jrA   s                 r$   r3   r3   j   s    iGC7## &D &D2aj#&&&&$R008rwwb  '' 	L 	LFAsin$$z#(>(>#PRQRPRBSBS$S#... z#..48C=3H3H%b&11111(d4EsKKK "i(( 	JJrNNN b)$$ 	$$&& 	G 	GC)C.((S
3-G-GCW]L]L]$S#/@#FFF 	DIcN**J// +484D + !d,=sCCCEIIIr&   r<   
BlockCacher)   list[BasicBlock]post_borrowr;   dict[Value, int]c                   | t          | j                  dz
  f}||         }	||         }
||         }| j        }t          |                                          D ]\  }}t          |t                    r$|j        t          j        k    r|dk    r	|j	        f}nd}t          ||||
|	||          }t          ||||
|          }|                    |t          |||||                     dS )aN  Insert inc_refs and/or dec_refs after a branch/goto.

    Add dec_refs for registers that become dead after a branch.
    Add inc_refs for registers that become unborrowed after a branch or goto.

    Branches are special as the true and false targets may have a different
    live and borrowed register sets. Add new blocks before the true/false target
    blocks that tweak reference counts.

    Example where we need to add an inc_ref:

      def f(a: int) -> None
          if a:
              a = 1
          return a  # a is borrowed if condition is false and unborrowed if true
       r   r    N)lenr/   
terminatorrX   targetsr.   r   r^   IS_ERRORr#   after_branch_decrefsafter_branch_increfs
set_target	add_block)r=   r<   r)   rT   rV   rb   r?   r;   prev_keysource_live_regssource_borrowedsource_definedtermr]   targetomitteddecsincss                     r$   r0   r0      s   4 s59~~)*H)!(+O&x0NDt||~~.. I I	6 dF## 	6?(B(BqAvvzmGGG#Hno?OQY[b
 
 $FHj/S[\\9T4GGHHHHI Ir&   labelrq   rp   ro   rt   Iterable[Value]tuple[tuple[Value, bool], ...]c                    || df         }||z
  |z
  }|r.t          fdt          |fd          D                       S dS )Nr   c              3  \   K   | ]&}|j         j        r|v|t          |          fV  'd S rD   )rN   rO   rE   )r"   regrt   rq   s     r$   	<genexpr>z'after_branch_decrefs.<locals>.<genexpr>   sY       
 
x%
 +.W*<*< $^S99:*<*<*<*<
 
r&   c                    |          S rD   r    rr;   s    r$   <lambda>z&after_branch_decrefs.<locals>.<lambda>   s    HQK r&   rI   r    tuplesorted)	rw   rT   rq   rp   ro   r;   rt   target_pre_livedecrefs	     `  ``  r$   rj   rj      s     uax(O//AF 
 
 
 
 
 
f*?*?*?*?@@@
 
 
 
 
 	

 2r&   tuple[Value, ...]c                    || df         }|| df         }||z
  |z  }|r+t          d t          |fd          D                       S dS )Nr   c              3  2   K   | ]}|j         j        |V  d S rD   )rN   rO   r"   r|   s     r$   r}   z'after_branch_increfs.<locals>.<genexpr>   s@       
 
H^

 
 
 
 
 
r&   c                    |          S rD   r    r   s    r$   r   z&after_branch_increfs.<locals>.<lambda>   s     r&   r   r    r   )rw   rT   rV   rp   r;   r   target_borrowedincrefs       `   r$   rk   rk      s     uax(O *O/?BF 
 
 
!&.C.C.C.CDDD
 
 
 
 
 	
 2r&   ru   Decsrv   Incsc                j   | s|s|S || |f|v r||| |f         S t                      }|                    |           |j                            d | D                        |j                            d |D                        |j                            t	          |                     |||| |f<   |S )Nc              3  >   K   | ]\  }}t          ||           V  dS )rL   N)r   )r"   r|   xdecs      r$   r}   zadd_block.<locals>.<genexpr>   s3      EE93VC...EEEEEEr&   c              3  4   K   | ]}t          |          V  d S rD   )r   r   s     r$   r}   zadd_block.<locals>.<genexpr>  s(      11SVC[[111111r&   )r   rP   r/   extendr   )ru   rv   r<   r)   rw   r=   s         r$   rm   rm      s        	tTe##UD$&''LLE
MM%	IEEEEEEEE	I11D111111	IT%[[!!!$E%t
Lr&   c                d   i }d}| j         D ]}|||<   |dz  }| j        D ]}|j        D ]}t          |t                    r2t          |j        t                    r|j        |vr|||j        <   |dz  }t          |t                    r|j        |vr|||j        <   |dz  }w||vr
|||<   |dz  }|S )zrCreate a ordering of values that allows them to be sorted.

    This omits registers that are only ever read.
    r   re   )	r*   r)   r/   r.   r   rA   r   r   rG   )r   resultnargr=   r^   s         r$   r,   r,     s      "F	A{  s	Q  ) 	 	B2{++rvx00 F&(( "#rvQ"f%% 7&((&'F27OFA6!!r
Q	" Mr&   N)r   r   r   r   )r?   r@   rA   r   r   rB   )
r/   rF   rG   r   r:   rH   rI   rJ   r   r   )r/   rF   rG   r   r   r   )r=   r   rT   rH   rU   rH   rV   rH   r?   rH   r   r   )r=   r   r<   r`   r)   ra   rT   rH   rV   rH   rb   rH   r?   rH   r;   rc   r   r   )rw   r   rT   rH   rq   r@   rp   r@   ro   r@   r;   rc   rt   rx   r   ry   )rw   r   rT   rH   rV   rH   rp   r@   r;   rc   r   r   )ru   r   rv   r   r<   r`   r)   ra   rw   r   r   r   )r   r   r   rc   ).__doc__
__future__r   collections.abcr   mypyc.analysis.dataflowr   r   r   r   r	   r
   mypyc.ir.func_irr   r   mypyc.ir.opsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rB   r   r   dictr`   r>   rE   rQ   rS   r3   r0   rj   rk   rm   r,   r    r&   r$   <module>r      se   $ # " " " " " $ $ $ $ $ $                0 / / / / / / /                               " U5$;$%UCZ
 %
D$./;<
   @F F F FQ Q Q Q! ! ! !
0 0 0 0f/I /I /I /Id   (   "   &     r&   