o
    hl                    @   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 )	_AttrKind	parameterbufferconstantmoduleN)__name__
__module____qualname__	PARAMETERBUFFERCONSTANTMODULE r0   r0   j/var/www/html/construction_image-detection-poc/venv/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)old_flagr0   r0   r1   _disable_interpreter;   s   r4   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kt_callitemr0   r1   	<genexpr>\   s    
z_assign_attr.<locals>.<genexpr>)r9   z2FakeScriptObject should only exist during tracing.)splitsethasattrsetattrtorchnnModuleupdate_modulesitemsr$   r,   
isinstance	Parameterregister_parameterr-   Tensorregister_bufferr.   r   ScriptObjectr/   )	r5   r6   r7   r8   r9   prefixfield
to_modulestsr0   r@   r1   _assign_attrH   sH   





rW   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 r;   )rY   selfr0   r0   r1   	type_name~      z_SubmoduleBase.type_nameN)r)   r*   r+   r
   str__annotations__r^   r0   r0   r0   r1   rX   {   s   
 rX   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 r;   )super__init__rc   rY   owning_moduler2   _run_with_interpreter)r]   rc   rd   	__class__r0   r1   rf      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 r;   r0   )r=   
kwarg_namekwargsr0   r1   rB      s    z,InterpreterModule.forward.<locals>.<genexpr>rc   enable_io_processingF)rb   r   rG   compileris_dynamo_compilingrh   typeforwardlist	arg_nameslenextendtuplefxInterpreterrc   run)r]   argsrm   arg_listkwarg_namesr0   rl   r1   rs      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 )Nrb   placeholder)rG   ry   GraphModulerc   __dict__lintru   nodesopappendr7   r]   noder0   r0   r1   finalize   s   

zInterpreterModule.finalizeTFc                 C      t | d||||S )Nr    r   r]   print_outputinclude_strideinclude_devicecoloredr0   r0   r1   print_readable      z InterpreterModule.print_readabler;   TFFF)r)   r*   r+   __doc__r
   rG   ry   r   ra   Graphr`   rf   rs   r   r   __classcell__r0   r0   ri   r1   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   )re   rf   rK   rF   getattrrY   _call_modules
_num_calls)r]   r   r   accessorri   r0   r1   rf      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   rv   	Exception)r]   r|   rm   call_moduler0   r0   r1   rs      s   z#InterpreterModuleDispatcher.forwardc                 C   r[   r;   )r   r\   r0   r0   r1   r      r_   z(InterpreterModuleDispatcher.call_modulesTFc                    s$    fdd| j D }d|S )Nc                    s   g | ]
}|  qS r0   )r   )r=   modr   r   r   r   r0   r1   
<listcomp>   s    z>InterpreterModuleDispatcher.print_readable.<locals>.<listcomp>
)r   join)r]   r   r   r   r   outputsr0   r   r1   r      s   
	z*InterpreterModuleDispatcher.print_readabler   )r)   r*   r+   r   rD   r`   rt   r    rf   rs   r   r   r   r0   r0   ri   r1   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metadatarZ   c                 C   s   dS )z=NOTE: This adapter may mutate given ``input_args_with_path``.Nr0   )r]   r   r   r   r   r0   r0   r1   adapt  s   	zFlatArgsAdapter.adaptr;   )r)   r*   r+   r   abcabstractmethodpytreeTreeSpecrt   r   r
   dictr`   r   r0   r0   r0   r1   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 r0   )fqnr=   entryr0   r0   r1   r   %      z.UnflattenedModule.__init__.<locals>.<listcomp>r    unflattened_moduleF)requires_grad)r8   T)r8   r9   c                    s    |  }| ||f d S r;   )r   )obj_id	node_nametarget_name	name_list)
consts_mapr0   r1   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   r0   )r=   tr0   r0   r1   r         c                    s   g | ]}| vr|qS r0   r0   r=   r   )redirected_call_indicesr0   r1   r         c                 S   s   g | ]}d |vr|qS )@r0   r   r0   r0   r1   r     r   c                 S   s   g | ]	}|j d kr|qS r   r   r=   r   r0   r0   r1   r     s    c                 S      i | ]\}}||qS r0   r0   )r=   ir   r0   r0   r1   
<dictcomp>      z.UnflattenedModule.__init__.<locals>.<dictcomp>remove_duplicate)Hre   rf   graph_signaturebackward_signature
ValueErrormodule_call_graphr   rc   rG   ry   r   rg   r   rb   metaadaptedr2   rh   _inplace_buffer_mutations_IValsivals_outline_submodulescreatevalues_copy_graph_attrs_graph_modulerange_constraintsequality_constraints
state_dictrD   
parametersidrH   rN   cloner   rW   r$   r,   addnon_persistent_buffersbuffers	constantsr-   rL   rM   rP   r.   r   rt   input_specskindr   r9   rE   argr7   r`   r   CONSTANT_TENSOR
CUSTOM_OBJ_sink_params_deduplicate_modules_dispatch_modulesr   input_placeholderscheck_input_constraints	enumeratenamed_modulesrv   _reorder_submodulesr   )$r]   r   r   fqn_listexport_graphseen_modules
seen_attrsr   assigned_paramsid_to_paramr   paramr   assigned_buffersid_to_bufferr9   r&   tensor	is_bufferid_to_constr   r'   	_constantconsts_targetsr   added_params_bufferss
const_nameconstph_name_inputs_to_statenode_targettargetsn	fqn_orderri   )r   r   r1   rf     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:rc   )r   printrE   rM   rc   rG   ry   r   )r]   r   r   r0   r0   r1   _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   rv   
num_leaves)r]   	flat_argsr  r  r0   r0   r1   _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   r0   r=   xr0   r0   r1   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   r0   r0   r1   r   C  s    )r   r  r   r  r   tree_flatten_with_pathr   r   r  r  r   torch._export.utilsr  r   r   )
r]   r|   rm   r  reordered_kwargsflat_args_with_pathr  r  r  new_flat_args_with_pathr0   r0   r1   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   rn   ro   Fr   )rG   _dynamodisabler!  r   r  r   ry   rz   rc   r{   rM   rx   rv   rp   rq   rh   r   r   tree_unflattenout_spec)r]   r|   rm   r  r  
return_valtree_outr0   r0   r1   rs   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   0r:   r   r   c                 S   s   g | ]\}}|qS r0   r0   )r=   r  r   r0   r0   r1   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   r:   )r   r   r7   rC   )rS   rc   r   r   pathcalled_modulesr0   r1   elide_call_indices  s   

z?UnflattenedModule._dispatch_modules.<locals>.elide_call_indicesFr   rc   r   N)r   rt   r   r   r  r   getrC   r   intrD   rsplitr   rL   sortedrv   range
_call_namer   rK   popset_submoduler!   r   rE   rc   r   )r]   r   r  r   r   r   baser  	attrs_mapr7   orig_fqnr   indexed_call_modulesr   r   rS   r,  mod_r0   r*  r1   r   e  sL   



z#UnflattenedModule._dispatch_modulesTFc                 C   r   )Nr"   r   r   r0   r0   r1   r     r   z UnflattenedModule.print_readabler;   r   )r)   r*   r+   r   r
   r   rf   r  r  r!  rs   r   r   r   r0   r0   ri   r1   r"     s$     g.<r"   r(   r   rZ   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   r0   r0   r1   r#     s   
r#   rc   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   r0   r0   )r=   r>   vr0   r0   r1   r     r   z-_inplace_buffer_mutations.<locals>.<dictcomp>c                 S   s   i | ]}|j d kr|j|qS r   )r   r   r   r0   r0   r1   r     s    call_functionc                    s   |  uS r;   r0   )r  new_noder0   r1   <lambda>  s    z+_inplace_buffer_mutations.<locals>.<lambda>)nextiterreversedr   r   rv   r|   buffers_to_mutateinputs_to_buffersrL   r   inserting_aftercreate_noderG   opsatencopy_r   replace_all_uses_withrx   )rc   r   output_nodereturn_argsmutation_node_to_buffer	mutationsbuffers_to_inputsinput_name_to_nodemutationbuffer_name
input_name
input_noder>   r;  user_outputsr0   r=  r1   r     s4   

r   c                 C   s$   t | t |k o|dt |  | kS )z2Check whether `candidate` is a prefix of `target`.N)rv   )	candidater7   r0   r0   r1   
_is_prefix  s   $rW  
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   r:   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.)rC   rv   RuntimeErrorr   )rX  rY  parent_splitchild_splitr0   r0   r1   _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 )Nrc   rZ   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 )NrZ   c                    s*   t | tjjrdt t|   S t| S )N%)rM   rG   ry   Noder`   r   )r   	nodes_idxr0   r1   arg_dump!  s   z>_check_graph_equivalence.<locals>.graph_dump.<locals>.arg_dumpc                 S   s   g | ]}t |qS r0   )r`   r  r0   r0   r1   r   '  r   z@_check_graph_equivalence.<locals>.graph_dump.<locals>.<listcomp>c                 S   s   g | ]\}}| d | qS )=r0   )r=   keyvaluer0   r0   r1   r   (  s    )r<  get_attrr   z: [z](z, )r   )r`   r   r   r   tree_mapr|   rm   rL   r   r7   r   r   r   )rc   retrc  r   r   	args_dumpr7   r0   ra  r1   
graph_dump  s   *
z,_check_graph_equivalence.<locals>.graph_dump)rG   ry   r   r`   rM   rc   )r  r^  rm  r0   r0   r1   _check_graph_equivalence  s   rn  gmc                 C   sF   d}t | d| r|d7 }t | d| s
d| }t| || |S )Nr   _spec_r   )rE   rF   )ro  specr   r   r0   r0   r1   	_add_spec6  s   
rr  c                 C   s*   | j tj|f}| j tj|df}|S r   )rc   r<  r   tree_flattenoperatorgetitem)ro  r   flatten	getitem_0r0   r0   r1   _generate_flatten?  s   rx  c                 C   *   t | |}| j|}| jtj||fS r;   )rr  rc   rg  r<  	fx_pytreetree_flatten_spec)ro  r   rq  r   	spec_noder0   r0   r1   _generate_flatten_specE     
r}  c                 C   ry  r;   )rr  rc   rg  r<  r   r$  )ro  r   rq  r   r|  r0   r0   r1   _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 )Nr:   )rC   r   rM   rG   rH   rI   )r   r7   rS   rT   rA   submodr0   r0   r1   _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 )Nr:   r   F)
rC   r   r   r   rG   rH   rI   rF   rM   
add_module)	r   r7   r  r  rS   rT   r   rA   r  r0   r0   r1   _add_submodulef  s   
r  r5  r  c                 C   s   |dkr| S |  d|d  S )Nr   r   r0   )r5  r  r0   r0   r1   r2    s   r2  	call_namec                 C   s   t t |d | d uS )Nz(@\d+)?$)rematchescape)r  r5  r0   r0   r1   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   rd   c                    sN    j r j  d|  n| }|jv rj| S ttj d}|j|< |S )Nr:   r  )r   created_modulesr    rG   ry   r   )r   r)  r  )parentr]   rd   r0   r1   r    s   


z,_ModuleFrame.__init__.<locals>.create_moduler   )rX  parent_moduleparent_call_moduler   call_idxr(      c                    s   g | ]} j d | qS )_positional_arg_)rc   r   )r=   r  r\   r0   r1   r     s    z)_ModuleFrame.__init__.<locals>.<listcomp>r<  
_constant_)r   r7   r|   r   c                    s"   g | ]}j jtj |fqS r0   r  rc   r<  rt  ru  )r=   r   )	args_noder]   r0   r1   r   "  s    c                    s$   i | ]}|j jtj |fqS r0   r  )r=   r>   )kwargs_noder]   r0   r1   r   &  s    

z)_ModuleFrame.__init__.<locals>.<dictcomp>)>r  r   
seen_nodesr   r   r  r  r  	module_idr   verboser   r2  rY  r(   rE   r   r-  r    rG   ry   r   rc   node_mapnode_to_placeholderr  r]  r  r   rK   r   _SubmoduleEntryr  num_childrenchildren_specscontextrE  r1  r   r}  rx   r   inputsrF  rt  ru  rM   r   r   copyr   inserting_beforerf  r   r   r   r   remap_inputr  r<  r|   rm   )r]   r  r   r  r   r   r  r  r  r  r   r(   	num_callsr   r  base_module_framer  	args_speckwargs_spec	arg_nodeskwarg_nodesr   r  r  r   flat_arg_nodeinput_nodesinputinputs_noder0   )r  r  r  r]   rd   r1   rf     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	type_expr)
r   rc   r  r  r   r   rr   r  r   r  )r]   r  placeholder_noder0   r0   r1   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 r;   )r   tree_map_onlyrG   ry   r`  r  r|   rm   rc   r<  r7   r  r   r  )r]   r  r|   rm   r   r0   r0   r1   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(ri  r   r   r<  r*   	_operatorz(Could not run remap_input() on op type: z
 for node )"rc   r  r  r  r  r   r   r-  r   r  r  r  r  
insert_argr  r7   rG   rG  rH  sym_sizer.  rA   defaultunbindsumdim_IntListviewdiffrE   r*   r  r   readrZ  )r]   r  r0   r0   r1   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: )r  r   r  r  rZ  rc   )r:  	seen_noder\   r0   r1   get_actual_output_node  s   



z=_ModuleFrame.finalize_outputs.<locals>.get_actual_output_nodec                 3   s    | ]} |V  qd S r;   r0   )r=   r:  )r  r0   r1   rB     s    z0_ModuleFrame.finalize_outputs.<locals>.<genexpr>r   r   valc                 S   s   g | ]}|j d qS )r  )r   r-  )r=   or0   r0   r1   r     r   z1_ModuleFrame.finalize_outputs.<locals>.<listcomp>)%r  r3  r   r   r-  rY  r  r   rM   r   r   r   r   r   r  r   rZ  r  r(   rx   r%  r}  r  r  keysusersrv   rt   rG   ry   r`  rc   r:  r   r   Proxyr   )r]   orig_outputsr  r:  tree_out_node
parent_outgraph_outputs	orig_node	user_noder   orig_output	proxy_outr0   )r  r]   r1   finalize_outputsu  sl   



z_ModuleFrame.finalize_outputsc                 C   s6   |  d|  | j|| j| j|< || j|j< d S )Ncopying)r  format_noderc   	node_copyr  r  r  r   r   r0   r0   r1   	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   r   r   r:  )
r   r  r   r  r   r-  r  r   r  run_from)r]   r   r   node_idxr0   r0   r1   	run_outer  s   







z_ModuleFrame.run_outerc                 O   s   | j rt|i | d S d S r;   )r  r  )r]   r|   rm   r0   r0   r1   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   r   STEPr:  r   r  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   r  r   )r.  rC   )r=   r>   r)  rd   r0   r0   r1   r   
  s    

z)_ModuleFrame.run_from.<locals>.<listcomp>	outliningzCreating new stack frame forr   rg  )rv   r   r   r  r  r  r  r   r-  rZ  (torch._export.passes._node_metadata_hookr  rL   r   rc   rW  rt   r  r  r  r  r   r   r  rC   r   r  rY  r   r7   r  )
r]   r  
module_idxr   depthr  r  node_module_stacknext_modulenext_module_keyr0   r0   r1   r    sn   



	


z_ModuleFrame.run_fromr;   )r)   r*   r+   rG   ry   r   rx   r`  rt   r`   r
   r.  r   r   r   r   r"   rf   r  r  r  r  r  r  r  r  r0   r0   r0   r1   r    s,    	

 %,Tr  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 )r  rX  r  r  r   r  r(   N)r)   r*   r+   r`   ra   rG   rH   rI   ry   r`  r.  r0   r0   r0   r1   r  C  s   
 r  
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 r0   )r  r   r   r0   r0   r1   r   \  s    z'_outline_submodules.<locals>.<dictcomp>)r(   )r   rt   rD   r  rx   r   r   r  )r  r  r  r   r   r  r0   r0   r1   r   M  s*   r   r   r  r  rS   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   r:   )rS   )re  )rt   r  r  r  rG   rH   rI   rK   rL   r   rC   delattrr   sortrt  
itemgetterregister_module)r  r  rS   r   childrenr   childr  r0   r0   r1   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 r;   )r   rD   fqnsstorager\   r0   r0   r1   rf     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  r  )dtype)r  rg  r   rr   r  r   r  rG   emptyshaper  r  r   )r]   r   rc   r   	ival_nodefaker0   r0   r1   r    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   rE  rg  rr   r  r   rF  rG   rG  rH  rI  )r]   r   rc   r   r  new_ival_noder0   r0   r1   rJ     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(   rc   r   r   r  rJ   r   rt   r  rL   rF   )r]   
partitionsr  entriesshared_submodulesr   rc   r   r   r   r  r   r   	ival_namer0   r0   r1   r     s,   


z_IVals.createN)r)   r*   r+   r   rf   r  rJ   r   r0   r0   r0   r1   r   |  s    r   r   c                 C   sH   |  D ]\}}|rt||n|}|D ]}t| |}t||| qqd S r;   )rL   r   r   rF   )ro  r  r   rY  namesr(   r   r  r0   r0   r1   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 )NFr:   T)r   r2  r   r  r]  rX  rn  r(   r  rC   r   rK   r3  r  r7   r4  )r  r   r  r   r   rY  r7   deduplicatedseenr  rS   r   seen_child_fqnseen_targetr0   r0   r1   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.
    Nrc   r   c                 S   
   | j dkS )Nr   r   r  r0   r0   r1   r?  B     
 z_sink_params.<locals>.<lambda>r  c                 S   r  )Nr   r   r  r0   r0   r1   r?  F  r   c                    s   | j  t vS r;   )r   r   r  r  	submoduler0   r1   r?  N  r   r:   c                 S   s   g | ]	}| d d qS )r   r   )rC   r  r0   r0   r1   r   \  s    z _sink_params.<locals>.<listcomp>rg  T)propagate_meta)%r   rD   r   rK   rL   r   r	   rG   rH   rI   rJ   r   rv   r   rM   ry   r   rt   filterr   r7   rx   r|   r   rC   r  r   rP   rR   rE  rF  r   rJ  
erase_noder   r    r   )r(   r	  r  r  r   submod_id_to_inputs_removedr>   r;  rc   r  the_last_inputcall_module_nodesr   inputs_to_state_of_scope
state_namesnsn_splitinputs_removed	attr_path
state_attrr>  r0   r  r1   r     sx   




r   )Tr;   )r   )dr   r  loggingrt  r  collectionsr   
contextlibr   r   dataclassesr   enumr   typingr   r   r	   r
   r   rG   torch.fx._pytreery   _pytreerz  torch.utils._pytreeutilsr   "torch._library.fake_class_registryr   torch.export._tree_utilsr   torch.export.exported_programr   r   r   r   r   r   r   r   r   torch.fx._symbolic_tracer   torch.fx.graph_moduler   r   r   r   r   _remove_effect_tokens_passr   	getLoggerr)   log__all__r$   r2   r4   rP   rR   rH   rI   r`   boolrW   rX   r    r!   ABCr   r"   r#   r   r   rW  r]  rn  rr  r   r`  rx  r}  r  r  r  r.  r2  r<   r  r  r   r   r   r   rD   r   r   rt   r   r0   r0   r0   r1   <module>   s   ,
	

3X0   

;	


   ;	

`
/