o
    ߗiS                     @   s  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mZmZm	Z	 d dl
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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!m"Z" dd
l#m$Z$ ddl%m&Z&m'Z'm(Z(m)Z) ddl*m+Z+ ej,G dd dZ-G dd dZ.dS )    N)CounterDictListOptional   )utils)
add_push_nulladd_push_null_call_function_excreate_call_functioncreate_call_methodcreate_dup_topcreate_instructioncreate_load_constcreate_load_methodcreate_rot_nInstruction)unimplemented)
AttrSourceSource)is_safe_constantrot_n_helper)ValueMutationExistingVariableTracker)NNModuleVariable)NumpyNdarrayVariableSymNodeVariableTensorVariableUnspecializedPythonVariable)TensorWithTFOverrideVariablec                   @   s   e Zd ZU eed< eed< dS )GraphOutputEntryindexvariableN)__name__
__module____qualname__int__annotations__r    r'   r'   S/home/ubuntu/transcripts/venv/lib/python3.10/site-packages/torch/_dynamo/codegen.pyr   &   s   
 r   c                   @   s*  e Zd ZdZ					dfdeejj dee ddfddZ	dd	d
dZ
dd Zdd ZdgddZdhd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ee fd%d&Zdefd'd(Zdefd)d*Zdefd+d,Zdefd-d.Zdefd/d0Zdgdefd1d2Zdefd3d4Z defd5d6Z!d7d8 Z"d9d: Z#defd;d<Z$d=d> Z%d?d@ Z&defdAdBZ'dCdD Z(didFdGZ)dHdI Z*dJdK Z+dLdM Z,dNe-dOe.fdPdQZ/dRdS Z0dTdU Z1dVdW Z2	EdidXedYe3j4dOe.fdZd[Z5defd\d]Z6dXeddfd^d_Z7djd`daZ8dee fdbdcZ9defdddeZ:dS )k	PyCodegenz<
    Helper class uses for constructing Python bytecode
    Nrootgraph_output_varreturnc                 C   sn   || _ d | _t | _i | _g | _|pi | _|| _|| _	| jj
j| _| jj| _| jj
j| _d| _|p3i | _d S )NT)r*   top_of_stackcollectionsr   usesgraph_outputs_outputtempvarstxr+   outputcode_optionscell_and_freevarsnew_varvalue_from_sourceoverridden_sources)selfr3   r*   r+   r2   r9   r'   r'   r(   __init__1   s   


zPyCodegen.__init__T)r8   c                C   s4   | j }|  j |M  _ z| | W || _ d S || _ w N)r8   foreach)r:   stack_valuesr8   prevr'   r'   r(   restore_stackN   s
   zPyCodegen.restore_stackc                 C   s   dd | j  D S )Nc                 S   s   g | ]}|j qS r'   )r!   .0xr'   r'   r(   
<listcomp>W   s    z/PyCodegen.graph_output_vars.<locals>.<listcomp>)r0   valuesr:   r'   r'   r(   graph_output_varsV      zPyCodegen.graph_output_varsc                 C   s$   | | }|d u sJ d| d S )Nzreconstruct!=None )reconstruct)r:   valueresr'   r'   r(   call_reconstructY   s   
zPyCodegen.call_reconstructFc                 C   s|   t | j}tjdk r|   |  | j|d }| j|d= |r)| jt| n| jt| tjdkr<|   dS dS )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)lenr1   sysversion_info	clear_tosextendr	   r   )r:   gen_fncall_function_exold_lenadded_instsr'   r'   r(   r   ]   s   


zPyCodegen.add_push_nullc                    sl  t |trj||}|   dS t |tsJ jj |rKj	|u r3
t  dS j|durK
j|  |_	dS |jdur`|r`t |jts[jr`|jS | rvt| rv
|  n;t |tr|fdd   j 
j|jdd tdd nt |t r|! t"krڈjj#sڈ|$jt%j& fdd	}| td
d nt |t't t(t)fr3|t |t)r	fdd   j tdd nt |t(r*|j*r* fdd	}| td
d n  j n~t |t+rz|j,-d}|d
 j.d v rZ
|d
  |dd }nj/dusbJ 
0j/ |D ]}
1| qmn7j2|  d7  < z| W n t3y   t4d|  Y nw |r|jv rj
t  5| |_	dS )a2  
        Generate code such that top-of-stack (TOS) is set to value.

        `allow_cache` is used to determine whether the following could happen,
        when `value` is a `VariableTracker`:
        1. if `value` was codegen-ed previously with `allow_cache=True` and
           without using source, reuse the generated code by loading from top
           of stack or tempvars.
        2. emit code based on `value.source` to handle aliasing.

        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, if we don't codegen `value` based
           on source or cache/top-of-stack reuse; in other words, if we codegen
           as if `value` is modelling some brand new python value.
        Nc                           tjdS )Nto_subclassload_import_fromr   r"   r'   rF   r'   r(   <lambda>       z$PyCodegen.__call__.<locals>.<lambda>Tadd   Fc                      $      j d d S Nitemload_graph_outputr    appendcreate_load_attrr'   r0   graph_outputs_keyr4   r:   r'   r(   rU         z"PyCodegen.__call__.<locals>.gen_fnr   c                      rY   )Nto_numpy_helperr[   r'   rF   r'   r(   r]      r^   r   c                      rb   rc   re   r'   ri   r'   r(   rU      rk   .co_varnameszreconstruct: )6
isinstancer   r9   getrL   rS   r   r1   r0   r-   rg   r   r2   create_loadsourcemutation_typer   r8   is_python_constantr   as_python_constantr   r   add_graph_outputr   rf   r    create_load_globalglobal_mangled_class_namer3   rT   r
   r   python_typefloatexport	as_tensortorchfloat64r   r   r   need_unwrapr   
module_keysplitr5   r*   create_load_const_uncheckedrh   r/   NotImplementedErrorr   	add_cache)r:   rJ   allow_cacherr   rU   partspartr'   ri   r(   __call__z   s   










	



zPyCodegen.__call__c                 C   s0   t | }|| jvrtt| j|| j|< |S r<   )idas_proxyr0   r   rP   )r:   rJ   rj   r'   r'   r(   rv     s   


zPyCodegen.add_graph_outputc                 C   s:   | j }|| | j || | |td d S )NBINARY_SUBSCR)r1   rg   rq   r+   r   r   )r:   r    r4   r'   r'   r(   rf     s   zPyCodegen.load_graph_outputc                 C   s(   |   }|| j|< | j| | d S r<   )r7   r2   r1   rg   create_store)r:   rJ   varr'   r'   r(   r     s   
zPyCodegen.add_cachec                 C   s   |D ]}| | qd S r<   r'   )r:   itemsir'   r'   r(   r=   #  s   
zPyCodegen.foreachc                 C   sP   t dd|}| jj}||v rt|| t|ksJ n|||< | j|ddgS )zStore value in a new globalz[^a-zA-Z0-9_]+_Tr_   )resubr3   	f_globalsr   rw   )r:   namerJ   r   r'   r'   r(   setup_globally_cached'  s   zPyCodegen.setup_globally_cachedc                 C   s
   d | _ d S r<   )r-   rF   r'   r'   r(   rS   1  s   
zPyCodegen.clear_tosc                 C   s&   t |tsJ | j| |   d S r<   )ro   r   r1   rg   rS   )r:   instr'   r'   r(   append_output4  s   zPyCodegen.append_outputc                 C   s.   t dd |D sJ | j| |   d S )Nc                 s   s    | ]}t |tV  qd S r<   )ro   r   rA   r'   r'   r(   	<genexpr>:  s    z*PyCodegen.extend_output.<locals>.<genexpr>)allr1   rT   rS   )r:   instsr'   r'   r(   extend_output9  s   zPyCodegen.extend_outputc                 C   s   | j S r<   )r1   rF   r'   r'   r(   get_instructions>  s   zPyCodegen.get_instructionsc                 C   (   || j d v sJ | dtd|dS )Nrn    missing	LOAD_FASTargvalr5   r   r:   r   r'   r'   r(   rq   A     zPyCodegen.create_loadc                 C   s.   ||   v sJ tjdkrdnd}t||dS )NrM   r   LOAD_CLOSUREr   )r6   rQ   rR   r   )r:   r   	inst_namer'   r'   r(   create_load_closureE  s   zPyCodegen.create_load_closurec                 C      ||   v sJ td|dS )N
LOAD_DEREFr   r6   r   r   r'   r'   r(   create_load_derefJ     zPyCodegen.create_load_derefc                 C   r   )Nrn   r   
STORE_FASTr   r   r   r'   r'   r(   r   N  r   zPyCodegen.create_storec                 C   r   )NSTORE_DEREFr   r   r   r'   r'   r(   create_store_derefR  r   zPyCodegen.create_store_derefc                 C   s:   |r	| j j| || jd v sJ | dtd|dS )Nco_namesz not in co_namesLOAD_GLOBALr   )r3   r4   update_co_namesr5   r   )r:   r   r`   r'   r'   r(   rw   V  s   zPyCodegen.create_load_globalc                 C   s   t |S r<   r   r:   rJ   r'   r'   r(   r   \  s   zPyCodegen.create_load_constc                 C   s   t |ddS )NF)checkedr   r   r'   r'   r(   r   _     z%PyCodegen.create_load_const_uncheckedc                 C   s    | j j| | t| d S r<   )r3   r4   r   r   r   r   r'   r'   r(   load_methodb  s   zPyCodegen.load_methodc                 C   s   |  t| d S r<   )r   r   )r:   nargsr'   r'   r(   call_methodf     zPyCodegen.call_methodc                 C   .   || j d vr| j d  |f7  < td|dS )Nr   	LOAD_ATTRr   r   r   r'   r'   r(   rh   i     zPyCodegen.create_load_attrc                 C      |  | | d S r<   )r   rh   r   r'   r'   r(   	load_attrn  rH   zPyCodegen.load_attrc                    s    fdd| dD S )Nc                    s   g | ]}  |qS r'   )rh   )rB   r   rF   r'   r(   rD   r  s    z/PyCodegen.create_load_attrs.<locals>.<listcomp>rm   )r   )r:   namesr'   rF   r(   create_load_attrsq  s   zPyCodegen.create_load_attrsc                 C   r   )Nr   
STORE_ATTRr   r   r   r'   r'   r(   create_store_attrt  r   zPyCodegen.create_store_attrc                 C   r   r<   )r   r   r   r'   r'   r(   
store_attry  rH   zPyCodegen.store_attrr   c                 C   s   g }|r.t jdkr.|t| j|dd |dkr,|g | |d | |d  |S || j|ddg| |d  |S )z6Load the global fn_name on the stack num_on_stack downrN      Tr_   r   ra   r   )rQ   rR   rT   r   rw   rot_n)r:   fn_name	push_nullnum_on_stackr4   r'   r'   r(   load_function_name|  s&   zPyCodegen.load_function_namec                 C   sX   zt |W S  ty+   td|d| t|gt dtdddtd|d Y S w )NBUILD_TUPLEargra   CALL_FUNCTION_EXr   UNPACK_SEQUENCE)r   AttributeErrorr   r   r   )r:   nr'   r'   r(   r     s   



zPyCodegen.rot_nc                 C   sL   t jdksJ | dd gt jdkrtdddfndtd	d
tdS )Nr   c                   S   s   d S r<   r'   r'   r'   r'   r(   r]     s    z$PyCodegen.pop_null.<locals>.<lambda>rM   SWAPra   r   r'   r   FPOP_TOP)rQ   rR   r   r   r
   rF   r'   r'   r(   pop_null  s   
	zPyCodegen.pop_nullc                 C   s   |  td d S )Nr   )r   r   rF   r'   r'   r(   pop_top  r   zPyCodegen.pop_topr   r   c                 C   s   |  t||d d S )N)r   )r   r
   )r:   r   r   r'   r'   r(   call_function  s   zPyCodegen.call_functionc                 C   s   |  t  d S r<   )r   r   rF   r'   r'   r(   dup_top  s   zPyCodegen.dup_topc                 C   r   r<   )r   r   r:   varnamer'   r'   r(   store  rH   zPyCodegen.storec                 C   r   r<   )r   r   r   r'   r'   r(   
load_deref  rH   zPyCodegen.load_derefr   codec                    s    j sJ j fdd}|r5tjdkr5| |d  |d  n|  |d    d S )Nc                     s   D ]} |   v sJ |  qtdtd   tjdk r5 tjdkrItdtdddg d S tddd d S )Nr   r   r   rM   MAKE_FUNCTIONSET_FUNCTION_ATTRIBUTE   )	r6   rg   r   r   rP   r   rQ   rR   rT   )r   r   r   freevarsr4   r:   r'   r(   rU     s   


z4PyCodegen.make_function_with_closure.<locals>.gen_fnr   ra   r   )co_freevarsr1   rQ   rR   r   rT   r   rS   )r:   r   r   r   r   rU   r'   r   r(   make_function_with_closure  s   
z$PyCodegen.make_function_with_closurec                 C   sd   | j j}|j}tdd|j}||d|u r| j|ddS d| }| j j||}| j|ddS )zT
        Generate a LOAD_GLOBAL instruction to fetch a given python module.
        z^.*[.] NTr_   
___module_)	r3   r4   global_scoper   r   r"   rp   rw   install_global_by_id)r:   modr4   r   r   prefixglobal_namer'   r'   r(   create_load_python_module  s   
z#PyCodegen.create_load_python_modulec                    s|      |d  jjj}|D ]!}|jr,  fdd  |   tdd q | q  tt	|d dS )z2Call the generated code function stored in fn_nameTc                      s      t dgS )N_as_tensor_fullprec)r   r   r}   rh   r'   rF   r'   r(   r]     s
    z4PyCodegen.make_call_generated_code.<locals>.<lambda>r   FN)
r   r   r3   r4   	graphargspass_arg_as_tensorr   rL   r
   rP   )r:   r   r   r   r'   rF   r(   make_call_generated_code  s   


z"PyCodegen.make_call_generated_codec                 C   s   | t | j|| d S r<   )r   r3   import_source)r:   module_nameobject_namer'   r'   r(   r\     s   zPyCodegen.load_import_fromc                 C   s   t jdkr&t||}|d jdksJ |d| | td|d|d< |S t jdkrUt||}t jdkr:d}d}nd}d	}|| j|ksGJ td
|d}||| |S | |td|dgS )NrM   CALLCALL_KWr   r   )rN      PRECALLKW_NAMESr   CALL_FUNCTION_KW)rQ   rR   r
   opnameinsertr   r   )r:   r   kw_namesr   r4   idxexpected_instkw_names_instr'   r'   r(   create_call_function_kw	  s(   





z!PyCodegen.create_call_function_kwc                 C   s   t d|dS )NDELETE_FASTr   )r   r   r'   r'   r(   create_delete!  r   zPyCodegen.create_delete)NNNNN)F)T)r   )r,   N);r"   r#   r$   __doc__r   r}   nnModulestrr;   r@   rG   rL   r   r   rv   rf   r   r=   r   rS   r   r   r   r   r   rq   r   r   r   r   rw   r   r   r   r   rh   r   r   r   r   r   r   r   r   r%   boolr   r   r   r   typesCodeTyper   r   r   r\   r  r  r'   r'   r'   r(   r)   ,   s    



 


&
r)   )/r.   dataclassesr   rQ   r
  typingr   r   r   r   torch.nnr}   r   r   bytecode_transformationr   r	   r
   r   r   r   r   r   r   r   excr   rr   r   r   r   r   variables.baser   r   variables.nn_moduler   variables.tensorr   r   r   r   variables.torch_functionr   	dataclassr   r)   r'   r'   r'   r(   <module>   s&   0