o
    ài›7  ã                   @   sÖ   d dl Z d dlmZ d dlmZ d dlmZ ddlmZ	 dd„ Z
G d	d
„ d
eƒZe 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G dd„ deƒZG dd„ deƒZedkrie  ¡  dS dS )é    N)Úir)Úbinding)ÚTestCaseé   )Úrefprune_protoc                 #   sD    ‡ fdd„}t j ¡ D ]\}}| d¡rd|› ||ƒfV  qd S )Nc                    s(   ‡ ‡fdd„}dˆ j › dˆ j› |_|S )Nc                    s
   ˆ| ˆ ƒS ©N© )Úself)ÚfnÚgenerate_testr   úk/var/www/html/eduruby.in/lip-sync/lip-sync-env/lib/python3.10/site-packages/llvmlite/tests/test_refprune.pyÚwrapped   s   
z-_iterate_cases.<locals>.wrap.<locals>.wrappedzgenerated test for Ú.)Ú
__module__Ú__name__Ú__doc__)r
   r   ©r   )r
   r   Úwrap
   s   z_iterate_cases.<locals>.wrapÚcaseZtest_)ÚprotoÚ__dict__ÚitemsÚ
startswith)r   r   ÚkZcase_fnr   r   r   Ú_iterate_cases	   s   €
€þr   c                   @   s4   e Zd ZdZdd„ ZeeƒD ]	\ZZeeƒ e< qdS )ÚTestRefPrunePrototypez-
    Test that the prototype is working.
    c                 C   s,   |ƒ \}}}t  ||¡ ¡ }|  ||¡ d S r   )r   ZFanoutAlgorithmÚrunÚassertEqual)r	   Úcase_genÚnodesÚedgesÚexpectedÚgotr   r   r   r      s   z#TestRefPrunePrototype.generate_testN)	r   r   Ú__qualname__r   r   r   Únamer   Úlocalsr   r   r   r   r      s    ÿr   é   c                   @   sl   e Zd 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eeƒD ]	\ZZeeƒ e< q*dS )ÚTestRefPrunePasszß
    Test that the C++ implementation matches the expected behavior as for
    the prototype.

    This generates a LLVM module for each test case, runs the pruner and checks
    that the expected results are achieved.
    c                 C   ó"   t  t  ¡ tg¡}t j||ddS )NÚ
NRT_incref©r$   ©r   ÚFunctionTypeÚVoidTypeÚptr_tyÚFunction©r	   ÚmÚfntyr   r   r   Úmake_incref/   ó   zTestRefPrunePass.make_increfc                 C   r(   )NÚ
NRT_decrefr*   r+   r0   r   r   r   Úmake_decref3   r4   zTestRefPrunePass.make_decrefc                 C   ó"   t  t  d¡d¡}t j||ddS )Né    r   Zswitcherr*   ©r   r,   ÚIntTyper/   r0   r   r   r   Úmake_switcher7   r4   zTestRefPrunePass.make_switcherc                 C   r7   )Nr   r   Zbrancherr*   r9   r0   r   r   r   Úmake_brancher;   r4   zTestRefPrunePass.make_brancherc                 C   s¶  t  ¡ }|  |¡}|  |¡}|  |¡}|  |¡}t  t  ¡ tg¡}t j	||dd}	|	j
\}
d|
_i }|D ]	}|	 |¡||< q4t  ¡ }| ¡ D ]’\}}| || ¡ || D ]}|dkrc| ||
g¡ qU|dkro| ||
g¡ qUtdƒ‚t|ƒ}|dkr€| ¡  qF|dkr|\}| || ¡ qF|d	kr©|\}}| |d
¡}| ||| || ¡ qF|d	krÕ| |d
¡}|^}}|j||| d}t|ƒD ]\}}| | |¡|| ¡ qÄqFtdƒ‚|S )NÚmainr*   ZmemÚincrefÚdecrefZunreachabler   r   é   r   )Údefault)r   ÚModuler3   r6   r;   r<   r,   r-   r.   r/   Úargsr$   Zappend_basic_blockZ	IRBuilderr   Zposition_at_endÚcallÚAssertionErrorÚlenZret_voidÚbranchZcbranchÚswitchÚ	enumerateZadd_caseÚtype)r	   r   r    r1   Z	incref_fnZ	decref_fnZswitcher_fnZbrancher_fnr2   r
   ZptrZbbmapÚbbZbuilderZjump_targetsÚactionZ	n_targetsÚdstÚleftÚrightÚselÚheadÚtailÚswÚir   r   r   Úgenerate_ir?   sP   




ÿzTestRefPrunePass.generate_irc                 C   s,   t  t|ƒ¡}t  ¡ }| ¡  | |¡ |S r   )ÚllvmÚparse_assemblyÚstrÚModulePassManagerÚadd_refprune_passr   )r	   ÚirmodÚmodÚpmr   r   r   Úapply_refpruneu   s
   
zTestRefPrunePass.apply_refprunec                 C   s
  i }|  ¡ D ]\}}| d¡}| d¡}||dœ||< q|  ¡ D ]"\}}	| |¡rB|	d  d8  < || D ]}
||
 d  d8  < q5q |jD ]	}|jdkrO nqF|jD ]/}||j }	t|ƒ}| d¡}| d¡}| j|	d |d|› d	 | j|	d |d|› d	 qSd S )
Nr>   r?   )r>   r?   r   r=   r)   r5   zBB )Úmsg)r   ÚcountÚgetZ	functionsr$   ÚblocksrX   r   )r	   r\   r!   r   Údr   ÚvsZn_increfZn_decrefÚstatsZdec_bbÚfrK   Útextr   r   r   Úcheck|   s.   


€

ÿ



úzTestRefPrunePass.checkc                 C   s4   |ƒ \}}}|   ||¡}|  |¡}|  |||¡ d S r   )rU   r^   rh   )r	   r   r   r    r!   r[   Zoutmodr   r   r   r   –   s   
zTestRefPrunePass.generate_testN)r   r   r#   r   r3   r6   r;   r<   rU   r^   rh   r   r   r$   r   r%   r   r   r   r   r'   &   s    6ÿr'   c                   @   s   e Zd ZdZdZddd„ZdS )ÚBaseTestByIRr   zG
declare void @NRT_incref(i8* %ptr)
declare void @NRT_decref(i8* %ptr)
Nc                 C   sj   t  | j› d|› ¡}t  ¡ }|d u r| | j¡ n|j| j|d t  ¡ }| |¡ t  ¡ }||| fS )NÚ
©Úsubgraph_limit)rV   rW   ÚprologuerY   rZ   Úrefprune_bitmaskZdump_refprune_statsr   )r	   r[   rl   r\   r]   ÚbeforeÚafterr   r   r   rh   ©   s   ÿ
zBaseTestByIR.checkr   )r   r   r#   rn   rm   rh   r   r   r   r   ri   ¡   s    ri   c                   @   sD   e Zd ZejjZdZdd„ ZdZ	dd„ Z
dZdd	„ Zd
Zdd„ ZdS )Ú	TestPerBBzv
define void @main(i8* %ptr) {
    call void @NRT_incref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   ó"   |   | j¡\}}|  |jd¡ d S ©Nr@   )rh   Úper_bb_ir_1r   Ú
basicblock©r	   r\   re   r   r   r   Útest_per_bb_1Â   ó   zTestPerBB.test_per_bb_1zâ
define void @main(i8* %ptr) {
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   ó2   |   | j¡\}}|  |jd¡ |  dt|ƒ¡ d S )Né   zcall void @NRT_incref(i8* %ptr))rh   Úper_bb_ir_2r   ru   ÚassertInrX   rv   r   r   r   Útest_per_bb_2Ñ   ó   zTestPerBB.test_per_bb_2zÌ
define void @main(i8* %ptr, i8* %other) {
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %other)
    ret void
}
c                 C   ry   )Nr@   ú!call void @NRT_decref(i8* %other))rh   Úper_bb_ir_3r   ru   r|   rX   rv   r   r   r   Útest_per_bb_3á   r~   zTestPerBB.test_per_bb_3zü
; reordered
define void @main(i8* %ptr, i8* %other) {
    call void @NRT_incref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %other)
    call void @NRT_incref(i8* %ptr)
    ret void
}
c                 C   ry   )Nrz   r   )rh   Úper_bb_ir_4r   ru   r|   rX   rv   r   r   r   Útest_per_bb_4ó   r~   zTestPerBB.test_per_bb_4N)r   r   r#   rV   ÚRefPruneSubpassesZPER_BBrn   rt   rw   r{   r}   r€   r   r‚   rƒ   r   r   r   r   rq   ·   s    
rq   c                   @   óP   e Zd ZejjZdZdd„ ZdZ	dd„ Z
dZdd	„ Zd
Zdd„ ZdZdd„ ZdS )ÚTestDiamondz•
define void @main(i8* %ptr) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br label %bb_B
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   rs   )rh   Úper_diamond_1r   Údiamondrv   r   r   r   Útest_per_diamond_1  rx   zTestDiamond.test_per_diamond_1zè
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    br label %bb_D
bb_C:
    br label %bb_D
bb_D:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   rs   )rh   Úper_diamond_2r   rˆ   rv   r   r   r   Útest_per_diamond_2  rx   zTestDiamond.test_per_diamond_2a3  
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    br label %bb_D
bb_C:
    call void @NRT_decref(i8* %ptr)  ; reject because of decref in diamond
    br label %bb_D
bb_D:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   ©Nr   )rh   Úper_diamond_3r   rˆ   rv   r   r   r   Útest_per_diamond_3/  rx   zTestDiamond.test_per_diamond_3a5  
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_incref(i8* %ptr)     ; extra incref will not affect prune
    br label %bb_D
bb_C:
    br label %bb_D
bb_D:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   rs   )rh   Úper_diamond_4r   rˆ   rv   r   r   r   Útest_per_diamond_4C  rx   zTestDiamond.test_per_diamond_4a0  
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    br label %bb_D
bb_C:
    br label %bb_D
bb_D:
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   )Nrz   )rh   Úper_diamond_5r   rˆ   rv   r   r   r   Útest_per_diamond_5X  rx   zTestDiamond.test_per_diamond_5N)r   r   r#   rV   r„   ZDIAMONDrn   r‡   r‰   rŠ   r‹   r   rŽ   r   r   r‘   r’   r   r   r   r   r†   ú   s    r†   c                   @   sD   e Zd ZdZejjZdZdd„ Z	dZ
dd„ ZdZd	d
„ Zdd„ ZdS )Ú
TestFanoutz6More complex cases are tested in TestRefPrunePass
    zí
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret void
bb_C:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   )Né   )rh   Úfanout_1r   Úfanoutrv   r   r   r   Útest_fanout_1q  rx   zTestFanout.test_fanout_1a6  
define void @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret void
bb_C:
    call void @NRT_decref(i8* %ptr)
    br label %bb_B                      ; illegal jump to other decref
}
c                 C   rr   rŒ   )rh   Úfanout_2r   r–   rv   r   r   r   Útest_fanout_2ƒ  rx   zTestFanout.test_fanout_2a}  
define void @main(i8* %ptr, i1 %cond) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret void
bb_C:
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 C   rr   )Né   ©rh   Úfanout_3r   r–   rv   r   r   r   Útest_fanout_3™  rx   zTestFanout.test_fanout_3c                 C   s&   | j | jdd\}}|  |jd¡ d S )Nr   rk   r   r›   rv   r   r   r   Útest_fanout_3_limited  s   z TestFanout.test_fanout_3_limitedN)r   r   r#   r   rV   r„   ZFANOUTrn   r•   r—   r˜   r™   rœ   r   rž   r   r   r   r   r“   ]  s    r“   c                   @   r…   )ÚTestFanoutRaisea'  
define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret i32 0
bb_C:
    store i8* null, i8** %excinfo, !numba_exception_output !0
    ret i32 1
}
!0 = !{i1 true}
c                 C   rr   rs   )rh   Úfanout_raise_1r   Úfanout_raiserv   r   r   r   Útest_fanout_raise_1¶  rx   z#TestFanoutRaise.test_fanout_raise_1a:  
define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret i32 0
bb_C:
    store i8* null, i8** %excinfo, !numba_exception_typo !0      ; bad metadata
    ret i32 1
}

!0 = !{i1 true}
c                 C   rr   rŒ   )rh   Úfanout_raise_2r   r¡   rv   r   r   r   Útest_fanout_raise_2Ê  s   z#TestFanoutRaise.test_fanout_raise_2a:  
define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    ret i32 0
bb_C:
    store i8* null, i8** %excinfo, !numba_exception_output !0
    ret i32 1
}

!0 = !{i32 1}       ; ok; use i32
c                 C   rr   rs   )rh   Úfanout_raise_3r   r¡   rv   r   r   r   Útest_fanout_raise_3à  rx   z#TestFanoutRaise.test_fanout_raise_3a!  
define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    ret i32 1    ; BAD; all tails are raising without decref
bb_C:
    ret i32 1    ; BAD; all tails are raising without decref
}

!0 = !{i1 1}
c                 C   rr   rŒ   )rh   Úfanout_raise_4r   r¡   rv   r   r   r   Útest_fanout_raise_4ò  rx   z#TestFanoutRaise.test_fanout_raise_4a™  
define i32 @main(i8* %ptr, i1 %cond, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    br label %common.ret
bb_C:
    store i8* null, i8** %excinfo, !numba_exception_output !0
    br label %common.ret
common.ret:
    %common.ret.op = phi i32 [ 0, %bb_B ], [ 1, %bb_C ]
    ret i32 %common.ret.op
}
!0 = !{i1 1}
c                 C   rr   rs   )rh   Úfanout_raise_5r   r¡   rv   r   r   r   Útest_fanout_raise_5  rx   z#TestFanoutRaise.test_fanout_raise_5N)r   r   r#   rV   r„   ZFANOUT_RAISErn   r    r¢   r£   r¤   r¥   r¦   r§   r¨   r©   rª   r   r   r   r   rŸ   ¤  s    rŸ   Ú__main__)ZunittestZllvmliter   r   rV   Zllvmlite.testsr   Ú r   r   r   r   r:   Z
as_pointerr.   r'   ri   rq   r†   r“   rŸ   r   r=   r   r   r   r   Ú<module>   s"    {CcGiÿ