NL i?LdZddlmZddlmZddlmZmZddlm Z m Z ddl m Z m Z mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZm 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:m;Z;GddZd%d Z?e dZ@eAeBeeCfeDe@fZEGdde e@ZFeBeDe@eDe@fZGGdde,eGe@ZHGddeHe;ZI d&dZJ d' d(dZKGddeHe;ZL d)dZMGddeHe;ZNd*dZOGddeHe;ZPd+dZQdZRd ZS d, d-d"ZTy!).zData-flow analyses.) annotations)abstractmethod)IterableIterator)GenericTypeVar)0Assign AssignMulti BasicBlockBoxBranchCallCallCCast ComparisonOp ControlOpDecRefExtendFloatFloatComparisonOpFloatNegFloatOpGetAttr GetElementPtrGotoIncRef InitStaticIntegerIntOp KeepAlive LoadAddressLoadErrorValue LoadGlobal LoadLiteralLoadMem LoadStatic MethodCallOp OpVisitor PrimitiveOpRaiseStandardError RegisterOpReturnSetAttr SetElementSetMemTruncateTupleGetTupleSetUnborrowUnboxUndef UnreachableValuec0eZdZdZ ddZddZy)CFGzyControl-flow graph. Node 0 is always assumed to be the entry point. There must be a non-empty set of exits. c6|sJ||_||_||_yN)succpredexits)selfr=r>r?s ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/mypyc/analysis/dataflow.py__init__z CFG.__init__Ds  u   cpt|jd}d|d|jd|jS)Nc,t|jSr<)intlabel)es rAzCFG.__str__..PsQWWrC)keyzexits: z succ: z pred: )sortedr?r=r>)r@r?s rA__str__z CFG.__str__Os4tzz'=>x {(499+FFrCN)r="dict[BasicBlock, list[BasicBlock]]r>rMr?zset[BasicBlock]returnNonerNstr)__name__ __module__ __qualname____doc__rBrLrCrAr:r:=s8 0 1    GrCr:F) use_yieldscri}i}t}|D]}td|jddDrJd|rHt|jt r.|jj r|jj g}n#t|jj}|s|j||g|zD]*}|js|j|j,|||<g||<|jD] \}} | D]} || j|"t|||S)zCalculate basic block control-flow graph. If use_yields is set, then we treat returns inserted by yields as gotos instead of exits. c3<K|]}t|tywr<) isinstancer).0ops rA zget_cfg..^s *,Jr9 % sNz-Control-flow ops must be at the end of blocks)setanyopsrZ terminatorr- yield_targetlisttargetsadd error_handlerappenditemsr:) blocksrWsucc_mappred_mapr?blockr= error_pointprevnxtrGs rAget_cfgrqTsG H35H EE 05 #2   ; : ;  *U%5%5v>5CSCSC`C`$$112D((0023D IIe "7T> 7K(( K556 7;<^^%) c )E UO " "4 ( )) x5 ))rCct|jdk(r6t|jdtr|jdj}|S)Nr^)lenrarZrrG)rGs rAget_real_targetrus; 599~z%))B-> " ## LrCcd}|r|D]R}t|jjD]*\}}|jj|t |,Td}t |}|j }|jt|D]-\}}|dk(s|j|r|j|,d}/|ryy)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. TFrN) enumeraterbre set_targetrurqcopyclearr>rh)rjchangedrmitgtcfg orig_blockss rA cleanup_cfgrsG  EE#E$4$4$<$<$>? E3  ++As/CD E E fokkm  !+. HAuAv% e$   rCTceZdZddZddZy)AnalysisResultc ||_||_yr<beforeafter)r@rrs rArBzAnalysisResult.__init__s  rCc<d|jd|jdS)Nzbefore: z after:  r)r@s rArLzAnalysisResult.__str__s$++i |2>>rCN)rAnalysisDict[T]rrrNrOrP)rRrSrTrBrLrVrCrArrs ?rCrcLeZdZd%dZed&dZed'dZed(dZed)dZd*dZ d+dZ d,dZ d-d Z d.d Z d/d Zd0d Zd1d Zd2dZd3dZd4dZd5dZd6dZd7dZd8dZd9dZd:dZd;dZddZd?dZd@dZdAdZ dBdZ!dCdZ"dDd Z#dEd!Z$dFd"Z%dGd#Z&y$)HBaseAnalysisVisitorc*ttfSr<r_r@r\s rA visit_gotozBaseAnalysisVisitor.visit_gotouce|rCctr<NotImplementedErrorrs rAvisit_register_opz%BaseAnalysisVisitor.visit_register_op!!rCctr<rrs rA visit_assignz BaseAnalysisVisitor.visit_assignrrCctr<rrs rAvisit_assign_multiz&BaseAnalysisVisitor.visit_assign_multirrCctr<rrs rA visit_set_memz!BaseAnalysisVisitor.visit_set_memrrCc$|j|Sr<rrs rA visit_callzBaseAnalysisVisitor.visit_call%%b))rCc$|j|Sr<rrs rAvisit_method_callz%BaseAnalysisVisitor.visit_method_callrrCc$|j|Sr<rrs rAvisit_load_error_valuez*BaseAnalysisVisitor.visit_load_error_valuerrCc$|j|Sr<rrs rAvisit_load_literalz&BaseAnalysisVisitor.visit_load_literalrrCc$|j|Sr<rrs rAvisit_get_attrz"BaseAnalysisVisitor.visit_get_attrrrCc$|j|Sr<rrs rAvisit_set_attrz"BaseAnalysisVisitor.visit_set_attrrrCc$|j|Sr<rrs rAvisit_load_staticz%BaseAnalysisVisitor.visit_load_staticrrCc$|j|Sr<rrs rAvisit_init_staticz%BaseAnalysisVisitor.visit_init_staticrrCc$|j|Sr<rrs rAvisit_tuple_getz#BaseAnalysisVisitor.visit_tuple_getrrCc$|j|Sr<rrs rAvisit_tuple_setz#BaseAnalysisVisitor.visit_tuple_setrrCc$|j|Sr<rrs rA visit_boxzBaseAnalysisVisitor.visit_boxrrCc$|j|Sr<rrs rA visit_unboxzBaseAnalysisVisitor.visit_unboxrrCc$|j|Sr<rrs rA visit_castzBaseAnalysisVisitor.visit_castrrCc$|j|Sr<rrs rAvisit_raise_standard_errorz.BaseAnalysisVisitor.visit_raise_standard_errorrrCc$|j|Sr<rrs rA visit_call_cz BaseAnalysisVisitor.visit_call_crrCc$|j|Sr<rrs rAvisit_primitive_opz&BaseAnalysisVisitor.visit_primitive_oprrCc$|j|Sr<rrs rAvisit_truncatez"BaseAnalysisVisitor.visit_truncaterrCc$|j|Sr<rrs rA visit_extendz BaseAnalysisVisitor.visit_extendrrCc$|j|Sr<rrs rAvisit_load_globalz%BaseAnalysisVisitor.visit_load_globalrrCc$|j|Sr<rrs rA visit_int_opz BaseAnalysisVisitor.visit_int_oprrCc$|j|Sr<rrs rAvisit_float_opz"BaseAnalysisVisitor.visit_float_oprrCc$|j|Sr<rrs rAvisit_float_negz#BaseAnalysisVisitor.visit_float_negrrCc$|j|Sr<rrs rAvisit_comparison_opz'BaseAnalysisVisitor.visit_comparison_op rrCc$|j|Sr<rrs rAvisit_float_comparison_opz-BaseAnalysisVisitor.visit_float_comparison_op rrCc$|j|Sr<rrs rAvisit_load_memz"BaseAnalysisVisitor.visit_load_memrrCc$|j|Sr<rrs rAvisit_get_element_ptrz)BaseAnalysisVisitor.visit_get_element_ptrrrCc$|j|Sr<rrs rAvisit_set_elementz%BaseAnalysisVisitor.visit_set_elementrrCc$|j|Sr<rrs rAvisit_load_addressz&BaseAnalysisVisitor.visit_load_addressrrCc$|j|Sr<rrs rAvisit_keep_alivez$BaseAnalysisVisitor.visit_keep_aliverrCc$|j|Sr<rrs rAvisit_unborrowz"BaseAnalysisVisitor.visit_unborrowrrCN)r\rrN GenAndKill[T])r\r,rNr)r\r rNr)r\r rNr)r\r0rNr)r\rrNr)r\r'rNr)r\r"rNr)r\r$rNr)r\rrNr)r\r.rNr)r\r&rNr)r\rrNr)r\r2rNr)r\r3rNr)r\r rNr)r\r5rNr)r\rrNr)r\r+rNr)r\rrNr)r\r*rNr)r\r1rNr)r\rrNr)r\r#rNr)r\rrNr)r\rrNr)r\rrNr)r\rrNr)r\rrNr)r\r%rNr)r\rrNr)r\r/rNr)r\r!rNr)r\r rNr)r\r4rNr)'rRrSrTrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrVrCrArrs""""""""******************************rCrcReZdZdZd d dZd dZddZddZddZddZ ddZ dd Z y )DefinedVisitoraVisitor 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. c||_yr< strict_errors)r@rs rArBzDefinedVisitor.__init__2s *rCc*ttfSr<rrs rA visit_branchzDefinedVisitor.visit_branch5rrCc*ttfSr<rrs rA visit_returnzDefinedVisitor.visit_return8rrCc*ttfSr<rrs rAvisit_unreachablez DefinedVisitor.visit_unreachable;rrCc*ttfSr<rrs rArz DefinedVisitor.visit_register_op>rrCct|jtr9|jjs |jrt |j hfS|j ht fSr<)rZsrcr" undefinesrr_destrs rArzDefinedVisitor.visit_assignAsJ bffn -2663C3CtGYGY5277)# #GG9ce# #rCc*ttfSr<rrs rArz!DefinedVisitor.visit_assign_multiHsuce|rCc*ttfSr<rrs rArzDefinedVisitor.visit_set_memLrrCNF)rboolrNrOr\r rNGenAndKill[Value]r\r-rNrr\r7rNrr\r,rNrr\r rNrr\r rNrr\r0rNr) rRrSrTrUrBrrrrrrrrVrCrArr"s/ +$rCrc<t||t|dtS)zCalculate potentially defined registers at each CFG location. A register is defined if it has a value along some path from the initial location. Frjr~ gen_and_killinitialbackwardkind) run_analysisrMAYBE_ANALYSIS)rjr~initial_defineds rAanalyze_maybe_defined_regsrPs&  #%   rCc Tt||t||dtt|S)aICalculate 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. rFrjr~rrrruniverse)rr MUST_ANALYSISr_)rjr~rregsrs rAanalyze_must_defined_regsras/  #-@ T rCcLeZdZd dZd dZd dZd dZddZddZddZ ddZ y )BorrowedArgumentsVisitorc||_yr<)args)r@r s rArBz!BorrowedArgumentsVisitor.__init__}s  rCc*ttfSr<rrs rArz%BorrowedArgumentsVisitor.visit_branchrrCc*ttfSr<rrs rArz%BorrowedArgumentsVisitor.visit_returnrrCc*ttfSr<rrs rArz*BorrowedArgumentsVisitor.visit_unreachablerrCc*ttfSr<rrs rArz*BorrowedArgumentsVisitor.visit_register_oprrCc|j|jvrt|jhfSttfSr<)rr r_rs rArz%BorrowedArgumentsVisitor.visit_assigns3 77dii 5277)# #uce|rCc*ttfSr<rrs rArz+BorrowedArgumentsVisitor.visit_assign_multirrCc*ttfSr<rrs rArz&BorrowedArgumentsVisitor.visit_set_memrrCN)r  set[Value]rNrOrrrrrrr) rRrSrTrBrrrrrrrrVrCrAr r |s* rCr c @t||t||dt|S)zCalculate arguments that can use references borrowed from the caller. When assigning to an argument, it no longer is borrowed. Fr)rr r)rjr~borroweds rAanalyze_borrowed_argumentsrs+  -h7  rCcDeZdZd dZd dZd dZd dZd dZddZddZ y)UndefinedVisitorc*ttfSr<rrs rArzUndefinedVisitor.visit_branchrrCc*ttfSr<rrs rArzUndefinedVisitor.visit_returnrrCc*ttfSr<rrs rArz"UndefinedVisitor.visit_unreachablerrCcJt|js|hfStfSr<)r_is_voidrs rArz"UndefinedVisitor.visit_register_ops!u"**rd77#%77rCc0t|jhfSr<r_rrs rArzUndefinedVisitor.visit_assignurwwirCc0t|jhfSr<rrs rArz#UndefinedVisitor.visit_assign_multir rCc*ttfSr<rrs rArzUndefinedVisitor.visit_set_memrrCNrrrrrrr) rRrSrTrrrrrrrrVrCrArrs%8  rCrct}|jD]/}t|ttt fr|j |1|Sr<)r_sourcesrZrrr6rf)r\resultsources rAnon_trivial_sourcesr'sB UF**,&7E5"9: JJv  MrCcTeZdZd dZd dZd dZddZddZddZddZ ddZ dd Z y )LivenessVisitorc,t|tfSr<r'r_rs rArzLivenessVisitor.visit_branch"2&--rCct|jttfs|jht fSt t fSr<)rZvaluerrr_rs rArzLivenessVisitor.visit_returns6"((We$45HH:su$ $5#%< rCc*ttfSr<rrs rArz!LivenessVisitor.visit_unreachablerrCcRt|}|js||hfS|tfSr<)r'rr_)r@r\gens rArz!LivenessVisitor.visit_register_ops+!"%zz9 : rCc2t||jhfSr<r'rrs rArzLivenessVisitor.visit_assign"2& 11rCc2t||jhfSr<r3rs rArz"LivenessVisitor.visit_assign_multir4rCc,t|tfSr<r+rs rArzLivenessVisitor.visit_set_memr,rCc*ttfSr<rrs rA visit_inc_refzLivenessVisitor.visit_inc_refrrCc*ttfSr<rrs rA visit_dec_refzLivenessVisitor.visit_dec_refrrCNrrrrrrr)r\rrNr)r\rrNr) rRrSrTrrrrrrrr8r:rVrCrAr)r)s/. 22.rCr)cLt||ttdtS)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)rr)r_r)rjr~s rAanalyze_live_regsr<s(  $&   rCrsNci}i}|D]m} t} t} | j} |rtt| } | D]&} | j |\}}| |z |z} | |z |z} (| || <| || <ot|}|s|j t|}i}i}|D]K} |t k(rt|| <t|| <'|Jdt||| <t||| <M|r|j}|j}n|j}|j}|r|j}|j|||r;d}||D]-}|t||}|t k(r |||z}&|||z}/| Jt|}|||<|||z ||z}|||k7r1||D])}||vs|j||j|+|||<|ri}i}|D]h} | }||}t| j}|rtt|}|D]/\}} ||||f<| j |\}}||z |z}||||f<1j|r||}}t||S)aPRun 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) Nz,Universe must be defined for a must analysis)r_rardreversedacceptreverserr=r>popremoverhrfrwr) rjr~rrrrr block_gen block_killrmr1killrar\opgenopkillworklistworksetrrrlrkrG new_beforer> new_afterr= op_beforeop_aftercurops_enumidxs rArrs4IJ !euii x}%C +BIIl3ME6<5(C5LF*D + % 5 !F|H (mG')F&(E) > !EF5M5E%L' W)W W'MF5Mx=E%L)88888888  u E?(,J  .%!$U4[!1J^+%+-J%+-J  .) ))WJ"u *U"33y7GG e $  &w&OOD)KK% &!e - 279I57H 'Um-6uyy-A X/H 'GC$'IeSj !IIl3ME6<5(C#&HUCZ  ' '') )X ..rC)rjlist[BasicBlock]rWrrNr:)rGr rNr )rjrQrNrO)rjrQr~r:rrrNAnalysisResult[Value]r) rjrQr~r:rrrzIterable[Value]rrrNrR)rjrQr~r:rrrNrR)r\r(rNr)rjrQr~r:rNrRr<)rjrQr~r:rzOpVisitor[GenAndKill[T]]rzset[T]rrFrrrz set[T] | NonerNzAnalysisResult[T])UrU __future__rabcrcollections.abcrrtypingrr mypyc.ir.opsr r r r r rrrrrrrrrrrrrrrrrrr r!r"r#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r5r6r7r8r:rqrurrdicttuplerFr_ AnalysisDictr GenAndKillrrrrr rrr'r)r<rrrrVrCrAr\s*".#1111111111111hGG.=B**Z 6 CLE*c/*CF23 ?WQZ?3q63q6> " l*)JqM2l*^+(/+\ #&9C,          62598 #&2<$*51.!)%0!H " #l/ l/ l/+l/ l/  l/  l/l/l/rC