~L isdZddlZddlZddlZddlZddlZddlmZddlmZddl m Z m Z m Z m Z mZddlZddlmZddlmZmZmZdd lmZmZmZmZmZmZmZmZm Z m!Z!dd l"m#Z#m$Z$dd l%m&Z&m'Z'm(Z(m)Z)dd lm*Z*m+Z+dd l,m-Z-m.Z.ddl/m0Z0m1Z1ddl2m3Z3ddl4m5Z5m6Z6m7Z7m8Z8ddl9m:Z:e r ddl;mZ>ej~GddZ@GddZAy)a This module provides utilities for generating Python bytecode in PyTorch's Dynamo system. It includes functionality for: - Constructing bytecode sequences for Python operations - Managing stack operations and variable tracking - Handling graph outputs and their conversions - Supporting different Python versions (3.11+, 3.12+, 3.13+) - Converting high-level operations to low-level bytecode instructions - Managing constant loading and attribute access - Supporting function creation and closure handling N)Counter)Iterable)AnyCallableOptional TYPE_CHECKINGUnion) OrderedSet)configgraph_break_hintsutils) add_push_nulladd_push_null_call_function_excreate_call_functioncreate_call_methodcreate_dup_topcreate_instructioncreate_load_constcreate_load_method create_rot_n Instruction)IncorrectUsageunimplemented_v2) AttrSource ChainedSourceDictGetItemSourceSource)is_safe_constant rot_n_helper)ValueMutationExistingVariableTracker)4ContextlibContextManagerLocalGeneratorObjectVariableLocalGeneratorObjectVariable)NNModuleVariable)NumpyNdarrayVariableSymNodeVariableTensorVariableUnspecializedPythonVariable)TensorWithTFOverrideVariable)GraphArg)InstructionTranslatorBasec"eZdZUeed<eed<y)GraphOutputEntryindexvariableN)__name__ __module__ __qualname__int__annotations__r"[/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/torch/_dynamo/codegen.pyr.r.>s Jr7r.c6eZdZdZ dTdddeej jdeedee e e e fe fdee e e fd df d Zd d d ee ded dfdZd ee fdZde e e dfd dfdZ dUdegdfded dfdZ dVde e e fded dfdZde d efdZded dfdZde e e fd dfdZdee e e fd dfdZd efdZd ede d eefd!ZdWd"Z d#ed dfd$Z!d%eed dfd&Z"d eefd'Z#d ed efd(Z$d ed efd)Z%d ed efd*Z&d ed efd+Z'd ed efd,Z(dUd ed-ed efd.Z)de d efd/Z*de d efd0Z+d ed dfd1Z,d2ed dfd3Z-d ed efd4Z.d ed dfd5Z/d6ed eefd7Z0d ed efd8Z1d ed dfd9Z2 dXd:ed;eded eefd?Z4dWd@Z5d2ed;ed dfdAZ6dWdBZ7dCed dfdDZ8dCed dfdEZ9 dXddd:edFe:jvd;eddJe d dfdKZ?d:ed dfdLZ@dMed efdNZAdMedOed dfdPZBd2edQeed;ed eefdRZCdeDd efdSZEy)Y PyCodegenz< Helper class uses for constructing Python bytecode Ntxr,rootgraph_output_vartempvarsoverridden_sourcesreturnc||_d|_tj|_i|_g|_|xsi|_||_||_ |jjj|_ |jj|_ |jjj|_ d|_|xsi|_y)NT)r< top_of_stack collectionsruses graph_outputs_outputr>r;r=output code_optionscell_and_freevarsnew_varvalue_from_sourcer?)selfr;r<r=r>r?s r8__init__zPyCodegen.__init__Is FJ=H=P=P=R :<*, DL>r  0 GGNN77!%!:!:ww~~-- '+9K8Pbr7T)rK stack_valuesrKc|j}|xj|zc_ |j|||_y#||_wxYwN)rKforeach)rLrNrKprevs r8 restore_stackzPyCodegen.restore_stackfsC%% "33 * LL &%)D "TD "s < Acp|jjDcgc]}|jc}Scc}wrP)rEvaluesr0)rLxs r8graph_output_varszPyCodegen.graph_output_varsps)$($6$6$=$=$?@q @@@s3valuer+c>|j|}| Jd|y)Nzreconstruct!=None ) reconstruct)rLrXress r8call_reconstructzPyCodegen.call_reconstructss+%{8088{r7gen_fncall_function_exct|j}tjdkr|j ||j|d}|j|d=|r%|jj t |n$|jj t|tjdk\r|j yy)a `gen_fn` generates instructions via PyCodegen methods that push a single callable to the stack. `add_push_null` pushes a NULL to the stack before or after the instructions generated by `gen_fn`, depending on Python version. Will attempt to use the NULL push bit for instructions with such bits (LOAD_GLOBAL 3.11+, LOAD_ATTR 3.12+, LOAD_SUPER_ATTR).  N)lenrFsys version_info clear_tosextendrr)rLr]r^old_len added_instss r8rzPyCodegen.add_push_nullysdll#   g % NN ll78, LL "  LL   >{ K L LL   k : ;   w & NN  'r7 allow_cachec & t|tr&jj||}|dusJdj|ur$j j tyjj|?j j jj||_yj|xxdz cc< j||jvr4j j tj%||_yt|t&sJj j(|rxj|ur j tyjj|5 j jj||_y|j+rt|t,r t/d |j0Z|rX|j+rt|t2s8t|j4t6s j8r|j0S|j;rOt=|j?r6 j jA|j?|_yt|tBrjE|jGfd jIjJ j jM|jOjPd  jStUd d|_yt|tVr|jYtZk(rjPj\svjE|j_jPt`jbd fd }jG| jStUdd|_yt|tdtVtfthfrjE|t|thrUjGfdjIjJ jStUdd|_yt|tfrI|jjr=d fd }jG| jStUdd|_yjIjJ|_yt|tlr|jnjqd}|djrdvr) j j|d|dd}n8jtJ j jwjt|D]"} j jy|$|_yj|xxdz cc< j||rB|jvr4j j tj%||_y#t$r<tdt|dt|d|dgt j" YwxYw#t$r2tdt|d|ddgt jzd YwxYw)a  Generate code such that top-of-stack (TOS) is set to value. `allow_cache` controls the behavior in the following manner. `value` can either be a VariableTracker or a Source. If `value` is a `Source`, `allow_cache` must be True (invariant asserted below). If the source was reconstructed earlier, we will reuse the generated code by loading from top of stack or tempvars. If `value` is a `VariableTracker`, we have the following cases: 1) `allow_cache=True` a) If the value.source is not None, we will emit the code based on `value.source` to handle aliasing. b) If value.source is None (example reconstructing a local list returned by the compiled function), we will reconstruct the variable tracker (w/o any source) to emit bytecode that generates a new python object. In both cases of value.source being None or not, if the value was reconstructed earlier, we will reuse the generated code by loading from top of stack or tempvars. 2) `allow_cache=False` - This is a special case (allow_cache defaults to True). a) If the value.source is not None, we reconstruct the variable tracker and emit a new python object. You might wonder what about aliasing? The place where we use this config also has the followup code where the original python object is assigned to this new python value to handle aliasing (check side_effects.py and search for allow_cache=False). b) If value.source is None, this is not allowed. TODO - assert this. Notable effects: 1. `self.top_of_stack` will be set to `value`, if we don't codegen `value` based on source. 2. `self.uses[value]` will increment, unless (a). we codegen via `top_of_stack` or cached `tempvars`, or (b). `value` has special VT types like `NNModuleVariable`, etc. Tz#allow_cache must be True for SourceNr z:Reconstruction failure: source.reconstruct not implementedz6Dynamo has no bytecode reconstruction implemented for z variable .)gb_typecontext explanationhintszENYI: Returning a @contextmanager object from a torch.compile functioncDjtjdS)N to_subclassload_import_fromrr1rLsr8z$PyCodegen.__call__..s--ennmLr7addFcjjjjdyNitemload_graph_outputr/appendcreate_load_attrrEgraph_outputs_keyrGrLsr8r]z"PyCodegen.__call__..gen_fn5s4&&}5F'G'M'MN d33F;.HsD11%..BSTr7cjjjjdyr{r}rsr8r]z"PyCodegen.__call__..gen_fnNs4**=9J+K+Q+QRMM$"7"7"?@r7 co_varnameszReconstruction failurezJDynamo has no bytecode reconstruction implemented for sourceless variable zIf Dynamo is attempting to trace a return statement and your code is attempting to return a variable that Dynamo cannot reconstruct, then remove it from the return statement.zReport an issue to PyTorch if you need reconstrtuction support. Note that objects that don't have reconstruction rules may be fundamentally unreconstructable.r@N)> isinstancerr?getrBrFrrr> create_loadrDr\NotImplementedErrorrstrtyper DYNAMO_BUG add_cacher"rE is_realizedr#rsourcer$ mutation_typer!rKis_python_constantras_python_constantrr*add_graph_outputrr~r/create_load_globalglobal_mangled_class_namer;rgrr' python_typefloatexport as_tensortorchfloat64r(r)r& need_unwrapr% module_keysplitrHr<create_load_const_uncheckedrCAUSED_BY_EARLIER_GRAPH_BREAK) rLrXrjrr]partspartrErrGs ` @@@r8__call__zPyCodegen.__call__sKZ eV $,,00>F$& M(M M&  E) ##N$45}}  (4 ##D$4$4T]]65J$KL$*! IIf  "  %%f-& ##N$45v& &D  %111**   E) n./}}  '3 d..t}}U/CDE$)!    : G$ !W  LL $!!# 5:V(W(5..0EF))ELL))  # # %*:5;S;S;U*V MM$001I1I1KL M|"{; < $ 5 5e <    L   " "=1B#C#I#I J MM''33DGG<$(  MM.q%8 9b"_ uo .!!#u,GGNN!% 5 57!  = =   v & MM.q%8 9v"u +$   !% 5 5e < %!56""T&&}5F'G'M'MN 21e<=T"SE#>?EDUDUAA""6* 21e<=D"A&&}5F'G'M'MN@"?/ 0$$**3/EQx4,,];; d..uQx89ab yy,,, d>>tyyIJ ; d33D9: ;.") IIe  !  %%e,u 5 ##N$45u%!A'  XK"XY]^dYeXffpqwpxxy z9-889  ^'  4J"lmrlsst ud+HHW   s%!Z 0[ A[[8\\ct|j}||jvr,tt |j||j|<|SrP)idas_proxyrEr.rc)rLrXrs r8rzPyCodegen.add_graph_outputwsPu~~/0 D$6$6 64DD&&'5D  0 1! r7r/c |j}|jJ|j|j|j|j|j ||j|j yrP)rFr=rrrcreate_binary_subscr)rLr/rGs r8r~zPyCodegen.load_graph_outputsf$$000 d&&t'<'<=> d,,U34 d//12r7c|j}||j|<|jj|j |yrP)rJr>rFr create_store)rLrXvars r8rzPyCodegen.add_caches8lln" e D--c23r7itemsc"|D] }|| yrPr6)rLris r8rQzPyCodegen.foreachs A G r7ctdS)N BINARY_SUBSCRrrus r8rzPyCodegen.create_binary_subscrs !/22r7namectjdd|}|jj}||vrt ||t |k(sJ|||<|j |dgS)zStore value in a new globalz[^a-zA-Z0-9_]+_Trw)resubr; f_globalsrr)rLrrXrs r8setup_globally_cachedzPyCodegen.setup_globally_cachedsivv'd3GG%% 9 io&"U)3 33#IdO''$'788r7cd|_yrP)rBrus r8rfzPyCodegen.clear_toss  r7instc~t|tsJ|jj||j yrP)rrrFrrf)rLrs r8 append_outputzPyCodegen.append_outputs.$ ,,, D! r7instsctd|DsJ|jj||jy)Nc3<K|]}t|tywrP)rr).0rVs r8 z*PyCodegen.extend_output..s=!:a-=s)allrFrgrf)rLrs r8 extend_outputzPyCodegen.extend_outputs2=u==== E" r7c|jSrP)rFrus r8get_instructionszPyCodegen.get_instructionss ||r7cR||jdvs J|dtd|S)Nr missing LOAD_FASTargvalrHrrLrs r8rzPyCodegen.create_loads4t((77JD69JJ7!+d;;r7cr||jvsJtjdk\rdnd}t||S)Nr`r LOAD_CLOSUREr)rIrdrer)rLr inst_names r8create_load_closurezPyCodegen.create_load_closures:t--////##3w#>KN !)D99r7cD||jvsJtd|S)N LOAD_DEREFrrIrrs r8create_load_derefzPyCodegen.create_load_derefs&t--////!,t<N6OO4!-==r7ct|SrPrrLrXs r8rzPyCodegen.create_load_consts  ''r7ct|dS)NF)checkedrrs r8rz%PyCodegen.create_load_const_uncheckeds 66r7c|jjj||jt |yrP)r;rGrrrrs r8 load_methodzPyCodegen.load_methods, &&t, -d34r7nargsc8|jt|yrP)rr)rLrs r8 call_methodzPyCodegen.call_methods -e45r7cn||jdvr|jdxx|fz cc<td|S)Nr LOAD_ATTRrrrs r8rzPyCodegen.create_load_attrs: t((4 4   j )dW 4 )!+d;;r7cD|j|j|yrP)rrrs r8 load_attrzPyCodegen.load_attrs 40067r7namesch|jdDcgc]}|j|c}Scc}w)Nrl)rr)rLrrs r8create_load_attrszPyCodegen.create_load_attrss*8= C8HI%%d+IIIs/cn||jdvr|jdxx|fz cc<td|S)Nr STORE_ATTRrrrs r8create_store_attrzPyCodegen.create_store_attrs: t((4 4   j )dW 4 )!,t<ZZ q 01   r7nc t|S#t$rOtd||jt |gtdtddtd|cYSwxYw)N BUILD_TUPLEargryCALL_FUNCTION_EXrUNPACK_SEQUENCE)rAttributeErrorrrr )rLrs r8rzPyCodegen.rot_nsz ? " #=a800aAa##51=  ##4!<   s AA%$A%c8|jtdy)NPOP_TOP)rrrus r8pop_topzPyCodegen.pop_top s -i89r7c<|jt||y)N)r)rr)rLrrs r8 call_functionzPyCodegen.call_functions /KLr7c6|jtyrP)rrrus r8dup_topzPyCodegen.dup_tops >+,r7varnamecD|j|j|yrP)rrrLr s r8storezPyCodegen.stores 4,,W56r7cD|j|j|yrP)rrrs r8 load_derefzPyCodegen.load_derefs 411':;r7codecjsJjdfd }|rktjdk\rXj |j j |dzj j |dzn*|j j |dzjy)NcjD]|}jur5|jvsJjj |F|jvsJj sJj |~jt dtjjtjdkr jjtjdk\r(jt dt ddgyjt ddy)Nrrrr` MAKE_FUNCTIONSET_FUNCTION_ATTRIBUTE) rfr;rIrrpost_prune_cell_and_freevarsrrcrrdrerg)rrrfreevarsrGrLr;s r8r]z4PyCodegen.make_function_with_closure..gen_fn&s. NN    ?=$"8"8"::::MM$":":3"?@""6"6"8888::::88=> ? MM,]H N O MM$006 7') d44W=>7* *?;*+CN 0dKLr7rryr r) co_freevarsrFrdrerrgrrf) rLr;rrrrr]rrGs ```` @@r8make_function_with_closurez$PyCodegen.make_function_with_closures##x M M8 ))W4   v & MM$**\A%56 7 MM$**\A%56 7 H MM$**\A%56 7 r7modcR|jj}|j}tjdd|j }|j |d|ur|j|dSd|}|jjj||}|j|dS)zT Generate a LOAD_GLOBAL instruction to fetch a given python module. z^.*[.]NTrw ___module_) r;rG global_scoperrr1rrinstall_global_by_id)rLrrGr!rprefix global_names r8create_load_python_modulez#PyCodegen.create_load_python_moduleKs** vviS\\2   D$ '3 .**4T*: :dV$ggnn99&#F &&{&==r7rc@||jvrd|j|<yy)zM Mark a source as a temp variable, so that it can be reused. N)r>)rLrs r8mark_source_tempzPyCodegen.mark_source_tempXs#  &$(DMM& ! 'r7cjj|djjj}t dt ddffd |D]!}|j|j#d}tjrPjfdjtddj}j||D]`}|jrAjfd j|jtd dPj|btjrdjfd |Jjj!|gjtd dj#jtt%|dy) z2Call the generated code function stored in fn_nameTrr@Nc|vrj|yj|t|tr|jt|t r.t|j tr|j yyyrP)r'rxrrbaserr/r)rcollect_temp_source seen_sourcesrLs r8r+z?PyCodegen.make_call_generated_code..collect_temp_sourcegss%%%f-   V $&-0#FKK0&"34 f:$FLL1:4r7cDjtjdS)Nrecord_pregraph_bytecode_enterrsrusr8rvz4PyCodegen.make_call_generated_code..s--NN$Dr7rFcnjjtjdgS)N_as_tensor_fullprec)rr%rrrusr8rvz4PyCodegen.make_call_generated_code..s4D.. ::5A 112GHr7r cDjtjdS)Nrecord_pregraph_bytecode_exitrsrusr8rvz4PyCodegen.make_call_generated_code..s--NN$Cr7)rrr;rG graphargsr rrr record_runtime_overheadrrrJrpass_arg_as_tensorr\rrrc)rLrr3rcm_varr+r,s` @@r8make_call_generated_codez"PyCodegen.make_call_generated_code_s 4227DABGGNN,, +5<  2 24 2* 0Czz%#CJJ/ 0  ) )       3Au= >\\^F JJv  +C%%""%%c*""#75#AB%%c* +  ) )     % %%    0 0 89 :   3Au= > LLN /IFGr7 module_namectd|S)N IMPORT_NAMErr)rLr8s r8create_import_namezPyCodegen.create_import_names!- DDr7 object_namect|jj||}|j|||yrP)rr; import_sourcer')rLr8r<rs r8rtzPyCodegen.load_import_froms4DGG11+> L f% V r7kw_namesctjdk\rSt||}|djdk(sJ|j d|j |t d||d<|Stjdk\r]t||}tjdk\rd}d}nd}d }||j|k(sJt d | }|j |||S|j |t d |gS) Nr`CALLCALL_KWrr)ra PRECALLKW_NAMESrCALL_FUNCTION_KW)rdreropnameinsertrr)rLrr?rrGidx expected_inst kw_names_insts r8create_call_function_kwz!PyCodegen.create_call_function_kws   w &)%;F":$$. .. MM"d44X> ?+I5AF2JM    ()%;F7* &  ) #;%%6 66.z(KM MM#} -M  " "8 , 1u =  r7ctd|S)N DELETE_FASTrrrs r8 create_deletezPyCodegen.create_deletes!->>r7)NNNN)F)Tr)r)Fr1r2r3__doc__rrnnModulerdictr r"rrrMlistboolrSrWr\rrrr4rr~rrrQrrrrfrrrrrrrrrrrrrrrrrrrrrr r rrtypesCodeTyper ModuleTyper%r'r7r;rtrNobjectrQr6r7r8r:r:Ds+/*.HL=A Q 'Quxx'Q#3- Q 4ov&= > CDE Q %T&&.%9: Q Q<EI* I*=A* *A4#8A9?FJ>?9 9DIr4x(<@ @JN]"?F23]"BF]" ]"~!o!#!3s3t34u_f%<=4$4 XeOV,C&DE$3k39#9c9d;>O9!+$ 4 #4 ${"3<< <:: : =c=k====>s>{>>s>>+> (s({(777555666 k . s tK0 :M3M4MDM-7S7T7<#<$< / '//nn /  /  / /b >U-=-= >+ >)v)$)HHHHHHTEcEkECcd  $,SM >B k  4?6?k?r7r:)BrRrC dataclassesrrdrXrcollections.abcrtypingrrrrr torch.nnrtorch.utils._ordered_setr rr r rbytecode_transformationrrrrrrrrrrexcrrrrrrrrr variables.baser!r"variables.functionsr#r$variables.nn_moduler%variables.tensorr&r'r(r)variables.torch_functionr*torch._dynamo.variables.builderr+symbolic_convertr, dataclassr.r:r6r7r8rks  $@@/..   2HH1B2 C8;  L ?L ?r7