o
    ٴi,=                     @   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   O/home/kuhnn/.local/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                   @   s   e Zd Zdd ZdS )PassManagerMixinc                 C   s0   t   t j  }t jddd}t ||S )Nr   )speed_level
size_level)llvminitialize_native_targetTargetfrom_default_triplecreate_target_machinecreate_pipeline_tuning_optionscreate_pass_builder)r   tm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   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r3   r   FunctionTypeVoidTypeptr_tyFunctionr   mfntyr   r   r   make_incref9      zTestRefPrunePass.make_increfc                 C   r7   )N
NRT_decrefr9   r:   r?   r   r   r   make_decref=   rC   zTestRefPrunePass.make_decrefc                 C   "   t t dd}t j||ddS )N    r   switcherr9   r   r;   IntTyper>   r?   r   r   r   make_switcherA   rC   zTestRefPrunePass.make_switcherc                 C   rF   )N   r   brancherr9   rI   r?   r   r   r   make_brancherE   rC   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mainr9   memincrefdecrefunreachabler   rL      r   )default)r   ModulerB   rE   rK   rN   r;   r<   r=   r>   argsr3   append_basic_block	IRBuilderr   position_at_endcallAssertionErrorlenret_voidbranchcbranchswitch	enumerateadd_casetype)r   r/   r0   r@   	incref_fn	decref_fnswitcher_fnbrancher_fnrA   r	   ptrbbmapbbbuilderjump_targetsaction	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>rQ   rR   )rQ   rR   rL   rO   r8   rD   zBB )msg)	r   r   countget	functionsr3   blocksrz   r-   )r   r~   r1   r/   dr   vsn_increfn_decrefstatsdec_bbfrk   textr   r   r   check   s.   








zTestRefPrunePass.checkc                 C   s4   | \}}}|  ||}| |}| ||| d S r   )rx   r   r   )r   r.   r/   r0   r1   r}   outmodr   r   r   r
      s   
zTestRefPrunePass.generate_testN)r   r   r)   r   rB   rE   rK   rN   rx   r   r   r
   r   r3   r   r4   r   r   r   r   r6   0   s    6r6   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   ry   prologuer(   r{   r|   refprune_bitmaskdump_refprune_statsr,   )r   r}   r   r~   r(   r   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 NrT   )r   per_bb_ir_1r-   
basicblockr   r~   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(ptr %ptr))r   per_bb_ir_2r-   r   assertInrz   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   )NrT   !call void @NRT_decref(ptr %other))r   per_bb_ir_3r-   r   r   rz   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   )r   per_bb_ir_4r-   r   r   rz   r   r   r   r   test_per_bb_4  r   zTestPerBB.test_per_bb_4N)r   r   r)   r   RefPruneSubpassesPER_BBr   r   r   r   r   r   r   r   r   r   r   r   r   r      s    
r   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   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_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   r   )Nr   )r   per_diamond_5r-   r   r   r   r   r   test_per_diamond_5i  r   zTestDiamond.test_per_diamond_5N)r   r   r)   r   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_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   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 )NrL   r   r   r   r   r   r   r   test_fanout_3_limited  s   z TestFanout.test_fanout_3_limitedN)r   r   r)   r   r   r   FANOUTr   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   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_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   r   )N   )r   fanout_raise_6r-   r   r   r   r   r   test_fanout_raise_68  r   z#TestFanoutRaise.test_fanout_raise_6N)r   r   r)   r   r   FANOUT_RAISEr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r     s    r   __main__)unittestcollectionsr   llvmliter   r   r   llvmlite.testsr   llvmlite.tests.refprune_prototestsrefprune_protor   r   r   r*   rJ   
as_pointerr=   r6   r   r   r   r   r   r   rO   r   r   r   r   <module>   s*    	 CcG 	