U
    yh)                     @   s  d dl 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Z d dlmZmZ d dlmZmZ ddlmZ dd	lmZmZmZmZ e	jjd
d Ze	j j!eee"  eee"e	j j#f ee"e	j j#f f dddZ$e	j j!eee"  ee"e	j j#f ee"e	j j#f ddddZ%d&ej&eej& eee"  edddZ'd'e	j j!eee"  eee"  ej&eej& ee"ef ee"ef eee"  dddZ(e	j j!eee"ef ee"ef ddddZ)G dd de*Z+G dd de	j j!e+dZ,d(e	j j!ee d d!d"Z-ee	j.j/d#d$d%Z0dS ))    N)chain)AnyDictListOptionalTuple)"_check_input_constraints_for_graph)_assign_attr	_AttrKind)_PyTreeCodeGen_PyTreeInfo   )_remove_effect_tokens)ExportedProgramExportGraphSignature	InputKind
OutputKindc                 O   sJ   t |\}}|| jkr.td| j d| tdd | jjD || jS )Nz>Trying to flatten user inputs with exported input tree spec: 
z-
but actually got inputs with tree spec of: 
c                 S   s   g | ]}|j d kr|qS placeholderop.0node r   F/var/www/html/venv/lib/python3.8/site-packages/torch/export/_unlift.py
<listcomp>"   s     
 z5_check_input_constraints_pre_hook.<locals>.<listcomp>)pytreeZtree_flatten_with_pathZ_in_spec
ValueErrorr   graphnodesrange_constraints)selfargskwargsZflat_args_with_pathZreceived_specr   r   r   !_check_input_constraints_pre_hook   s    
r%   )gmlifted_inputsreturnc           	   
   C   s   i }i }dd | j jD }t|t|ks.tt||D ]j\}}|dkrT|||j< q8| j |< | j |}|| |j	}| j 
| ||_	|||< W 5 Q R X q8||fS )z_
    Unlift inputs referring to params/buffers/constants as getattr nodes in the
    graph
    c                 S   s   g | ]}|j d kr|qS r   r   r   r   r   r   r   3   s     
 z-_unlift_inputs_as_getattr.<locals>.<listcomp>N)r   r    lenAssertionErrorzipnameZinserting_afterZget_attrreplace_all_uses_withmeta
erase_node)	r&   r'   unlifted_name_to_nodeinput_name_to_nodeZplaceholder_nodesZ
input_nodeZlifted_nodeZgetattr_nodemetadatar   r   r   _unlift_inputs_as_getattr(   s    
r3   )r&   mutated_outputsr0   r1   r(   c              
   C   s(  d}| j jD ]}|jdkr|} q$q|dk	s0tt|jd }t|t|ksTtg }t||D ]\}}	|	dkr~|	| qb|	|kr||	 }
n"|	|kr||	 }
nt
d|	 d| j |  | j tjjjj|
|f}W 5 Q R X qb| j |, | j t|}|| | j | W 5 Q R X dS )zt
    Find the all the buffers and inputs that were mutated and insert copy_
    operators to reflect mutations.
    Noutputr   zCould not find z  in either buffer or input nodes)r   r    r   r*   r   Ztree_flattenr#   r)   r+   appendRuntimeErrorZinserting_beforeZcall_functiontorchZopsZatenZcopy_defaultr5   tupler-   r/   )r&   r4   r0   r1   Zoutput_noder   outputsZuser_output_nodesZreturn_nodeZmutated_node_nameZmutated_node_Z
new_outputr   r   r   _insert_copy_for_mutationsE   s:    






 
r=   )in_specout_specforward_arg_namesr(   c                 C   s   |r
|}nv| j tkrl| jdkrl| jd j tkrl| jd j tkrldd t| jd jD }|| jd j ndd t| jD }tt	|| |S )zK
    Create the codegen for the graph module based on the in/out specs
       r   r   c                 S   s   g | ]}d | qS Zarg_r   r   ir   r   r   r      s     z _get_codegen.<locals>.<listcomp>c                 S   s   g | ]}d | qS rB   r   rC   r   r   r   r      s     )
typer:   Znum_childrenZchildren_specsdictrangeextendcontextr   r   )r>   r?   r@   namesr   r   r   _get_codegens   s(    rK   )r&   r'   r4   r>   r?   
state_dict	constantsr@   c           
      C   sL   t | |\}}	t| |||	 t|||| j_| j  | j  |   | S )a  
    Args:
        lifted_inputs: A list matching the graph module's input nodes. For
        an input node that is referring to a lifted parameter/buffer, this
        list will contain the fqn the corresponding attribute. Otherwise, this
        list will contain None. This is used to unlift the lifted parameters as
        get_attr nodes.

        mutated_outputs: A list matching the graph module's output nodes. For
        an output node that is referring to a mutated buffer or user input, this
        list will contain the name of the corresponding buffer or user input
        that needs to be mutated. Otherwise, this list will contain None. This
        is used to re-insert an inplace copy_ operator to copy the mutated
        values back to the original node.
    )r3   r=   rK   r   Z_codegenZlintZeliminate_dead_codeZ	recompile)
r&   r'   r4   r>   r?   rL   rM   r@   r0   r1   r   r   r   _unlift   s        

rN   )new_gmgraph_signaturerL   rM   r(   c                 C   s   t |j}|jD ]:}||kr*d}|| }nd}|| }t|| |tj|d q|jD ]}|| }t|| |tjd qRt|j	|j
D ]}|| }t|| |tjd qd S )NFT	attr_kind
persistent)rR   )setnon_persistent_buffersbuffersr	   r
   BUFFER
parameters	PARAMETERr   Zlifted_custom_objsZlifted_tensor_constantsZCONSTANT)rO   rP   rL   rM   rU   r,   rS   valuer   r   r   _register_attrs_to_new_gm   sB    


    
 r[   c                       s*   e Zd ZdZdd Zd fdd	Z  ZS )_StatefulGraphModuleFactoryzO
    Metaclass that ensures a private constructor for _StatefulGraphModule
    c                 O   s   t | j d| j dd S )N.z has no public constructor. )	TypeError
__module____qualname__)clsr#   r$   r   r   r   __call__   s    z$_StatefulGraphModuleFactory.__call__Nc                    s   t  j|||dS )Nr!   )superrb   )ra   rootr   r!   	__class__r   r   _create   s
    z#_StatefulGraphModuleFactory._create)N)__name__r_   r`   __doc__rb   rh   __classcell__r   r   rf   r   r\      s   r\   c                       s   e Zd Zd fdd	Z  ZS )_StatefulGraphModuleNc                    s   t  || |pg | _d S N)rd   __init__r!   )r"   re   r   r!   rf   r   r   rn      s    z_StatefulGraphModule.__init__)N)ri   r_   r`   rn   rk   r   r   rf   r   rl      s   rl   )	metaclass)plain_graph_modulerP   c                 C   sV   t j| | j|d}|jtdd |d kr,|S |jD ]}t| |||tj	dd q2|S )Nrc   T)Zwith_kwargsFrQ   )
rl   rh   r   Zregister_forward_pre_hookr%   rU   r	   Z
get_bufferr
   rW   )rp   r!   rP   Zstateful_gmbufferr   r   r   _create_stateful_graph_module   s(     
rr   )epr(   c              
   C   s   t | } tj| jt| j}t|| j	| j
| j | jjd}dd | j	jD }dd | j	jD }t|||| jj| jj| j
| j|d}t|| j| j	}|j| jj |S )Nr@   c                 S   s0   g | ](}|j tjtjtjtjfkr(|jnd qS rm   )kindr   rW   ZCONSTANT_TENSORrY   Z
CUSTOM_OBJtarget)r   r>   r   r   r   r      s   z:_unlift_exported_program_lifted_states.<locals>.<listcomp>c                 S   s(   g | ] }|j tjtjfkr |jnd qS rm   )rt   r   ZBUFFER_MUTATIONZUSER_INPUT_MUTATIONru   )r   r?   r   r   r   r   /  s   
)r@   )r   r8   fxGraphModuleZgraph_modulecopydeepcopyr   r[   rP   rL   rM   r.   getZinput_specsZoutput_specsrN   Z	call_specr>   r?   rr   r!   update)rs   rO   r@   r'   r4   Z	unlift_gmr   r   r   &_unlift_exported_program_lifted_states  s6    

  r|   )N)N)N)1rx   	itertoolsr   typingr   r   r   r   r   r8   Ztorch.utils._pytreeutilsZ_pytreer   Ztorch._export.utilsr   Ztorch.export.unflattenr	   r
   Ztorch.fx.graphr   r   Z_remove_effect_tokens_passr   Zexported_programr   r   r   r   Z_dynamodisabler%   rv   rw   strNoder3   r=   ZTreeSpecrK   rN   r[   rE   r\   rl   rr   nnModuler|   r   r   r   r   <module>   sj   

"
1 
) 




'

& !