o
    Zhl                    @   s6  d dl Z d dlZd dlZd dl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 dlmZ d dlmZmZmZmZmZ d dlZd dlm  mZ d dlm  m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'm(Z(m)Z) d dl*m+Z+ d dl,m-Z-m.Z.m/Z/ d dlm0Z0m1Z1 ddl2m3Z3 e4e5Z6g dZ7G dd deZ8da9edd Z:	dkdeej;ej<ej=j>f dej=j>de?de8de@f
ddZAG dd dZBG dd  d eBej=j>ZCG d!d" d"eBej=j>ZDG d#d$ d$e jEZFG d%d& d&ej=j>ZG	dld'e"d(eeF d)eGfd*d+ZHd,ejjId-e#d)dfd.d/ZJd0d1 ZKd2e?d3e?d)e?fd4d5ZLd6ej=j>d7ej=j>fd8d9ZMd:ej=j>d)e?fd;d<ZNd:ejjOd)ejjPfd=d>ZQd:eejjOeCeGf d)ejjPfd?d@ZRd:eejjOeCeGf d)ejjPfdAdBZSdCej=j>de?fdDdEZT	dldCej=j>de?dFej=j>dGeee?gej=j>f  fdHdIZUdJe?dKeVd)e?fdLdMZWdNe?dJe?d)e@fdOdPZXG dQdR dRZYeG dSdT dTZZdUejjIdVeGfdWdXZ[	YdmdZej=j>d[e\e?eVf d\e?fd]d^Z]G d_d` d`Z^d:ejjOdVeGdae\e?e_e? f fdbdcZ`ddde Za	dld'ej=j>dfe\e?ebe? f dgebe? dhee\eVe_e? f  fdidjZcdS )n    N)defaultdict)contextmanager)deepcopy)	dataclass)Enum)AnyCallablecastOptionalUnion)FakeScriptObject)reorder_kwargs)	ConstantArgumentExportedProgramExportGraphSignature	InputKindModuleCallSignatureSymBoolArgumentSymFloatArgumentSymIntArgumentTensorArgument)is_fx_tracing)	_get_attr_get_attr_via_attr_list_print_readable)
GetAttrKeySequenceKey   )_remove_effect_tokens)FlatArgsAdapterInterpreterModuleInterpreterModuleDispatcherUnflattenedModule	unflattenc                   @   s   e Zd ZdZdZdZdZdS )	_AttrKindZ	parameterbufferconstantmoduleN)__name__
__module____qualname__	PARAMETERBUFFERCONSTANTMODULE r/   r/   E/var/www/auris/lib/python3.10/site-packages/torch/export/unflatten.pyr$   1   s
    r$   Tc                  c   s"    t } da zd V  W | a d S | a w )NF)RUN_WITH_INTERPRETER)Zold_flagr/   r/   r0   _disable_interpreter;   s   r2   from_obj	to_moduletarget	attr_kind
persistentc           	         s:  | d^ }}|h}|D ]) t }|D ]}t| s$t| tj  | fdd|j	 D  q|}q|D ]a}|t
jkrPt| tjjsIJ |||  q9|t
jkrft| tjs]J |j|| |d q9|t
jkrt| trtJ dt| tjtjfsJ t|||  q9|t
jkrt| tjjsJ t|||  q9d S )N.c                 3   s"    | ]\}}t | r|V  qd S N)_is_call_name).0kZt_callitemr/   r0   	<genexpr>\   s    
z_assign_attr.<locals>.<genexpr>)r7   z2FakeScriptObject should only exist during tracing.)splitsethasattrsetattrtorchnnModuleupdate_modulesitemsr$   r+   
isinstance	ParameterZregister_parameterr,   TensorZregister_bufferr-   r   ScriptObjectr.   )	r3   r4   r5   r6   r7   prefixfieldZ
to_modulestsr/   r=   r0   _assign_attrH   sH   





rQ   c                   @   s,   e Zd ZU ee ed< dee fddZdS )_SubmoduleBase_tyreturnc                 C      | j S r9   )rS   selfr/   r/   r0   	type_name~      z_SubmoduleBase.type_nameN)r(   r)   r*   r
   str__annotations__rX   r/   r/   r/   r0   rR   {   s   
 rR   c                       sj   e Zd ZU dZeejj ed< 	ddejj	dee
 f fddZdd	 Zd
d Z				dddZ  ZS )r    zA module that uses torch.fx.Interpreter to execute instead of the usual
    codegen that GraphModule uses. This provides better stack trace information
    and makes it easier to debug execution.
    graph_moduleNgraphtyc                    s(   t    || _|| _| | j_t| _d S r9   )super__init__r]   rS   owning_moduler1   _run_with_interpreter)rW   r]   r^   	__class__r/   r0   r`      s
   

zInterpreterModule.__init__c                    s   | j d us	J dt s#tj s| js#t| j j| g|R i  S  rWt|}| j	t
|d  }| fdd|D  t
|t
 ksHJ t
|t
| j	ksSJ t|}tjj| | jdj|ddiS )Nz&Didn't finalize this InterpreterModulec                 3   s     | ]}| v r | V  qd S r9   r/   )r;   Z
kwarg_namekwargsr/   r0   r?      s    z,InterpreterModule.forward.<locals>.<genexpr>r]   enable_io_processingF)r\   r   rD   compileris_dynamo_compilingrb   typeforwardlist	arg_nameslenextendtuplefxInterpreterr]   run)rW   argsrf   arg_listZkwarg_namesr/   re   r0   rl      s*   	zInterpreterModule.forwardc                 C   sP   t j| | j| jd< | j  g | _| jjD ]}|jdkr%| j	|j
 qd S )Nr\   placeholder)rD   rr   GraphModuler]   __dict__lintrn   nodesopappendr5   rW   noder/   r/   r0   finalize   s   

zInterpreterModule.finalizeTFc                 C      t | d||||S )Nr    r   rW   print_outputinclude_strideinclude_devicecoloredr/   r/   r0   print_readable      z InterpreterModule.print_readabler9   TFFF)r(   r)   r*   __doc__r
   rD   rr   rx   r[   GraphrZ   r`   rl   r   r   __classcell__r/   r/   rc   r0   r       s    
 #r    c                       sT   e Zd ZdZdee dee f fddZdd Z	dd	 Z
	
			dddZ  ZS )r!   z
    A module that carries a sequence of InterpreterModules corresponding to
    a sequence of calls of that module. Each call to the module dispatches
    to the next InterpreterModule, and wraps back around after the last.
    attrscall_modulesc                    sZ   t    |s	J |d j| _|D ]}t| |t|d | q|d j| _|| _d| _d S Nr   )r_   r`   rH   rC   getattrrS   _call_modules
_num_calls)rW   r   r   accessorrc   r/   r0   r`      s   

z$InterpreterModuleDispatcher.__init__c                 O   sJ   | j | j }| jd t| j  | _z||i |W S  ty$   d| _ w )Nr   r   )r   r   ro   	Exception)rW   ru   rf   call_moduler/   r/   r0   rl      s   z#InterpreterModuleDispatcher.forwardc                 C   rU   r9   )r   rV   r/   r/   r0   r      rY   z(InterpreterModuleDispatcher.call_modulesTFc                    s$    fdd| j D }d|S )Nc                    s   g | ]
}|  qS r/   )r   )r;   modr   r   r   r   r/   r0   
<listcomp>   s    z>InterpreterModuleDispatcher.print_readable.<locals>.<listcomp>
)r   join)rW   r   r   r   r   outputsr/   r   r0   r      s   
	z*InterpreterModuleDispatcher.print_readabler   )r(   r)   r*   r   rA   rZ   rm   r    r`   rl   r   r   r   r/   r/   rc   r0   r!      s    
	r!   c                   @   sP   e Zd ZdZej	d
dejdejdee	 de
eee	f  dee	 f
dd	ZdS )r   zN
    Adapts input arguments with ``input_spec`` to align ``target_spec``.
    Ntarget_spec
input_spec
input_argsmetadatarT   c                 C   s   dS )z=NOTE: This adapter may mutate given ``input_args_with_path``.Nr/   )rW   r   r   r   r   r/   r/   r0   adapt  s   	zFlatArgsAdapter.adaptr9   )r(   r)   r*   r   abcabstractmethodpytreeZTreeSpecrm   r   r
   dictrZ   r   r/   r/   r/   r0   r   
  s    r   c                       sh   e Zd Z	ddedee f fddZdd Zdd	 Zd
d Z	dd Z
dd Z				dddZ  ZS )r"   Nexport_moduleflat_args_adapterc           $         s  t    |jjd urtddd |jD }|d dksJ t|j}t|j| _tj	
 | _| | j_t|j| _|| _|jj| _| | jd< d| _t| _t|| j t | _t|| \}}| j| |  t|j| | |j| _g | _|j}t }i }	| jjD ]-}
||
 }t||	vrtj j!|" |j#d|	t|< t$|	t| | |
t%j&d	 |'|
 qt| jj(}t }i }| jj)D ]9}
|
|v rd}|j*|
 }nd
}||
 }t||vr|" |f|t|< t$|t| d | |
t%j+|d |'|
 q|, D ]_\}
}|
|v s
|
|v rqd}t||v st-|tj j!sd
}|rAt||vr0|d
f|t|< t$|t| d | |
t%j+d
d qt||	vrN||	t|< t$|	t| | |
t%j&d	 qi }|j*, D ],\}}t||vrt-|tj.ry|" }||t|< |t| }t$|| |t%j/d	 qct0t1 t } fdd}t }| jj2D ]}|j3t4j&ks|j3t4j+kr|j5rt6|j7dsJ t-|j8t9sJ |t|j|j8 |j7j:|j8 |'|j8 |'|j8 q|j3t4j+kr|j5r |j3t4j;ks |j3t4j<kr't6|j7ds	J t-|j8t9sJ |t|j*|j8 |j7j:|j8 |'|j8 q|j*, D ]-\}}||vrZt| v sBJ d t| d \}}|t||| |'|j8 q.|j, D ]%\}}||vrt| vrsqa t| d \}}|t||| qai }  D ]} dd | D }!| D ]	\}"}|!||"< qqt=| |g  t>| fdd|D }| ?| dd |D }dd | jj@D | _Ad
| _Bdd tC|D }#| jDddD ]\}
}|
|#vrtE|#|#|
< qtF| |# | jG  d S )Nz%Unflattening on JointExportModule NYIc                 S   s   g | ]}|j qS r/   )fqnr;   entryr/   r/   r0   r   %      z.UnflattenedModule.__init__.<locals>.<listcomp>r    Zunflattened_moduleF)requires_grad)r6   T)r6   r7   c                    s    |  }| ||f d S r9   )r}   )obj_idZ	node_nametarget_name	name_list)
consts_mapr/   r0   add_to_consts_map  s   z5UnflattenedModule.__init__.<locals>.add_to_consts_mapnamez?Constants should be either aliased or appear in graph signaturec                 S      g | ]}|d  qS r   r/   )r;   tr/   r/   r0   r         c                    s   g | ]}| vr|qS r/   r/   r;   r   )redirected_call_indicesr/   r0   r         c                 S   s   g | ]}d |vr|qS )@r/   r   r/   r/   r0   r     r   c                 S   s   g | ]	}|j d kr|qS rw   r|   r;   r   r/   r/   r0   r     s    c                 S      i | ]\}}||qS r/   r/   )r;   ir   r/   r/   r0   
<dictcomp>      z.UnflattenedModule.__init__.<locals>.<dictcomp>Zremove_duplicate)Hr_   r`   graph_signatureZbackward_signature
ValueErrormodule_call_graphr   r]   rD   rr   r   ra   r   r\   metaadaptedr1   rb   _inplace_buffer_mutations_IValsivals_outline_submodulescreatevalues_copy_graph_attrsZ_graph_modulerange_constraintsZequality_constraints
state_dictrA   
parametersidrE   rK   cloner   rQ   r$   r+   addnon_persistent_buffersbuffers	constantsr,   rI   rJ   rL   r-   r   rm   Zinput_specskindr   r7   rB   argr5   rZ   r   ZCONSTANT_TENSORZ
CUSTOM_OBJ_sink_params_deduplicate_modules_dispatch_modulesr{   input_placeholderscheck_input_constraints	enumeratenamed_modulesro   _reorder_submodulesrz   )$rW   r   r   Zfqn_listZexport_graphseen_modules
seen_attrsr   Zassigned_paramsZid_to_paramr   paramr   Zassigned_buffersZid_to_bufferr7   r%   ZtensorZ	is_bufferZid_to_constr   r&   Z	_constantconsts_targetsr   Zadded_params_bufferssZ
const_nameconstZph_name_inputs_to_stateZnode_targettargetsn	fqn_orderrc   )r   r   r0   r`     s@  







	



zUnflattenedModule.__init__c                 C   sF   |   D ]\}}t|d  t|dr t|jtjjr t|j qd S )N:r]   )r   printrB   rJ   r]   rD   rr   r   )rW   r   r   r/   r/   r0   _print_graph  s   
zUnflattenedModule._print_graphc                 C   st   | j d j}||jkr|S | jd u rtd| jj|j||| jd}t||jjkr8tdt| d|jj |S )Nr   zeThere is no flat args adapter sepcified. Are you sure you are calling this with the right arguments? )r   r   r   r   z<Flat args adaption failed, number of args mismatch Adatped: z 
Exported module: )	r   	signaturein_specr   	TypeErrorr   r   ro   Z
num_leaves)rW   	flat_argsr   r   r/   r/   r0   _adapt_flat_args  s,   

z"UnflattenedModule._adapt_flat_argsc           
      O   s   | j d j}t||j}t||f\}}dd |D }t r!|S ||jkrC| js:td| dd|j  td | 	||}d| _| j
rcdd	lm} | jdu rYd
d |D }	n|}	|| j|	| j |S )Nr   c                 S   r   r   r/   r;   xr/   r/   r0   r   *  r   z<UnflattenedModule.process_forward_inputs.<locals>.<listcomp>zGInput treespec does not match with exported module's: 
Input treespec: z. zExported module treespec: z5Adapting flat arg to match exported module's treespecT)"_check_input_constraints_for_graphc                 S   s$   g | ]}t d dtddf|fqS )r   )idxz<unknown location>)r   )r   r   r;   r   r/   r/   r0   r   C  s    )r   r   r   r   r   Ztree_flatten_with_pathr   r   r   r   r   Ztorch._export.utilsr   r   r   )
rW   ru   rf   r   Zreordered_kwargsZflat_args_with_pathr   r   r   Znew_flat_args_with_pathr/   r/   r0   process_forward_inputs"  s<   



z(UnflattenedModule.process_forward_inputsc                 O   s   t j| j|i |}| jd j}t r5t jj| | j	dj
|ddi}t|tr3t|dkr3|d S |S t j rH| jsHt j| | j	| }nt jj| | j	dj
|ddi}t||jS )Nr   rg   rh   Fr   )rD   Z_dynamodisabler   r   r   r   rr   rs   r]   rt   rJ   rq   ro   ri   rj   rb   rx   r   tree_unflattenout_spec)rW   ru   rf   r   r   
return_valZtree_outr/   r/   r0   rl   P  s&   zUnflattenedModule.forwardc                    s  t t | jD ].}|jr5|jr5|j}t| |||}d|v r$|dn|dg\}} | t	||f qt t
}|D ]}	d|	v rR|	dd\}
}||
 | q<|d |	 q<  D ]C\}
}dd t|D }t|dkrtt|D ]}t|
|d }||vr|d^ }}t| |j| qw| |
t||
 | q^ fdd	}| jd
dD ](\}}t|dr|||j qt|dr|jD ]}t|dsJ |||j qqdS )zFor a module whose call signatures are preserved, replace
        multiple modules corresponding to multiple calls to that module
        with a single dispatcher module that tracks which module to call.
        r   0r8   r   r   c                 S   s   g | ]\}}|qS r/   r/   )r;   r   r   r/   r/   r0   r     r   z7UnflattenedModule._dispatch_modules.<locals>.<listcomp>c                    sN   |j D ]!}|jdkr$|jdd }| r|  d| n|}| v r$||_qd S )Nr   r   r   r8   )r{   r|   r5   r@   )rN   r]   r   r   pathZcalled_modulesr/   r0   elide_call_indices  s   

z?UnflattenedModule._dispatch_modules.<locals>.elide_call_indicesFr   r]   r   N)r   rm   r   r   r   r   getr@   r}   intrA   rsplitr   rI   sortedro   range
_call_namer   rH   popset_submoduler!   r   rB   r]   r   )rW   r   r   r   r   r   baser   Z	attrs_mapr5   Zorig_fqnr   Zindexed_call_modulesr   r   rN   r  Zmod_r/   r  r0   r   e  sL   



z#UnflattenedModule._dispatch_modulesTFc                 C   r   )Nr"   r   r   r/   r/   r0   r     r   z UnflattenedModule.print_readabler9   r   )r(   r)   r*   r   r
   r   r`   r   r   r   rl   r   r   r   r/   r/   rc   r0   r"     s$     g.<r"   r'   r   rT   c                 C   s   t | } t| |S )a  Unflatten an ExportedProgram, producing a module with the same module
    hierarchy as the original eager module. This can be useful if you are trying
    to use :mod:`torch.export` with another system that expects a module
    hierachy instead of the flat graph that :mod:`torch.export` usually produces.

    .. note:: The args/kwargs of unflattened modules will not necessarily match
        the eager module, so doing a module swap (e.g. :code:`self.submod =
        new_mod`) will not necessarily work. If you need to swap a module out, you
        need to set the :code:`preserve_module_call_signature` parameter of
        :func:`torch.export.export`.

    Args:
        module (ExportedProgram): The ExportedProgram to unflatten.
        flat_args_adapter (Optional[FlatArgsAdapter]): Adapt flat args if input TreeSpec does not match with exported module's.

    Returns:
        An instance of :class:`UnflattenedModule`, which has the same module
        hierarchy as the original eager module pre-export.
    )r   r"   )r'   r   r/   r/   r0   r#     s   
r#   r]   r   c              	      s*  t tt| j}|jdkrt|jdksJ |jd }|j}|dt| }dd |j	 D }dd | jD }|D ]I}||j
 }	||	 }
||
 }| |# | dtjjj||f |j	 D ]	\}}| j|< qaW d   n1 suw   Y  |  fd	d
 q;t|t|d }|f|_dS )a  Transform buffer mutations from their functionalized form into a copy_
    node in the graph.

    Functionalization represents buffer mutation by passing the buffer as an input and output. So for example, the eager code:
        def forward(self, x):
            self.buffer += x
            return x * x

    Will become a graph that looks like:
        def forward(self, buffer, x):
            mutated_buffer = aten.add(buffer, x)
            mul = aten.mul(x, x)
            return (mutated_buffer, mul)

    We want to inplace this into something that looks like the original eager code:
        def forward(self, buffer, x):
            mutated_buffer = aten.add(buffer, x)
            buffer.copy_(mutated_buffer)
            mul = aten.mul(x, x)
            return (mul,)
    outputr   r   Nc                 S   r   r/   r/   )r;   r<   vr/   r/   r0   r     r   z-_inplace_buffer_mutations.<locals>.<dictcomp>c                 S   s   i | ]}|j d kr|j|qS r   )r|   r   r   r/   r/   r0   r     s    call_functionc                    s   |  uS r9   r/   )r   new_noder/   r0   <lambda>  s    z+_inplace_buffer_mutations.<locals>.<lambda>)nextiterreversedr{   r|   ro   ru   Zbuffers_to_mutateZinputs_to_buffersrI   r   inserting_aftercreate_noderD   opsatencopy_r   replace_all_uses_withrq   )r]   r   Zoutput_nodeZreturn_argsZmutation_node_to_bufferZ	mutationsZbuffers_to_inputsZinput_name_to_nodeZmutationZbuffer_nameZ
input_nameZ
input_noder<   r  Zuser_outputsr/   r  r0   r     s4   

r   c                 C   s$   t | t |k o|dt |  | kS )z2Check whether `candidate` is a prefix of `target`.N)ro   )	candidater5   r/   r/   r0   
_is_prefix  s   $r  
parent_fqn	child_fqnc                 C   s`   | dkr|S |  d}| d}|d t| |kr%td| d|  dd|t|d  S )Nr   r8   zChild module 'z(' is not a descendant of parent module 'za'.This is currently unsupported.Please try to make child module attach to parent module directly.)r@   ro   RuntimeErrorr   )r  r  Zparent_splitZchild_splitr/   r/   r0   _compute_accessor
  s   

r!  r   yc                 C   sR   dt jjdtfdd}t| jt jjsJ t|jt jjsJ || j||jkS )Nr]   rT   c                    s   g }i  dt f fdd}t| jD ]E\}}dd t||jD }|dd t||j D 7 }|jdv r:|j	nd}|
| d	|j d
| dd| d | t|< qd|S )NrT   c                    s*   t | tjjrdt t|   S t| S )N%)rJ   rD   rr   NoderZ   r   )r   Z	nodes_idxr/   r0   arg_dump!  s   z>_check_graph_equivalence.<locals>.graph_dump.<locals>.arg_dumpc                 S   s   g | ]}t |qS r/   )rZ   r   r/   r/   r0   r   '  r   z@_check_graph_equivalence.<locals>.graph_dump.<locals>.<listcomp>c                 S   s   g | ]\}}| d | qS )=r/   )r;   keyvaluer/   r/   r0   r   (  s    )r  get_attrr   z: [z](z, )r   )rZ   r   r{   r   Ztree_mapru   rf   rI   r|   r5   r}   r   r   )r]   retr&  r   r   Z	args_dumpr5   r/   r%  r0   
graph_dump  s   *
z,_check_graph_equivalence.<locals>.graph_dump)rD   rr   r   rZ   rJ   r]   )r   r"  r.  r/   r/   r0   _check_graph_equivalence  s   r/  gmc                 C   sF   d}t | d| r|d7 }t | d| s
d| }t| || |S )Nr   Z_spec_r   )rB   rC   )r0  specr   r   r/   r/   r0   	_add_spec6  s   
r2  c                 C   s*   | j tj|f}| j tj|df}|S r   )r]   r  r   Ztree_flattenoperatorgetitem)r0  r   flattenZ	getitem_0r/   r/   r0   _generate_flatten?  s   r6  c                 C   *   t | |}| j|}| jtj||fS r9   )r2  r]   r*  r  	fx_pytreeZtree_flatten_spec)r0  r   r1  r   	spec_noder/   r/   r0   _generate_flatten_specE     
r:  c                 C   r7  r9   )r2  r]   r*  r  r   r   )r0  r{   r1  r   r9  r/   r/   r0   _generate_unflattenM  r;  r<  r   c                 C   sX   | d^ }}|D ]}t| |d }|d u r d S t|tjjs# d S |} q
t| |d S )Nr8   )r@   r   rJ   rD   rE   rF   )r   r5   rN   rO   r>   submodr/   r/   r0   _get_submoduleU  s   r>  module_to_addcreate_modulec           	      C   s   | d^ }}t|D ]7\}}t| |d }|d u r7|d ur,|d|d |d  }ntj }t| || t|tjjsA dS |} q| 	|| d S )Nr8   r   F)
r@   r   r   r   rD   rE   rF   rC   rJ   Z
add_module)	r   r5   r?  r@  rN   rO   r   r>   r=  r/   r/   r0   _add_submodulef  s   
rA  r  r   c                 C   s   |dkr| S |  d|d  S )Nr   r   r/   )r  r   r/   r/   r0   r	    s   r	  	call_namec                 C   s   t t |d | d uS )Nz(@\d+)?$)rematchescape)rB  r  r/   r/   r0   r:     s   r:   c                   @   s   e Zd Z	ddejjdeejjdf deee	e
e	 ef  dee	ef de
eejjef  f
d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dS )_ModuleFrameN
flat_graphr{   .module_stackr   r'   c              
      s6  |_ |_|_|_|_|__|_|	_|
_	d_
jd \_}tj|d _ |d urH|_t|drD|jni _njjttj d_j_jj_i _i _d _d urtjj}fdd}tj|j| j|_jj rjj d }|jjj_jj tjjjjjj|d jd	 |
j}|d urjd ur|j j!d
ksJ |j j"d }|j j"d }|j#d u sJ |j#d usJ j$d x fddt%|j!D }i }|j#D ]}j&|||< qt'jt(||f|j }t)|j*D ]A\}}jj+dt,j-||ft.|t/s9|j0nd| d}t.|t/rHq#|j0jv rct11j|j0 j2|_2|jj|j0 < q#W d    n	1 spw   Y  jj3j} g }|j*D ]8}t.|t/r||j4 q|j0jvr|d  qt.|t5t6t7t8fsJ |j9j|j0  qt:jj||j }jj;t,j-|df jj;t,j-|df fddt%|j!D }fdd|j#D }W d    n	1 sw   Y  jd usJ t(|j_<|j_=d S d S d S )NFr   r   r^   c                    sN    j r j  d|  n| }|jv rj| S ttj d}|j|< |S )Nr8   rJ  )r   created_modulesr    rD   rr   r   )r   r  r=  )parentrW   r^   r/   r0   r@    s   


z,_ModuleFrame.__init__.<locals>.create_moduler   )r  parent_moduleparent_call_moduler   call_idxr'      c                    s   g | ]} j d | qS )Z_positional_arg_)r]   rw   )r;   r   rV   r/   r0   r     s    z)_ModuleFrame.__init__.<locals>.<listcomp>r  Z
_constant_)r|   r5   ru   r   c                    s"   g | ]}j jtj |fqS r/   rL  r]   r  r3  r4  )r;   r   )	args_noderW   r/   r0   r   "  s    c                    s$   i | ]}|j jtj |fqS r/   rQ  )r;   r<   )kwargs_noderW   r/   r0   r   &  s    

z)_ModuleFrame.__init__.<locals>.<dictcomp>)>rG  r{   
seen_nodesr   r   rK  rL  rH  	module_idr   verboser   r	  r  r'   rB   r   r  r    rD   rr   r   r]   node_mapnode_to_placeholderrN  r!  rA  r   rH   r}   _SubmoduleEntryr   Znum_childrenZchildren_specscontextr  r  rw   r:  rq   r   inputsr  r3  r4  rJ   r   r   copyr   inserting_beforer)  r   r   r   r   remap_inputr<  r  ru   rf   )rW   rG  r{   rT  r   r   rK  rL  rH  rU  r   r'   Z	num_callsr   r@  Zbase_module_framer   Z	args_specZkwargs_specZ	arg_nodesZkwarg_nodesr   r   r   r   Zflat_arg_nodeZinput_nodesinputZinputs_noder/   )rR  rS  rL  rW   r^   r0   r`     s   






!

	

+z_ModuleFrame.__init__c                 C   s   | j dksJ d| d|j| ju sJ | jd  | jj|j|jd}W d    n1 s0w   Y  t|j|_|| j	|< d S )Nr   zCannot add placeholder z to root moduleZ	type_expr)
r   r]   rG  r]  rw   r   rk   r\  r   rX  )rW   r   Zplaceholder_noder/   r/   r0   add_placeholder0  s   z_ModuleFrame.add_placeholderc                 C   sZ   t tjj| j|j}t tjj| j|j}| j	|j
||}t|j|_|| j|< |S r9   )r   Ztree_map_onlyrD   rr   r$  r^  ru   rf   r]   r  r5   r\  r   rW  )rW   r   ru   rf   r   r/   r/   r0   copy_sym_call_function;  s   
z#_ModuleFrame.copy_sym_call_functionc                 C   s  |j | ju sJ || jv r| j| S | d| d || jv r%| j| S |jdks3| j| jd u re| 	| | j
d ur`| jj | j
 | j
d| j| W d    n1 s[w   Y  | j| S |jdkr|jtjjjjtjjjjtjjjjtjjjjtjjjjtjjjjfv st|jdr|jjdkr| | | j| S | j| jd ur| j | j| j |S t!d|j d	| )
Nzremap_input(r,  rw   r   r  r)   	_operatorz(Could not run remap_input() on op type: z
 for node )"r]   rG  rW  r   rX  r|   r   r  r   ra  rN  rL  r]  Z
insert_argr^  r5   rD   r  r  Zsym_sizer  r>   defaultZunbindsumZdim_IntListviewdiffrB   r)   rb  r   readr   )rW   r   r/   r/   r0   r^  I  sD   















		

z_ModuleFrame.remap_inputc                    s
  j jd  g }jj}|d urijd uri|jD ]'}t|t	t
ttfr>|jjv r8|j|j  q|d  qtd| fdd tjt fdd|D |j}tjjj|j}|}n2g }j D ]}|jD ]}|jjvr|| |j|   nquqpj}t|dkr|d }t|ttjjfsJ j | |d u rd S t|tjjr|j!dnd	d
 |D |j!d< t|dkr|d u r|jj|d < d S t"|D ]!\}	}
|
d u rqtj#||	 j$}|
j!d|j!d< |jj|
< qd S )Nz'Unsupported data type for output node: c                    sV   | d u rd S  j | j }| jv r j| S | jv r  j| S td|  d j )NzCould not find output node z	. Graph: )rT  r   rW  rX  r   r]   )r  Z	seen_noderV   r/   r0   get_actual_output_node  s   



z=_ModuleFrame.finalize_outputs.<locals>.get_actual_output_nodec                 3   s    | ]} |V  qd S r9   r/   )r;   r  )ri  r/   r0   r?     s    z0_ModuleFrame.finalize_outputs.<locals>.<genexpr>r   r   valc                 S   s   g | ]}|j d qS )rj  )r   r  )r;   or/   r/   r0   r     r   z1_ModuleFrame.finalize_outputs.<locals>.<listcomp>)%rK  r
  r   r   r  r  rL  r   rJ   r   r   r   r   r   rT  r}   r   r<  r'   rq   r   r:  rN  rW  keysusersro   rm   rD   rr   r$  r]   r  r   r   ZProxyr   )rW   Zorig_outputsr   r  Ztree_out_nodeZ
parent_outZgraph_outputsZ	orig_nodeZ	user_noder   Zorig_outputZ	proxy_outr/   )ri  rW   r0   finalize_outputsu  sl   



z_ModuleFrame.finalize_outputsc                 C   s6   |  d|  | j|| j| j|< || j|j< d S )NZcopying)r   format_noder]   Z	node_copyr^  rW  rT  r   r~   r/   r/   r0   	copy_node  s   z_ModuleFrame.copy_nodec                 C   s   t | jjD ]\}}| ||jd|  qd}| j| }|jdkr7| | |d7 }| j| }|jdks$| 	| | jjD ]}|jdkrL| | q@d S )Nnn_module_stackr   rw   r   r  )
r   rG  r{   r   r   r  ro  r|   rp  run_from)rW   r   r   node_idxr/   r/   r0   	run_outer  s   







z_ModuleFrame.run_outerc                 O   s   | j rt|i | d S d S r9   )rV  r   )rW   ru   rf   r/   r/   r0   r     s   z_ModuleFrame.printc           
      C   s  d}|t | jk r| j| }|jdksJ |   | d||  | | j t | j}|jdkr>|dkr8|S |   |S t |jdi dkrPt	d| |jd }ddl
m} t |dkri||v ri| j}nd	d
 |jd  D }|d | | jkr|   | d| j | | j |S |d usJ t| j|r|| }| d| t|jd  | }	t| j| j| j| j| j| j| | j|g |	dd | j
|}|d7 }q|| jksJ |jdkr| j| j |j | | |d7 }|t | jk s	d S d S )Nr   rw   ZSTEPr  r   rq  z(Unable to find nn_module_stack for node )_EMPTY_NN_MODULE_STACK_KEYc                 S   s@   g | ]\}\}}||r|nd d|v rt |dd ndfqS )Nr   rI  r   )r  r@   )r;   r<   r  r^   r/   r/   r0   r   
  s    

z)_ModuleFrame.run_from.<locals>.<listcomp>Z	outliningzCreating new stack frame forr   r*  )ro   r{   r|   r   ro  rH  rn  r   r  r   Z(torch._export.passes._node_metadata_hookru  rI   r   r]   r  rm   rl  rF  rG  rT  r   r   rK  r@   r   rr  r  r   r5   rp  )
rW   rs  Z
module_idxr   depthrq  ru  Znode_module_stackZnext_moduleZnext_module_keyr/   r/   r0   rr    sn   



	


z_ModuleFrame.run_fromr9   )r(   r)   r*   rD   rr   r   rq   r$  rm   rZ   r
   r  r   r   r   rx   r"   r`   ra  rb  r^  rn  rp  rt  r   rr  r/   r/   r/   r0   rF    s,    	

 %,TrF  c                   @   sJ   e Zd ZU eed< ejjed< ejj	ed< eed< e
ed< ejjed< dS )rY  r  rM  rN  r   rO  r'   N)r(   r)   r*   rZ   r[   rD   rE   rF   rr   r$  r  r/   r/   r/   r0   rY  C  s   
 rY  
orig_graphroot_modulec                 C   sV   i }t t}t t}i }t| t| j||||d dgddd |jD |d  ||fS )N)r   Nr   r   c                 S   s   i | ]
}|j r|j|j qS r/   )r   r   r   r/   r/   r0   r   \  s    z'_outline_submodules.<locals>.<dictcomp>)r'   )r   rm   rA   rF  rq   r{   r   rt  )rw  rx  rT  r   r   rK  r/   r/   r0   r   M  s*   r   r   rL  r   rN   c                 C   s   |dkr!t | dd  D ]}t| |d u r t| |tj  qg }t | j D ]*\}}|d u r3q*|| }t	|||
dd d d t| | ||| ||f q*|jtdd |D ]\}}}| || q`d S )Nr   r   r   r   r8   )rN   )r(  )rm   rl  r>  rA  rD   rE   rF   rH   rI   r   r@   delattrr}   sortr3  
itemgetterZregister_module)rL  r   rN   r   childrenr   childr   r/   r/   r0   r   f  s"   
r   c                   @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )r   av  
    Collect the intermediate values of buffer mutations in a graph,
    along with the module call fqns that create and use them. Later,
    in each fqn associated with an intermediate value we will install
    a corresponding attribute, so that it can be updated and read.

    Example: in the following graph, suppose that buf_in and buf_out
    are the input and output values of a buffer.

        buf_in = placeholder()
        ...
        ival1 = f0(buf_in, ...)  # inside self.n0(...)
        ...
        ival2 = f1(ival1, ...)  # inside self.n1(...)
        ...
        buf_out = f2(ival2, ...)  # inside self.n2(...)
        return buf_out, ...

    Here ival1 and ival2 are intermediate values created inside
    calls to n0 and n1 respectively, and used inside calls to
    n1 and n2 respectively.

    Thus our analysis will produce {ival1: {n0, n1}, ival2: {n1, n2}}.
    c                 C   s   t t| _i | _d S r9   )r   rA   fqnsstoragerV   r/   r/   r0   r`     s   

z_IVals.__init__c                 C   s   | d |jd|j |jd}t|j|_W d   n1 s"w   Y  |j| jvr?|jd }tj|j	|j
d| j|j< | j|j | |S )zM
        Read attribute corresponding to a given intermediate value.
        N__ival__r`  rj  )dtype)r]  r*  r   rk   r\  r   r  rD   emptyshaper  r~  r   )rW   r   r]   r   	ival_nodeZfaker/   r/   r0   rh    s   
z_IVals.readc                 C   s   | j |j | || |jd|j |jd}t|j|_W d   n1 s+w   Y  || |dt	j
jj||f}t|j|_W d   dS 1 sTw   Y  dS )zO
        Update attribute corresponding to a given intermediate value.
        r  r`  Nr  )r~  r   r   r  r*  rk   r\  r   r  rD   r  r  r  )rW   r   r]   r   r  Znew_ival_noder/   r/   r0   rG     s   "z_IVals.updatec                 C   s   d|fg}|D ](}|D ]#}| |j|jf |jj}|jD ]}|j| jv r-| |j|| qqqtt	}| j
 D ]\}	}
|
D ]	}||  |	 q?q9|D ]\}}|| D ]}	d|	 }t||| j|	  qTqLdS )z
        Update attributes corresponding to intermediate values that were read.
        Finally, initialize attributes in all modules that read or update
        corresponding intermediate values.
        r   r  N)r}   r   r'   r]   r{   r   r  rG   r   rm   r~  rI   rC   )rW   
partitionsrx  entriesshared_submodulesr   r]   r   r   r   r~  r   r   Z	ival_namer/   r/   r0   r     s,   


z_IVals.createN)r(   r)   r*   r   r`   rh  rG   r   r/   r/   r/   r0   r   |  s    r   r   c                 C   sH   |  D ]\}}|rt||n|}|D ]}t| |}t||| qqd S r9   )rI   r   r   rC   )r0  rx  r   r  namesr'   r   rj  r/   r/   r0   r     s   
r   c                 C   s   i }| D ]f}t |D ]_\}}t|j|j}t|j|}d}|d | D ]E}t|j|jrh|j}	|j|jkr]|	d^ }
}t
|	|
j| t|j|j}t|j|}||j_|||<  n|sh|	||j d}q#q
q|S )NFr8   T)r   r	  r   rO  r!  r  r/  r'   rM  r@   r   rH   r
  rN  r5   r  )r  r   r  r   r   r  r5   ZdeduplicatedseenrL  rN   r   Zseen_child_fqnZseen_targetr/   r/   r0   r     s2   
%r   r   scopemodule_id_to_inputs_removedc              	      sv   du rt t t|  v rt|  t|  iS | j D ]#\}tttjj	|||g  }| D ]\}} | 
| q4qt| dd}|du sRt|jdkrT S t|tjjs]J ttdd |j}	|	d }
tdd |j}|D ] }t| |jdurt v rtt fdd|j|_qui }|	D ]3}|j|vrqd}||j D ]}|d	}|dt| d
d |D kr|} nq|du rq|||< qt }| D ]U\}}t|jdkr|t|d }t| |}t|tjtjfsJ ||
 |dd	|}W d   n	1 sw   Y  |j |dd |!| |"|j qt| t#r5| $  t| |iS )a  Sink params, buffers, and constants from graph inputs into get_attr nodes.

    Exported modules are purely functional, so they pass their parameters and
    buffers in as inputs to the graph.

    To replicate eager's semantics, we need to get them from the module state
    via get_attr instead.

    module: GraphModule, potentially containing nested submodules.
    inputs_to_state: mapping graph input names to the corresponding key in the state_dict.
    scope: tracks where we are in the module hierarchy, so that we can emit the
        right `getattr(self, "foo.bar")` calls, etc.
    module_id_to_inputs_removed: records inputs removed by child modules, mapping
        the module object id to the list of placeholder node names in the child module
        that were removed.
    Nr]   r   c                 S   
   | j dkS )Nrw   r   r   r/   r/   r0   r  B     
 z_sink_params.<locals>.<lambda>rI  c                 S   r  )Nr   r   r  r/   r/   r0   r  F  r  c                    s   | j  t vS r9   )r   r   r  r  	submoduler/   r0   r  N  r   r8   c                 S   s   g | ]	}| d d qS )r   r   )r@   r   r/   r/   r0   r   \  s    z _sink_params.<locals>.<listcomp>r*  T)Zpropagate_meta)%r   rA   r   rH   rI   r   r	   rD   rE   rF   rG   r   ro   r{   rJ   rr   r   rm   filterr   r5   rq   ru   r   r@   rm  r   rL   rM   r  r  r   r  Z
erase_noder   r    r   )r'   r   r  r  r   Zsubmod_id_to_inputs_removedr<   r  r]   r[  Zthe_last_inputZcall_module_nodesr   Zinputs_to_state_of_scopeZ
state_nameZsnZsn_splitZinputs_removedZ	attr_pathZ
state_attrr  r/   r  r0   r     sx   




r   )Tr9   )r   )dr   r\  loggingr3  rC  collectionsr   
contextlibr   r   dataclassesr   enumr   typingr   r   r	   r
   r   rD   Ztorch.fx._pytreerr   Z_pytreer8  Ztorch.utils._pytreeutilsr   Z"torch._library.fake_class_registryr   Ztorch.export._tree_utilsr   Ztorch.export.exported_programr   r   r   r   r   r   r   r   r   Ztorch.fx._symbolic_tracer   Ztorch.fx.graph_moduler   r   r   r   r   Z_remove_effect_tokens_passr   	getLoggerr(   log__all__r$   r1   r2   rL   rM   rE   rF   rZ   boolrQ   rR   r    r!   ABCr   r"   r#   r   r   r  r!  r/  r2  rx   r$  r6  r:  r<  r>  rA  r  r	  r:   rF  rY  r   r   r   r   rA   r   r   rm   r   r/   r/   r/   r0   <module>   s   ,
	

3X0   

;	


   ;	

`
/