o
    7fTL                     @  s6  d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z: G dd dZ;dHddZ<dIddZ=dJddZ>edZ?eeee@f e
e? f ZAG dd dee? ZBee
e? e
e? f ZCG dd de.eCe?  ZDG dd deDe: ZEdKd d!ZF	"dLdMd'd(ZGG d)d* d*eDe: ZHdNd,d-ZIG d.d/ d/eDe: ZJdKd0d1ZKdOd4d5ZLG d6d7 d7eDe: ZMdPd8d9ZNdZOd:ZP	;dQdRdFdGZQd;S )SzData-flow analyses.    )annotations)abstractmethod)DictGenericIterableIteratorSetTupleTypeVar)
all_values)+AssignAssignMulti
BasicBlockBoxBranchCallCallCCastComparisonOp	ControlOpExtendFloatFloatComparisonOpFloatNegFloatOpGetAttrGetElementPtrGoto
InitStaticIntegerIntOp	KeepAliveLoadAddressLoadErrorValue
LoadGlobalLoadLiteralLoadMem
LoadStatic
MethodCallOp	OpVisitorRaiseStandardError
RegisterOpReturnSetAttrSetMemTruncateTupleGetTupleSetUnborrowUnboxUnreachableValuec                   @  s$   e Zd ZdZdd	d
ZdddZdS )CFGzyControl-flow graph.

    Node 0 is always assumed to be the entry point. There must be a
    non-empty set of exits.
    succ"dict[BasicBlock, list[BasicBlock]]predexitsset[BasicBlock]returnNonec                 C  s   |sJ || _ || _|| _d S N)r8   r:   r;   )selfr8   r:   r;    rA   P/home/ertert/spirit/venv/lib/python3.10/site-packages/mypyc/analysis/dataflow.py__init__?   s   
zCFG.__init__strc                 C  s,   t | jdd d}d| d| j d| j S )Nc                 S  s
   t | jS r?   )intlabel)erA   rA   rB   <lambda>K   s   
 zCFG.__str__.<locals>.<lambda>)keyzexits: z
succ: z
pred: )sortedr;   r8   r:   )r@   r;   rA   rA   rB   __str__J   s   zCFG.__str__N)r8   r9   r:   r9   r;   r<   r=   r>   r=   rD   )__name__
__module____qualname____doc__rC   rK   rA   rA   rA   rB   r7   8   s    
r7   blockslist[BasicBlock]r=   c           
      C  s   i }i }t  }| D ];}tdd |jdd D rJ dt|j }|s+|| |g| D ]}|jr;||j q0|||< g ||< q	|	 D ]\}}|D ]	}	||	 | qOqIt
|||S )zCalculate basic block control-flow graph.

    The result is a dictionary like this:

         basic block index -> (successors blocks, predecesssor blocks)
    c                 s  s    | ]}t |tV  qd S r?   )
isinstancer   ).0oprA   rA   rB   	<genexpr>Z   s    

zget_cfg.<locals>.<genexpr>Nz-Control-flow ops must be at the end of blocks)setanyopslist
terminatortargetsadderror_handlerappenditemsr7   )
rQ   succ_mappred_mapr;   blockr8   error_pointprevnxtrF   rA   rA   rB   get_cfgO   s.   


rh   rF   r   c                 C  s.   t | jdkrt| jd tr| jd j} | S )N   rW   )lenrZ   rS   r   rF   )rF   rA   rA   rB   get_real_targetz   s   rk   r>   c                 C  s   d}|rJ| D ]}t |j D ]\}}|j|t| qqd}t| }|  }|   t |D ]\}}|dks=|j| rC| 	| q0d}q0|sdS dS )zCleanup the control flow graph.

    This eliminates obviously dead basic blocks and eliminates blocks that contain
    nothing but a single jump.

    There is a lot more that could be done.
    TFr   N)
	enumerater\   r]   
set_targetrk   rh   copyclearr:   r`   )rQ   changedrd   itgtcfgorig_blocksrA   rA   rB   cleanup_cfg   s   ru   Tc                   @  s    e Zd ZdddZdd	d
ZdS )AnalysisResultbeforeAnalysisDict[T]afterr=   r>   c                 C  s   || _ || _d S r?   rx   rz   )r@   rx   rz   rA   rA   rB   rC      s   
zAnalysisResult.__init__rD   c                 C  s   d| j  d| j dS )Nzbefore: z
after: 
r{   )r@   rA   rA   rB   rK      s   zAnalysisResult.__str__N)rx   ry   rz   ry   r=   r>   rL   )rM   rN   rO   rC   rK   rA   rA   rA   rB   rw      s    
rw   c                   @  sf  e Zd ZdhddZedidd	ZedjddZedkddZedlddZdmddZ	dnddZ
doddZdpddZdqd d!Zdrd#d$Zdsd&d'Zdtd)d*Zdud,d-Zdvd/d0Zdwd2d3Zdxd5d6Zdyd8d9Zdzd;d<Zd{d>d?Zd|dAdBZd}dDdEZd~dGdHZddJdKZddMdNZddPdQZddSdTZddVdWZddYdZZ dd\d]Z!dd_d`Z"ddbdcZ#ddedfZ$dgS )BaseAnalysisVisitorrU   r   r=   GenAndKill[T]c                 C     t  t  fS r?   rX   r@   rU   rA   rA   rB   
visit_goto      zBaseAnalysisVisitor.visit_gotor,   c                 C     t r?   NotImplementedErrorr   rA   rA   rB   visit_register_op      z%BaseAnalysisVisitor.visit_register_opr   c                 C  r   r?   r   r   rA   rA   rB   visit_assign   r   z BaseAnalysisVisitor.visit_assignr   c                 C  r   r?   r   r   rA   rA   rB   visit_assign_multi   r   z&BaseAnalysisVisitor.visit_assign_multir/   c                 C  r   r?   r   r   rA   rA   rB   visit_set_mem   r   z!BaseAnalysisVisitor.visit_set_memr   c                 C  
   |  |S r?   r   r   rA   rA   rB   
visit_call      
zBaseAnalysisVisitor.visit_callr(   c                 C  r   r?   r   r   rA   rA   rB   visit_method_call   r   z%BaseAnalysisVisitor.visit_method_callr#   c                 C  r   r?   r   r   rA   rA   rB   visit_load_error_value   r   z*BaseAnalysisVisitor.visit_load_error_valuer%   c                 C  r   r?   r   r   rA   rA   rB   visit_load_literal   r   z&BaseAnalysisVisitor.visit_load_literalr   c                 C  r   r?   r   r   rA   rA   rB   visit_get_attr   r   z"BaseAnalysisVisitor.visit_get_attrr.   c                 C  r   r?   r   r   rA   rA   rB   visit_set_attr   r   z"BaseAnalysisVisitor.visit_set_attrr'   c                 C  r   r?   r   r   rA   rA   rB   visit_load_static   r   z%BaseAnalysisVisitor.visit_load_staticr   c                 C  r   r?   r   r   rA   rA   rB   visit_init_static   r   z%BaseAnalysisVisitor.visit_init_staticr1   c                 C  r   r?   r   r   rA   rA   rB   visit_tuple_get   r   z#BaseAnalysisVisitor.visit_tuple_getr2   c                 C  r   r?   r   r   rA   rA   rB   visit_tuple_set   r   z#BaseAnalysisVisitor.visit_tuple_setr   c                 C  r   r?   r   r   rA   rA   rB   	visit_box   r   zBaseAnalysisVisitor.visit_boxr4   c                 C  r   r?   r   r   rA   rA   rB   visit_unbox   r   zBaseAnalysisVisitor.visit_unboxr   c                 C  r   r?   r   r   rA   rA   rB   
visit_cast   r   zBaseAnalysisVisitor.visit_castr+   c                 C  r   r?   r   r   rA   rA   rB   visit_raise_standard_error   r   z.BaseAnalysisVisitor.visit_raise_standard_errorr   c                 C  r   r?   r   r   rA   rA   rB   visit_call_c   r   z BaseAnalysisVisitor.visit_call_cr0   c                 C  r   r?   r   r   rA   rA   rB   visit_truncate   r   z"BaseAnalysisVisitor.visit_truncater   c                 C  r   r?   r   r   rA   rA   rB   visit_extend   r   z BaseAnalysisVisitor.visit_extendr$   c                 C  r   r?   r   r   rA   rA   rB   visit_load_global   r   z%BaseAnalysisVisitor.visit_load_globalr    c                 C  r   r?   r   r   rA   rA   rB   visit_int_op   r   z BaseAnalysisVisitor.visit_int_opr   c                 C  r   r?   r   r   rA   rA   rB   visit_float_op   r   z"BaseAnalysisVisitor.visit_float_opr   c                 C  r   r?   r   r   rA   rA   rB   visit_float_neg   r   z#BaseAnalysisVisitor.visit_float_negr   c                 C  r   r?   r   r   rA   rA   rB   visit_comparison_op   r   z'BaseAnalysisVisitor.visit_comparison_opr   c                 C  r   r?   r   r   rA   rA   rB   visit_float_comparison_op  r   z-BaseAnalysisVisitor.visit_float_comparison_opr&   c                 C  r   r?   r   r   rA   rA   rB   visit_load_mem  r   z"BaseAnalysisVisitor.visit_load_memr   c                 C  r   r?   r   r   rA   rA   rB   visit_get_element_ptr  r   z)BaseAnalysisVisitor.visit_get_element_ptrr"   c                 C  r   r?   r   r   rA   rA   rB   visit_load_address  r   z&BaseAnalysisVisitor.visit_load_addressr!   c                 C  r   r?   r   r   rA   rA   rB   visit_keep_alive  r   z$BaseAnalysisVisitor.visit_keep_aliver3   c                 C  r   r?   r   r   rA   rA   rB   visit_unborrow  r   z"BaseAnalysisVisitor.visit_unborrowN)rU   r   r=   r~   )rU   r,   r=   r~   )rU   r   r=   r~   )rU   r   r=   r~   )rU   r/   r=   r~   )rU   r   r=   r~   )rU   r(   r=   r~   )rU   r#   r=   r~   )rU   r%   r=   r~   )rU   r   r=   r~   )rU   r.   r=   r~   )rU   r'   r=   r~   )rU   r   r=   r~   )rU   r1   r=   r~   )rU   r2   r=   r~   )rU   r   r=   r~   )rU   r4   r=   r~   )rU   r   r=   r~   )rU   r+   r=   r~   )rU   r   r=   r~   )rU   r0   r=   r~   )rU   r   r=   r~   )rU   r$   r=   r~   )rU   r    r=   r~   )rU   r   r=   r~   )rU   r   r=   r~   )rU   r   r=   r~   )rU   r   r=   r~   )rU   r&   r=   r~   )rU   r   r=   r~   )rU   r"   r=   r~   )rU   r!   r=   r~   )rU   r3   r=   r~   )%rM   rN   rO   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rA   rA   rA   rB   r}      sL    



























r}   c                   @  sb   e Zd ZdZd!d"ddZd#ddZd$ddZd%ddZd&ddZd'ddZ	d(ddZ
d)ddZd S )*DefinedVisitora  Visitor for finding defined registers.

    Note that this only deals with registers and not temporaries, on
    the assumption that we never access temporaries when they might be
    undefined.

    If strict_errors is True, then we regard any use of LoadErrorValue
    as making a register undefined. Otherwise we only do if
    `undefines` is set on the error value.

    This lets us only consider the things we care about during
    uninitialized variable checking while capturing all possibly
    undefined things for refcounting.
    Fstrict_errorsboolr=   r>   c                 C  
   || _ d S r?   r   )r@   r   rA   rA   rB   rC   %  r   zDefinedVisitor.__init__rU   r   GenAndKill[Value]c                 C  r   r?   r   r   rA   rA   rB   visit_branch(  r   zDefinedVisitor.visit_branchr-   c                 C  r   r?   r   r   rA   rA   rB   visit_return+  r   zDefinedVisitor.visit_returnr5   c                 C  r   r?   r   r   rA   rA   rB   visit_unreachable.  r   z DefinedVisitor.visit_unreachabler,   c                 C  r   r?   r   r   rA   rA   rB   r   1  r   z DefinedVisitor.visit_register_opr   c                 C  s6   t |jtr|jjs| jrt |jhfS |jht fS r?   )rS   srcr#   	undefinesr   rX   destr   rA   rA   rB   r   4  s   zDefinedVisitor.visit_assignr   c                 C  r   r?   r   r   rA   rA   rB   r   ;  s   z!DefinedVisitor.visit_assign_multir/   c                 C  r   r?   r   r   rA   rA   rB   r   ?  r   zDefinedVisitor.visit_set_memNF)r   r   r=   r>   rU   r   r=   r   rU   r-   r=   r   rU   r5   r=   r   rU   r,   r=   r   rU   r   r=   r   rU   r   r=   r   rU   r/   r=   r   )rM   rN   rO   rP   rC   r   r   r   r   r   r   r   rA   rA   rA   rB   r     s    





r   rs   initial_defined
set[Value]AnalysisResult[Value]c                 C  s   t | |t |dtdS )zCalculate potentially defined registers at each CFG location.

    A register is defined if it has a value along some path from the initial location.
    FrQ   rs   gen_and_killinitialbackwardkind)run_analysisr   MAYBE_ANALYSIS)rQ   rs   r   rA   rA   rB   analyze_maybe_defined_regsC  s   r   FregsIterable[Value]r   r   c              	   C  s    t | |t|d|dtt|dS )aI  Calculate always defined registers at each CFG location.

    This analysis can work before exception insertion, since it is a
    sound assumption that registers defined in a block might not be
    initialized in its error handler.

    A register is defined if it has a value along all paths from the
    initial location.
    r   FrQ   rs   r   r   r   r   universe)r   r   MUST_ANALYSISrX   )rQ   rs   r   r   r   rA   rA   rB   analyze_must_defined_regsT  s   r   c                   @  s\   e Zd ZdddZd d
dZd!ddZd"ddZd#ddZd$ddZd%ddZ	d&ddZ
dS )'BorrowedArgumentsVisitorargsr   r=   r>   c                 C  r   r?   )r   )r@   r   rA   rA   rB   rC   p  r   z!BorrowedArgumentsVisitor.__init__rU   r   r   c                 C  r   r?   r   r   rA   rA   rB   r   s  r   z%BorrowedArgumentsVisitor.visit_branchr-   c                 C  r   r?   r   r   rA   rA   rB   r   v  r   z%BorrowedArgumentsVisitor.visit_returnr5   c                 C  r   r?   r   r   rA   rA   rB   r   y  r   z*BorrowedArgumentsVisitor.visit_unreachabler,   c                 C  r   r?   r   r   rA   rA   rB   r   |  r   z*BorrowedArgumentsVisitor.visit_register_opr   c                 C  s&   |j | jv rt |j hfS t t fS r?   )r   r   rX   r   rA   rA   rB   r     s   z%BorrowedArgumentsVisitor.visit_assignr   c                 C  r   r?   r   r   rA   rA   rB   r     r   z+BorrowedArgumentsVisitor.visit_assign_multir/   c                 C  r   r?   r   r   rA   rA   rB   r     r   z&BorrowedArgumentsVisitor.visit_set_memN)r   r   r=   r>   r   r   r   r   r   r   r   )rM   rN   rO   rC   r   r   r   r   r   r   r   rA   rA   rA   rB   r   o  s    






r   borrowedc              	   C  s   t | |t||dt|dS )zCalculate arguments that can use references borrowed from the caller.

    When assigning to an argument, it no longer is borrowed.
    Fr   )r   r   r   )rQ   rs   r   rA   rA   rB   analyze_borrowed_arguments  s   r   c                   @  R   e Zd ZdddZddd	ZdddZdddZdddZdddZd ddZ	dS )!UndefinedVisitorrU   r   r=   r   c                 C  r   r?   r   r   rA   rA   rB   r     r   zUndefinedVisitor.visit_branchr-   c                 C  r   r?   r   r   rA   rA   rB   r     r   zUndefinedVisitor.visit_returnr5   c                 C  r   r?   r   r   rA   rA   rB   r     r   z"UndefinedVisitor.visit_unreachabler,   c                 C  s   t  |js	|hfS t  fS r?   )rX   is_voidr   rA   rA   rB   r     s   z"UndefinedVisitor.visit_register_opr   c                 C     t  |jhfS r?   rX   r   r   rA   rA   rB   r        zUndefinedVisitor.visit_assignr   c                 C  r   r?   r   r   rA   rA   rB   r     r   z#UndefinedVisitor.visit_assign_multir/   c                 C  r   r?   r   r   rA   rA   rB   r     r   zUndefinedVisitor.visit_set_memNr   r   r   r   r   r   r   
rM   rN   rO   r   r   r   r   r   r   r   rA   rA   rA   rB   r     s    





r   c                 C  s(   t tg | | }t| |t |dtdS )zCalculate potentially undefined registers at each CFG location.

    A register is undefined if there is some path from initial block
    where it has an undefined value.

    Function arguments are assumed to be always defined.
    Fr   )rX   r   r   r   r   )rQ   rs   r   initial_undefinedrA   rA   rB   analyze_undefined_regs  s   
r   rU   r)   c                 C  s0   t  }|  D ]}t|ttfs|| q|S r?   )rX   sourcesrS   r   r   r^   )rU   resultsourcerA   rA   rB   non_trivial_sources  s   
r   c                   @  r   )!LivenessVisitorrU   r   r=   r   c                 C     t |t fS r?   r   rX   r   rA   rA   rB   r     r   zLivenessVisitor.visit_branchr-   c                 C  s*   t |jttfs|jht fS t t fS r?   )rS   valuer   r   rX   r   rA   rA   rB   r     s   zLivenessVisitor.visit_returnr5   c                 C  r   r?   r   r   rA   rA   rB   r     r   z!LivenessVisitor.visit_unreachabler,   c                 C  s"   t |}|js||hfS |t fS r?   )r   r   rX   )r@   rU   genrA   rA   rB   r     s   

z!LivenessVisitor.visit_register_opr   c                 C     t ||jhfS r?   r   r   r   rA   rA   rB   r        zLivenessVisitor.visit_assignr   c                 C  r   r?   r   r   rA   rA   rB   r     r   z"LivenessVisitor.visit_assign_multir/   c                 C  r   r?   r   r   rA   rA   rB   r     r   zLivenessVisitor.visit_set_memNr   r   r   r   r   r   r   r   rA   rA   rA   rB   r     s    





r   c                 C  s   t | |t t dtdS )zCalculate live registers at each CFG location.

    A register is live at a location if it can be read along some CFG path starting
    from the location.
    Tr   )r   r   rX   r   )rQ   rs   rA   rA   rB   analyze_live_regs  s   r   ri   Nr   OpVisitor[GenAndKill[T]]r   set[T]r   rE   r   r   set[T] | NoneAnalysisResult[T]c                  C  s~  i }i }| D ]3}	t  }
t  }|	j}|rtt|}|D ]}||\}}|
| |B }
|| |B }q|
||	< |||	< qt| }|sG|ddd }t |}i }i }| D ]%}	|tkrbt  ||	< t  ||	< qQ|dusjJ dt |||	< t |||	< qQ|r|j}|j}n|j}|j}|r| }|	| || rd}|| D ]}|du rt || }q|tkr||| O }q||| M }q|dusJ nt |}|||< |||  || B }||| kr|| D ]}||vr|
| || q|||< |si }i }| D ]7}	|	}|| }t|	j}|rtt|}|D ]\}}||||f< ||\}}|| |B }||||f< qq|r:||}}t||S )aP  Run a general set-based data flow analysis.

    Args:
        blocks: All basic blocks
        cfg: Control-flow graph for the code
        gen_and_kill: Implementation of gen and kill functions for each op
        initial: Value of analysis for the entry points (for a forward analysis) or the
            exit points (for a backward analysis)
        kind: MUST_ANALYSIS or MAYBE_ANALYSIS
        backward: If False, the analysis is a forward analysis; it's backward otherwise
        universe: For a must analysis, the set of all possible values. This is the starting
            value for the work list algorithm, which will narrow this down until reaching a
            fixed point. For a maybe analysis the iteration always starts from an empty set
            and this argument is ignored.

    Return analysis results: (before, after)
    NrW   z,Universe must be defined for a must analysis)rX   rZ   r[   reversedacceptr   r8   r:   popremover`   r^   rl   rw   ) rQ   rs   r   r   r   r   r   	block_gen
block_killrd   r   killrZ   rU   opgenopkillworklistworksetrx   rz   rc   rb   rF   
new_beforer:   	new_afterr8   	op_beforeop_aftercurops_enumidxrA   rA   rB   r     s   







r   )rQ   rR   r=   r7   )rF   r   r=   r   )rQ   rR   r=   r>   )rQ   rR   rs   r7   r   r   r=   r   r   )rQ   rR   rs   r7   r   r   r   r   r   r   r=   r   )rQ   rR   rs   r7   r   r   r=   r   )rU   r)   r=   r   )rQ   rR   rs   r7   r=   r   r?   )rQ   rR   rs   r7   r   r   r   r   r   rE   r   r   r   r   r=   r   )RrP   
__future__r   abcr   typingr   r   r   r   r   r	   r
   mypyc.ir.func_irr   mypyc.ir.opsr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   rh   rk   ru   rv   rE   AnalysisDictrw   
GenAndKillr}   r   r   r   r   r   r   r   r   r   r   r   r   r   rA   rA   rA   rB   <module>   s<    $/

+
	i
.




