o
    Td7                     @   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   o/home/ncw/WWW/www-new/content/articles/pi-bbp/venv/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casetest_)proto__dict__items
startswith)r   r   k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   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.   r3   r   r   r   make_decref3   r7   zTestRefPrunePass.make_decrefc                 C   "   t t dd}t j||ddS )N    r   switcherr-   r   r/   IntTyper2   r3   r   r   r   make_switcher7   r7   zTestRefPrunePass.make_switcherc                 C   r:   )Nr   r   brancherr-   r=   r3   r   r   r   make_brancher;   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 ]\}}|||||  qqFtd|S )Nmainr-   memincrefdecrefunreachabler   r      r   )default)r   Moduler6   r9   r?   rA   r/   r0   r1   r2   argsr'   append_basic_block	IRBuilderr   position_at_endcallAssertionErrorlenret_voidbranchcbranchswitch	enumerateadd_casetype)r	   r"   r#   r4   	incref_fn	decref_fnswitcher_fnbrancher_fnr5   r
   ptrbbmapbbbuilderjump_targetsaction	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 )
NrD   rE   )rD   rE   r   rB   r,   r8   zBB )msg)r   countget	functionsr'   blocksrn   r    )r	   rr   r$   r"   dr   vsn_increfn_decrefstatsdec_bbfr^   textr   r   r   check|   s.   








zTestRefPrunePass.checkc                 C   s4   | \}}}|  ||}| |}| ||| d S r   )rk   rt   r   )r	   r!   r"   r#   r$   rq   outmodr   r   r   r      s   
zTestRefPrunePass.generate_testN)r   r   r&   r   r6   r9   r?   rA   rk   rt   r   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)rl   rm   prologuero   rp   refprune_bitmaskdump_refprune_statsr   )r	   rq   r   rr   rs   beforeafterr   r   r   r      s   
zBaseTestByIR.checkr   )r   r   r&   r   r   r   r   r   r   r   r      s    r   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 NrG   )r   per_bb_ir_1r    
basicblockr	   rr   r~   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))r   per_bb_ir_2r    r   assertInrn   r   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   r   )NrG   !call void @NRT_decref(i8* %other))r   per_bb_ir_3r    r   r   rn   r   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   r   )Nr   r   )r   per_bb_ir_4r    r   r   rn   r   r   r   r   test_per_bb_4   r   zTestPerBB.test_per_bb_4N)r   r   r&   rl   RefPruneSubpassesPER_BBr   r   r   r   r   r   r   r   r   r   r   r   r   r      s    
r   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   r   r   )r   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   r   r   )r   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   r   Nr   )r   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   r   r   )r   per_diamond_4r    r   r   r   r   r   test_per_diamond_4C  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   r   )Nr   )r   per_diamond_5r    r   r   r   r   r   test_per_diamond_5X  r   zTestDiamond.test_per_diamond_5N)r   r   r&   rl   r   DIAMONDr   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   r   )N   )r   fanout_1r    fanoutr   r   r   r   test_fanout_1q  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   r   r   )r   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   r   )N   r   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   r   r   r   r   r   r   r   test_fanout_3_limited  s   z TestFanout.test_fanout_3_limitedN)r   r   r&   r   rl   r   FANOUTr   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   r   r   )r   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   r   r   )r   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   r   r   )r   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   r   r   )r   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   r   r   )r   fanout_raise_5r    r   r   r   r   r   test_fanout_raise_5  r   z#TestFanoutRaise.test_fanout_raise_5N)r   r   r&   rl   r   FANOUT_RAISEr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s    r   __main__)unittestllvmliter   r   rl   llvmlite.testsr    r   r   r   r   r>   
as_pointerr1   r*   r   r   r   r   r   r   rB   r   r   r   r   <module>   s"    {CcGi