o
    "Æ&ij?  ã                   @   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l	m
  mZ dd„ ZG dd	„ d	ƒZG d
d„ deƒZe d¡ ¡ ZG dd„ deeƒZG dd„ d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dkr{e  ¡  dS dS )é    N)Údefaultdict)Úir)Úbinding)ÚTestCasec                 #   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   úGC:\wamp64\www\opt\env\Lib\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                   @   s   e Zd Zdd„ ZdS )ÚPassManagerMixinc                 C   s0   t  ¡  t j ¡  ¡ }t jddd}t  ||¡S )Nr   )Zspeed_levelZ
size_level)ÚllvmZinitialize_native_targetZTargetZfrom_default_tripleZcreate_target_machineZcreate_pipeline_tuning_optionsZcreate_pass_builder)r   ÚtmZptor   r   r   Úpb   s   zPassManagerMixin.pbN)r   r   Ú__qualname__r   r   r   r   r   r      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   r   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_incref9   ó   zTestRefPrunePass.make_increfc                 C   r+   )NÚ
NRT_decrefr-   r.   r3   r   r   r   Úmake_decref=   r7   zTestRefPrunePass.make_decrefc                 C   ó"   t  t  d¡d¡}t j||ddS )Né    r   Zswitcherr-   ©r   r/   ÚIntTyper2   r3   r   r   r   Úmake_switcherA   r7   zTestRefPrunePass.make_switcherc                 C   r:   )Né   r   Zbrancherr-   r<   r3   r   r   r   Úmake_brancherE   r7   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   ÚModuler6   r9   r>   r@   r/   r0   r1   r2   Ú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$   r4   Z	incref_fnZ	decref_fnZswitcher_fnZbrancher_fnr5   r	   ÚptrZbbmapÚbbZbuilderZjump_targetsÚactionZ	n_targetsÚdstÚleftÚrightÚselÚheadÚtailÚswÚir   r   r   Úgenerate_irI   sP   




ÿzTestRefPrunePass.generate_irc                 C   s6   t  t|ƒ¡}|  ¡ }| ¡ }| ¡  | ||¡ |S r   )r   Úparse_assemblyÚstrr   ÚgetModulePassManagerÚadd_refprune_passr    )r   ÚirmodÚmodr   Úpmr   r   r   Úapply_refprune   s   zTestRefPrunePass.apply_refprunec                 C   s  t dd„ ƒ}| ¡ D ]\}}| d¡}| d¡}||dœ||< q
| ¡ D ]"\}}	| |¡rF|	d  d8  < || D ]}
||
 d  d8  < q9q$|jD ]	}|jdkrS nqJ|jD ]/}||j }	t|ƒ}| d¡}| d	¡}| j|	d |d
|› d | j|	d |d
|› d qWd S )Nc                   S   s   t tƒS r   )r   Úintr   r   r   r   Ú<lambda>Œ   s    z(TestRefPrunePass.check.<locals>.<lambda>rB   rC   )rB   rC   r?   rA   r,   r8   zBB )Úmsg)	r   r   ÚcountÚgetZ	functionsr'   Úblocksr\   r!   )r   r`   r%   r#   Údr   ÚvsZn_increfZn_decrefÚstatsZdec_bbÚfrP   Útextr   r   r   Úcheck‡   s.   


€

ÿ



úzTestRefPrunePass.checkc                 C   s4   |ƒ \}}}|   ||¡}|  |¡}|  |||¡ d S r   )rZ   rb   rn   )r   r"   r#   r$   r%   r_   Zoutmodr   r   r   r
   ¦   s   
zTestRefPrunePass.generate_testN)r   r   r   r   r6   r9   r>   r@   rZ   rb   rn   r
   r   r'   r   r(   r   r   r   r   r*   0   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   st   t  | j› d|› ¡}|  ¡ }| ¡ }|d u r| | j¡ n|j| j|d t  ¡ }| ||¡ t  ¡ }||| fS )NÚ
©Úsubgraph_limit)	r   r[   Úprologuer   r]   r^   Úrefprune_bitmaskZdump_refprune_statsr    )r   r_   rr   r`   r   ra   ÚbeforeÚafterr   r   r   rn   ¹   s   ÿzBaseTestByIR.checkr   )r   r   r   rt   rs   rn   r   r   r   r   ro   ±   s    ro   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 ©NrD   )rn   Úper_bb_ir_1r!   Ú
basicblock©r   r`   rk   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(ptr %ptr))rn   Úper_bb_ir_2r!   r{   ÚassertInr\   r|   r   r   r   Útest_per_bb_2â   ó   zTestPerBB.test_per_bb_2zÌ
define void @main(ptr %ptr, ptr %other) {
    call void @NRT_incref(ptr %ptr)
    call void @NRT_incref(ptr %ptr)
    call void @NRT_decref(ptr %ptr)
    call void @NRT_decref(ptr %other)
    ret void
}
c                 C   r   )NrD   ú!call void @NRT_decref(ptr %other))rn   Úper_bb_ir_3r!   r{   r‚   r\   r|   r   r   r   Útest_per_bb_3ò   r„   zTestPerBB.test_per_bb_3zü
; reordered
define void @main(ptr %ptr, ptr %other) {
    call void @NRT_incref(ptr %ptr)
    call void @NRT_decref(ptr %ptr)
    call void @NRT_decref(ptr %ptr)
    call void @NRT_decref(ptr %other)
    call void @NRT_incref(ptr %ptr)
    ret void
}
c                 C   r   )Nr€   r…   )rn   Úper_bb_ir_4r!   r{   r‚   r\   r|   r   r   r   Útest_per_bb_4  r„   zTestPerBB.test_per_bb_4N)r   r   r   r   ÚRefPruneSubpassesZPER_BBrt   rz   r}   r   rƒ   r†   r‡   rˆ   r‰   r   r   r   r   rw   È   s    
rw   c                   @   sP   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   rx   ry   )rn   Úper_diamond_1r!   Údiamondr|   r   r   r   Útest_per_diamond_1  r~   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   rx   ry   )rn   Úper_diamond_2r!   r   r|   r   r   r   Útest_per_diamond_2,  r~   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   rx   ©Nr   )rn   Úper_diamond_3r!   r   r|   r   r   r   Útest_per_diamond_3@  r~   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   rx   ry   )rn   Úper_diamond_4r!   r   r|   r   r   r   Útest_per_diamond_4T  r~   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   rx   )Nr€   )rn   Úper_diamond_5r!   r   r|   r   r   r   Útest_per_diamond_5i  r~   zTestDiamond.test_per_diamond_5N)r   r   r   r   rŠ   ZDIAMONDrt   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   rx   )Né   )rn   Úfanout_1r!   Úfanoutr|   r   r   r   Útest_fanout_1‚  r~   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   rx   r‘   )rn   Úfanout_2r!   r›   r|   r   r   r   Útest_fanout_2”  r~   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   rx   )Né   ©rn   Úfanout_3r!   r›   r|   r   r   r   Útest_fanout_3ª  r~   zTestFanout.test_fanout_3c                 C   s&   | j | jdd\}}|  |jd¡ d S )Nr?   rq   r   r    r|   r   r   r   Útest_fanout_3_limited®  s   z TestFanout.test_fanout_3_limitedN)r   r   r   r   r   rŠ   ZFANOUTrt   rš   rœ   r   rž   r¡   r¢   r£   r   r   r   r   r˜   n  s    r˜   c                   @   s\   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Zdd„ ZdS )Ú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   rx   ry   )rn   Úfanout_raise_1r!   Úfanout_raiser|   r   r   r   Útest_fanout_raise_1Ç  r~   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   rx   r‘   )rn   Úfanout_raise_2r!   r¦   r|   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   rx   ry   )rn   Úfanout_raise_3r!   r¦   r|   r   r   r   Útest_fanout_raise_3ñ  r~   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   rx   r‘   )rn   Úfanout_raise_4r!   r¦   r|   r   r   r   Útest_fanout_raise_4  r~   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   rx   ry   )rn   Úfanout_raise_5r!   r¦   r|   r   r   r   Útest_fanout_raise_5  r~   z#TestFanoutRaise.test_fanout_raise_5af  
define i32 @main(i8* %ptr, i1 %cond1, i1 %cond2, i1 %cond3, i8** %excinfo) {
bb_A:
    call void @NRT_incref(i8* %ptr)
    call void @NRT_incref(i8* %ptr)
    br i1 %cond1, label %bb_B, label %bb_C
bb_B:
    call void @NRT_decref(i8* %ptr)
    br i1 %cond2, label %bb_D, label %bb_E
bb_C:
    store i8* null, i8** %excinfo, !numba_exception_output !0
    ret i32 1
bb_D:
    call void @NRT_decref(i8* %ptr)
    ret i32 0
bb_E:
    call void @NRT_incref(i8* %ptr)
    br i1 %cond3, label %bb_F, label %bb_C
bb_F:
    call void @NRT_decref(i8* %ptr)
    call void @NRT_decref(i8* %ptr)
    ret i32 0
}
!0 = !{i1 1}
c                 C   rx   )Né   )rn   Úfanout_raise_6r!   r¦   r|   r   r   r   Útest_fanout_raise_68  r~   z#TestFanoutRaise.test_fanout_raise_6N)r   r   r   r   rŠ   ZFANOUT_RAISErt   r¥   r§   r¨   r©   rª   r«   r¬   r­   r®   r¯   r±   r²   r   r   r   r   r¤   µ  s    r¤   Ú__main__)ZunittestÚcollectionsr   Zllvmliter   r   r   Zllvmlite.testsr   Zllvmlite.tests.refprune_protoÚtestsZrefprune_protor   r   r   r   r=   Z
as_pointerr1   r*   ro   rw   r‹   r˜   r¤   r   rA   r   r   r   r   Ú<module>   s*    	 CcG 	ÿ