
    we7                     z   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 Z
 G d d	e          Z ej        d
                                          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Zedk    r e j                     dS dS )    N)ir)binding)TestCase   )refprune_protoc              #       K    fd}t           j                                        D ],\  }}|                    d          rd|  ||          fV  -d S )Nc                 D      fd}d j          d j         |_        |S )Nc                      |           S N )selffngenerate_tests    <lib/python3.11/site-packages/llvmlite/tests/test_refprune.pywrappedz-_iterate_cases.<locals>.wrap.<locals>.wrapped   s     =r***    zgenerated test for .)
__module____name____doc__)r   r   r   s   ` r   wrapz_iterate_cases.<locals>.wrap
   sB    	+ 	+ 	+ 	+ 	+ 	+MMMMMr   casetest_)proto__dict__items
startswith)r   r   kcase_fns   `   r   _iterate_casesr    	   s           n**,, - -
7<< 	-!++ttG}},,,,- -r   c                   T    e Zd ZdZd Z ee          D ]\  ZZe e            e<   dS )TestRefPrunePrototypez-
    Test that the prototype is working.
    c                      |            \  }}}t          j        ||                                          }|                     ||           d S r   )r   FanoutAlgorithmrunassertEqual)r   case_gennodesedgesexpectedgots         r   r   z#TestRefPrunePrototype.generate_test   sN    !)uh#E51155773'''''r   N)	r   r   __qualname__r   r   r    namer   localsr   r   r   r"   r"      s]         ( ( ( %n]33  
d r   r"      c                   ~    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Z ee          D ]\  ZZe e            e<   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                     t          j        t          j                    t          g          }t          j        ||d          S )N
NRT_increfr-   r   FunctionTypeVoidTypeptr_tyFunctionr   mfntys      r   make_increfzTestRefPrunePass.make_incref/   2    r{}}vh77{1d6666r   c                     t          j        t          j                    t          g          }t          j        ||d          S )N
NRT_decrefr4   r5   r:   s      r   make_decrefzTestRefPrunePass.make_decref3   r>   r   c                 ~    t          j        t          j        d          d          }t          j        ||d          S )N    r   switcherr4   r   r6   IntTyper9   r:   s      r   make_switcherzTestRefPrunePass.make_switcher7   s2    rz"~~r22{1d4444r   c                 ~    t          j        t          j        d          d          }t          j        ||d          S )Nr   r   brancherr4   rE   r:   s      r   make_brancherzTestRefPrunePass.make_brancher;   s2    rz!}}b11{1d4444r   c                 B   t          j                    }|                     |          }|                     |          }|                     |          }|                     |          }t          j        t          j                    t          g          }t          j	        ||d          }	|	j
        \  }
d|
_        i }|D ]}|	                    |          ||<   t          j                    }|                                D ]\  }}|                    ||                    ||         D ]L}|dk    r|                    ||
g            |dk    r|                    ||
g           >t#          d          t%          |          }|dk    r|                                 |dk    r |\  }|                    ||                    |d	k    r@|\  }}|                    |d
          }|                    |||         ||                    |d	k    r}|                    |d
          }|^}}|                    |||                   }t/          |          D ]4\  }}|                    |                    |          ||                    5t#          d          |S )Nmainr4   memincrefdecrefunreachabler   r      r   )default)r   Moduler=   rA   rG   rJ   r6   r7   r8   r9   argsr-   append_basic_block	IRBuilderr   position_at_endcallAssertionErrorlenret_voidbranchcbranchswitch	enumerateadd_casetype)r   r(   r)   r;   	incref_fn	decref_fnswitcher_fnbrancher_fnr<   r   ptrbbmapbbbuilderjump_targetsaction	n_targetsdstleftrightselheadtailswis                            r   generate_irzTestRefPrunePass.generate_ir?   s   IKK$$Q''	$$Q''	((++((++r{}}vh77[Dv... 	2 	2B--b11E"II,.. % 	4 	4B##E"I...) 8 8X%%LLSE2222x''LLSE2222(777 L))IA~~  """"a$uSz****a ,ull;33U4[%,????Qll;33 ,^^Ct^=='oo 9 9FAsKKU3Z88889 %]333r   c                     t          j        t          |                    }t          j                    }|                                 |                    |           |S r   )llvmparse_assemblystrModulePassManageradd_refprune_passr%   )r   irmodmodpms       r   apply_refprunezTestRefPrunePass.apply_refpruneu   sL    !#e**--#%%

s
r   c                    i }|                                 D ]7\  }}|                    d          }|                    d          }||d||<   8|                                 D ]K\  }}	|                    |          r1|	dxx         dz  cc<   ||         D ]}
||
         dxx         dz  cc<   L|j        D ]}|j        dk    r n|j        D ]}||j                 }	t          |          }|                    d          }|                    d          }|                     |	d         |d| 	           |                     |	d         |d| 	           d S )
NrN   rO   )rN   rO   r   rL   r3   r@   zBB )msg)r   countget	functionsr-   blocksry   r&   )r   r}   r*   r(   dr   vsn_increfn_decrefstatsdec_bbfrh   texts                 r   checkzTestRefPrunePass.check|   s   [[]] 	< 	<EArxx))Hxx))H&(;;AaDD		 	- 	-HAu||A -h1$&qk - -FfIh'''1,''''  	 	Av   ( 	H 	HBbgJEr77Dzz,//Hzz,//HU8_hJ"JJGGGU8_hJ"JJGGGG	H 	Hr   c                      |            \  }}}|                      ||          }|                     |          }|                     |||           d S r   )ru   r   r   )r   r'   r(   r)   r*   r|   outmods          r   r   zTestRefPrunePass.generate_test   sX    !)uh  ..$$U++

68U+++++r   N)r   r   r,   r   r=   rA   rG   rJ   ru   r   r   r   r    r-   r   r.   r   r   r   r1   r1   &   s         7 7 77 7 75 5 55 5 54 4 4l  H H H4, , , %n]33  
d r   r1   c                       e Zd ZdZdZddZdS )BaseTestByIRr   zG
declare void @NRT_incref(i8* %ptr)
declare void @NRT_decref(i8* %ptr)
Nc                 Z   t          j        | j         d|           }t          j                    }||                    | j                   n|                    | j        |           t          j                    }|                    |           t          j                    }|||z
  fS )N
subgraph_limit)rw   rx   prologuerz   r{   refprune_bitmaskdump_refprune_statsr%   )r   r|   r   r}   r~   beforeafters          r   r   zBaseTestByIR.check   s    !T]"="=e"="=>>#%%!  !67777  !60> ! @ @ @)++
s(**EFN""r   r   )r   r   r,   r   r   r   r   r   r   r   r      s5        H
# # # # # #r   r   c                   N    e Zd Zej        j        ZdZd ZdZ	d Z
dZd ZdZ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                 v    |                      | j                  \  }}|                     |j        d           d S NrQ   )r   per_bb_ir_1r&   
basicblockr   r}   r   s      r   test_per_bb_1zTestPerBB.test_per_bb_1   s9    ZZ 011
U)1-----r   z
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                     |                      | j                  \  }}|                     |j        d           |                     dt          |                     d S )N   zcall void @NRT_incref(i8* %ptr))r   per_bb_ir_2r&   r   assertInry   r   s      r   test_per_bb_2zTestPerBB.test_per_bb_2   sT    ZZ 011
U)1---7SBBBBBr   z
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                     |                      | j                  \  }}|                     |j        d           |                     dt          |                     d S )NrQ   !call void @NRT_decref(i8* %other))r   per_bb_ir_3r&   r   r   ry   r   s      r   test_per_bb_3zTestPerBB.test_per_bb_3   T    ZZ 011
U)1---93s88DDDDDr   z
; 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                     |                      | j                  \  }}|                     |j        d           |                     dt          |                     d S )Nr   r   )r   per_bb_ir_4r&   r   r   ry   r   s      r   test_per_bb_4zTestPerBB.test_per_bb_4   r   r   N)r   r   r,   rw   RefPruneSubpassesPER_BBr   r   r   r   r   r   r   r   r   r   r   r   r   r      s        -4K. . .	KC C CKE E E
KE E E E Er   r   c                   X    e Zd Zej        j        ZdZd ZdZ	d Z
dZd ZdZd Zd	Z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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   per_diamond_1r&   diamondr   s      r   test_per_diamond_1zTestDiamond.test_per_diamond_1  8    ZZ 233
U*****r   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:
    br label %bb_D
bb_C:
    br label %bb_D
bb_D:
    call void @NRT_decref(i8* %ptr)
    ret void
}
c                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   per_diamond_2r&   r   r   s      r   test_per_diamond_2zTestDiamond.test_per_diamond_2  r   r   a3  
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                 v    |                      | j                  \  }}|                     |j        d           d S Nr   )r   per_diamond_3r&   r   r   s      r   test_per_diamond_3zTestDiamond.test_per_diamond_3/  r   r   a5  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   per_diamond_4r&   r   r   s      r   test_per_diamond_4zTestDiamond.test_per_diamond_4C  r   r   a0  
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                 v    |                      | j                  \  }}|                     |j        d           d S )Nr   )r   per_diamond_5r&   r   r   s      r   test_per_diamond_5zTestDiamond.test_per_diamond_5X  r   r   N)r   r   r,   rw   r   DIAMONDr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s        -5	M+ + +M+ + +M + + +M + + +M"+ + + + +r   r   c                   N    e Zd ZdZej        j        ZdZd Z	dZ
d ZdZd Z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                 v    |                      | j                  \  }}|                     |j        d           d S )N   )r   fanout_1r&   fanoutr   s      r   test_fanout_1zTestFanout.test_fanout_1q  7    ZZ..
Uq)))))r   a6  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_2r&   r   r   s      r   test_fanout_2zTestFanout.test_fanout_2  r   r   a}  
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                 v    |                      | j                  \  }}|                     |j        d           d S )N   r   fanout_3r&   r   r   s      r   test_fanout_3zTestFanout.test_fanout_3  r   r   c                 z    |                      | j        d          \  }}|                     |j        d           d S )Nr   r   r   r   r   s      r   test_fanout_3_limitedz TestFanout.test_fanout_3_limited  s=     ZZaZ@@
Uq)))))r   N)r   r   r,   r   rw   r   FANOUTr   r   r   r   r   r   r   r   r   r   r   r   r   ]  s}          -4H* * *H* * *H$* * ** * * * *r   r   c                   X    e Zd Zej        j        ZdZd ZdZ	d Z
dZd ZdZd Zd	Z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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_raise_1r&   fanout_raiser   s      r   test_fanout_raise_1z#TestFanoutRaise.test_fanout_raise_1  9    ZZ 344
U+Q/////r   a:  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_raise_2r&   r   r   s      r   test_fanout_raise_2z#TestFanoutRaise.test_fanout_raise_2  s;     ZZ 344
U+Q/////r   a:  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_raise_3r&   r   r   s      r   test_fanout_raise_3z#TestFanoutRaise.test_fanout_raise_3  r   r   a!  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_raise_4r&   r   r   s      r   test_fanout_raise_4z#TestFanoutRaise.test_fanout_raise_4  r   r   a  
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                 v    |                      | j                  \  }}|                     |j        d           d S r   )r   fanout_raise_5r&   r   r   s      r   test_fanout_raise_5z#TestFanoutRaise.test_fanout_raise_5  r   r   N)r   r   r,   rw   r   FANOUT_RAISEr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s        -:N0 0 0N 0 0 0N 0 0 0N0 0 0N$0 0 0 0 0r   r   __main__)unittestllvmliter   r   rw   llvmlite.testsr    r   r   r    r"   rF   
as_pointerr8   r1   r   r   r   r   r   r   rL   r   r   r   <module>r      s          $ $ $ $ $ $ # # # # # # % % % % % %	- 	- 	-    H    
A	!	!	#	#x x x x xx x x xv# # # # #8 # # #,@E @E @E @E @E @E @E @EF`+ `+ `+ `+ `+, `+ `+ `+FD* D* D* D* D* D* D* D*Nf0 f0 f0 f0 f0l f0 f0 f0R zHMOOOOO r   