U
    zh                     @   s  d dl Z 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
mZmZmZmZ ddlmZmZmZmZ ejG dd dZejG dd dZejed	d
dZG dd dZdeddedddZedddZedddZedddZee dddZee dddZee dddZedddZ edd d!Z!edd"d#Z"ee dd$d%Z#de$e$eee$ ee$e$gdf f d&d'd(Z%d)d* Z&e$ee$ d+d,d-Z'e$d.d/d0Z(ejG d1d2 d2Z)e$ee$ d+d3d4Z*ee$ e$d5d6d7Z+ee) dd8d9d:Z,e-ee) d;d<d=Z.ee) e-d8d>d?Z/ee e$ee-e-f d@dAdBZ0e
e$ef e$dCdDdEZ1dddFdGZ2e3ej4Z5eddHdIdJZ6ee e$dKdLdMZ7dNdO Z8e-ee dPdQdRZ9ee ee) dSdTdUZ:ee dd8dVdWZ;ee ddSdXdYZ<ee dZd[d\Z=ee ddSd]d^Z>ee ee dSd_d`Z?ee ddSdadbZ@ee ddSdcddZAejBee ddedfdgZCee e$dSdhdiZDe$ddjdkZEdddldmZFdddndoZGeHddpdqZIdrds ZJe3ejKZLe3ejMZNe3ejOZPe3ejQZRe$ddtduZSdee dZdvdwZTdxdy ZUeeH ddzd{ZVdejBdd}d~ZWee eeH e
eHef eee ejBf dddZXdd ZYdee dddZZe[ Z\eHdddZ]ejBe^dddZ_dddZ`dS )    N)AnyCallablecastDictIteratorListOptionalTuple   )get_indexofpropagate_line_numsremove_extra_line_numsstacksize_analysisc                   @   sR   e Zd ZU ded< ded< ded< eed< eed< eddd	Zedd
dZdS )InstructionExnTabEntryInstructionstartendtargetdepthlastireturnc                 C   s:   d| j   d| j  d| j  d| j d| j dS )NzInstructionExnTabEntry(start=z, end=z	, target=z, depth=z, lasti=))r   short_inst_reprr   r   r   r   self r   W/var/www/html/venv/lib/python3.8/site-packages/torch/_dynamo/bytecode_transformation.py__repr__   s    8zInstructionExnTabEntry.__repr__c                 C   s<   | j |j ko:| j|jko:| j|jko:| j|jko:| j|jkS N)r   r   r   r   r   )r   or   r   r   __eq__"   s    



zInstructionExnTabEntry.__eq__N)	__name__
__module____qualname____annotations__intboolstrr   r!   r   r   r   r   r      s   
r   c                   @   s   e Zd ZU dZeed< eed< ee ed< eed< dZ	ee ed< dZ
ee ed< d	Zeed
< dZed ed< dZed  ed< dZee ed< edddZedddZedddZdS )r   z$A mutable version of dis.InstructionopcodeopnameargargvalNoffsetstarts_lineFis_jump_targetdis.Positions	positionsr   exn_tab_entryr   c                 C   s   t | S r   idr   r   r   r   __hash__<   s    zInstruction.__hash__c                 C   s   t | t |kS r   r3   )r   otherr   r   r   r!   ?   s    zInstruction.__eq__c                 C   s   d| j  d| j dS )NzInstruction(opname=z	, offset=r   )r*   r-   r   r   r   r   r   B   s    zInstruction.short_inst_repr)r"   r#   r$   __doc__r&   r%   r(   r   r   r-   r.   r/   r'   r1   r   r2   r   r5   r!   r   r   r   r   r   r   ,   s   
r   )ir   c                 C   s,   t | j| j| j| j| j| j| jt| dd S )Nr1   )	r   r)   r*   r+   r,   r-   r.   r/   getattr)r8   r   r   r   convert_instructionF   s    
r:   c                   @   s   e Zd ZedddZdS )_NotProvidedr   c                 C   s   dS )Nr;   r   r   r   r   r   r   T   s    z_NotProvided.__repr__N)r"   r#   r$   r(   r   r   r   r   r   r;   S   s   r;   )r+   r,   r   r   c                C   sp   | dkrt d|  |dk	|tk	 |dk	 }|dkr>t d|dk	rXt|tsXt dttj|  | |||dS )aS  
    At most one of `arg`, `argval`, and `target` can be not None/_NotProvided.
    This is to prevent ambiguity, e.g. does
        create_instruction("LOAD_CONST", 5)
    mean load the constant at co_consts[5], or load the constant 5?

    If `arg` is not provided, it will be computed during assembly from
    `argval` or `target`.

    Do not use for LOAD_GLOBAL - use create_load_global instead.
    Do not use for LOAD_ATTR - use create_load_attr instead.
    Do not use for LOAD_SUPER_ATTR - if you need to create this instruction,
        implement a create_load_super_attr function.
    LOAD_GLOBAL	LOAD_ATTRLOAD_SUPER_ATTRzcannot create_instruction with Nr
   z@only one of arg, argval, and target can be not None/_NotProvidedz#instruction arg must be int or None)r)   r*   r+   r,   r   )RuntimeErrorr;   
isinstancer&   r   disopmap)namer+   r,   r   Zcntr   r   r   create_instructionX   s         rE   c                 C   s   t jdkrdnd}t|| dS )N      JUMP_FORWARDJUMP_ABSOLUTEr   sysversion_inforE   )r   instr   r   r   create_jump_absolutex   s    rP   c                 C   s   t tjd d|| dS )a  
    `name` is the name of the global to be loaded.
    `push_null` specifies whether or not a NULL should be pushed to the stack
    before the global (Python 3.11+ only).

    Python 3.11 changed the LOAD_GLOBAL instruction in that the first bit of
    the instruction arg specifies whether a NULL should be pushed to the stack
    before the global. The remaining bits of the instruction arg contain the
    name index. See `create_call_function` for why this NULL is needed.

    The instruction's `arg` is actually computed when assembling the bytecode.
    For Python 3.11, push_null information is propagated through the arg.

    NOTE: we don't use create_instruction since LOAD_GLOBAL is the only instruction
    where both arg and argval need to be specified.
    r=   r)   r*   r+   r,   r   rB   rC   )rD   	push_nullr   r   r   create_load_global}   s    rT   c                   C   s   t jdkrtdddS tdS )NrF   COPYr
   r+   DUP_TOPrL   r   r   r   r   create_dup_top   s    
rX   c                 C   s   | dkrg S t jdkr,dd t| ddD S t jdk rN| dkrNtd|  d	t jd
k rp| dkrptd|  d| dkrtddddg| d   gS td| dgS )a  
    Returns a "simple" sequence of instructions that rotates TOS to the n-th
    position in the stack. For Python < 3.11, returns a single ROT_*
    instruction. If no such instruction exists, an error is raised and the
    caller is expected to generate an equivalent sequence of instructions.
    For Python >= 3.11, any rotation can be expressed as a simple sequence of
    swaps.
    r
   rF   c                 S   s   g | ]}t d |dqS )SWAPrV   )rE   .0r8   r   r   r   
<listcomp>   s     z create_rot_n.<locals>.<listcomp>)rG         zrotate z not supported for Python < 3.8rG   
      z  not supported for Python < 3.10ZROT_ZTWOZTHREEZFOUR   ZROT_NrV   )rM   rN   rangeAttributeErrorrE   nr   r   r   create_rot_n   s    	
rh   c                 C   sr   t jdkrdg }|r2|td |t| d  t jdk rN|td| d |td| d |S td| dgS )	a  
    Creates a sequence of instructions that makes a function call.

    `push_null` is used in Python 3.11+ only. It is used in codegen when
    a function call is intended to be made with the NULL + fn convention,
    and we know that the NULL has not been pushed yet. We will push a
    NULL and rotate it to the correct position immediately before making
    the function call.
    push_null should default to True unless you know you are calling a function
    that you codegen'd with a null already pushed, for example
    (assume `math` is available in the global scope),

    create_load_global("math", True)  # pushes a null
    create_load_attr("sqrt")
    create_instruction("LOAD_CONST", argval=25)
    create_call_function(1, False)
    rF   Z	PUSH_NULLrc   rG      PRECALLrV   CALLCALL_FUNCTION)rM   rN   appendrE   extendrh   )nargsrS   outputr   r   r   create_call_function   s    

rr   c                 C   sH   t jdkrtd| dgS t jdkr:td| dtd| dgS td| dgS )Nri   rl   rV   rF   rk   CALL_METHODrL   )rp   r   r   r   create_call_method   s    



rt   c                 C   s   t tjd dd| dS )Nr>   FrQ   rR   rD   r   r   r   create_load_attr   s    rv   c                 C   s,   t jdkr ttjd dd| dS td| dS )Nri   r>   TrQ   LOAD_METHODr,   )rM   rN   r   rB   rC   rE   ru   r   r   r   create_load_method   s    
ry   c                 C   s   t jdkrdnd}t|| dS )NrF   ZBEFORE_WITH
SETUP_WITHrK   rL   )r   r*   r   r   r   create_setup_with   s    r{   c                 C   s   t jdkrtd| dgS | dkr$g S td| d dtdtddd	td
tdtdtdtddd	tdtdtdftdtdtd| d dfS )NrF   rY   rV   r
   
BUILD_LISTrW   
LOAD_CONSTr]   rx   BINARY_SUBSCR	ROT_THREESTORE_SUBSCRreverser   POP_TOPUNPACK_SEQUENCE)rM   rN   rE   ry   rt   rf   r   r   r   create_swap   s(    


r   )linenobytenor   c                    s*   t jdk stg  fdd}|fS )z
    Used to create typing.CodeType.co_lnotab
    See https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt
    This is the internal format of the line number table if Python < 3.10
    r`   c                    st   | ks| krpt dt|  d}t dt|  d}|dksL|dksLt |7  |7 ||d@ f q d S )Nr      i   maxminAssertionErrorro   )
lineno_new
byteno_newbyte_offsetline_offsetr   r   lnotabr   r   update2  s    zlnotab_writer.<locals>.updaterM   rN   r   )r   r   r   r   r   r   lnotab_writer'  s    
r   c                    s`   t jdkrt jdk stg | ddfdd  fdd} fdd	}||fS )
z
    Used to create typing.CodeType.co_linetable
    See https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt
    This is the internal format of the line number table for Python 3.10
    r`   rF   r   c                    sl   | dks|dkrht dt| d}t dt|d}|dksD|dksDt| |8 } ||8 } ||d@ f q d S )Nr      ir   r   r   )byteno_deltalineno_deltar   r   )	linetabler   r   _updateK  s    z%linetable_310_writer.<locals>._updatec                    s&   | }| | |  | d S r   r   )r   r   r   )r   r   r   r   r   r   r   T  s
    
z$linetable_310_writer.<locals>.updatec                    s    |   d S r   r   )total_bytes)r   r   r   r   r   r   \  s    z!linetable_310_writer.<locals>.endr   )first_linenor   r   r   )r   r   r   r   r   r   linetable_310_writer?  s    	r   )rg   r   c                 C   sR   | dkst | d@ g}| dL } | dkrN|d  dO  < || d@  | dL } q|S )z~
    6-bit chunk encoding of an unsigned integer
    See https://github.com/python/cpython/blob/3.11/Objects/locations.md
    r   ?      r]   @   )r   rn   )rg   br   r   r   encode_varintb  s    

r   )r   c                    s2   t jdkstg |  dd fdd}|fS )z
    Used to create typing.CodeType.co_linetable
    See https://github.com/python/cpython/blob/3.11/Objects/locations.md
    This is the internal format of the line number table for Python 3.11
    rF   r0   r1   c                    s`    r
 j nd } fdd}|d kr*d}n| }||dkrR||d |d8 }q6||| d S )Nc                    s   d|  k rdksn t d}r|jd k	r|jd k	r|jd k	r|jd k	r| d| d  jj jd jd f}n d| d  | dk r|  d> dB } n| dK }  t|  |D ]} t| qd S )Nr   r^   r      r
      )r   r   
end_lineno
col_offsetend_col_offsetrn   ro   r   )deltasizeZother_varintsrg   )r   r1   r   r   r     s0    
z5linetable_311_writer.<locals>.update.<locals>._updater   r^   )r   )r1   	inst_sizer   r   r   r   r   r   r   r   {  s     

z$linetable_311_writer.<locals>.updater   )r   r   r   r   r   linetable_311_writerq  s
    .r   c                   @   s6   e Zd ZU eed< eed< eed< eed< eed< dS )ExceptionTableEntryr   r   r   r   r   N)r"   r#   r$   r&   r%   r'   r   r   r   r   r     s
   
r   c                 C   sp   | dkst | d@ g}| dL } | dkr>|| d@  | dL } q|  tt|d D ]}||  dO  < qV|S )zR
    Similar to `encode_varint`, but the 6-bit chunks are ordered in reverse.
    r   r   r   r
   r   )r   rn   r   rd   len)rg   r   r8   r   r   r   encode_exception_table_varint  s    

r   )
bytes_iterr   c                 C   s:   t | }|d@ }|d@ r6|dK }t | }||d@ O }q|S )z5
    Inverse of `encode_exception_table_varint`.
    r   r   r   )next)r   r   valr   r   r   decode_exception_table_varint  s    r   )tabr   c                 C   sf   t t| d D ]P}| | j| | jkr\| | j| |d  jk r\| |d  j| |d  jkstqdS )z
    Verifies that a list of ExceptionTableEntries will make a well-formed
    jump table: entries are non-empty, sorted, and do not overlap.
    r
   N)rd   r   r   r   r   )r   r8   r   r   r   check_exception_table  s    r   )exntabr   c           
      C   s   t | }g }zht|d }t|d }|| d }t|d }t|}|d? }t|d@ }	|t|||||	 qW n  tk
r   t| | Y S X dS )z
    Parse the exception table according to
    https://github.com/python/cpython/blob/3.11/Objects/exception_handling_notes.txt
    rc   r
   N)iterr   r'   rn   r   StopIterationr   )
r   Zexntab_iterr   r   lengthr   r   dlr   r   r   r   r   parse_exception_table  s    r   c                 C   s   g }| D ]}t |jd }|d  dO  < || |j|j d }|t |d  |t |jd  |jd> |j }|t | qt|S )zd
    Inverse of parse_exception_table - encodes list of exception
    table entries into bytes.
    rc   r      r
   )r   r   ro   r   r   r   r   bytes)r   r   entryZfirst_entryr   r   r   r   r   assemble_exception_table  s    
r   )instructionsfirstlinenor   c                 C   sv  g }t jdkrt|\}}d}t| D ]\}}|jdkrvd}|d7 }dD ]*}	| ||	  jdkrH| ||	  j|_ qqHnt|d | }d}||j| d}|jpd}
||j	|
d@ f t
t|d d D ]}|d qq&nt jd	k rt|\}}nt|\}}}| D ]B}|jd
k	r*||jt| |jp4d}
||j	|
d@ f q
t jd	krf|t| t|t|fS )z)Do the opposite of dis.get_instructions()rF   r   EXTENDED_ARGr
   r
   rc   rG   rc   r   )r   r   r`   N)rM   rN   r   	enumerater*   r1   instruction_sizer+   ro   r)   rd   r   r   r.   r   r   )r   r   coder   Zupdate_linenoZnum_extr8   rO   r   jr+   _r   r   r   r   assemble  s>    



r   )offset_to_instr-   c                 C   s2   dD ](}| ||  j tjkr| ||    S qdS )zU
    Get the instruction located at a given offset, accounting for EXTENDED_ARGs
    )r   rc   r_   r   Nr)   rB   r   )r   r-   rg   r   r   r   _get_instruction_by_offset1  s    r   c                 C   sB   dd | D }| D ]*}|j tjks.|j tjkrt||j|_qdS )z9Replace jump targets with pointers to make editing easierc                 S   s   i | ]}|j |qS r   )r-   r[   rO   r   r   r   
<dictcomp>=  s      z$virtualize_jumps.<locals>.<dictcomp>N)r)   rB   hasjabshasjrelr   r,   r   )r   Zjump_targetsrO   r   r   r   virtualize_jumps;  s    r   )instructionr   c                 C   sr   t jdk rtdd| jkr.| jdd| _n$d| jkrJ| jdd| _ntdtj| j | _| jt	ksnt
d S )NrF   z+Cannot flip jump direction in Python < 3.11FORWARDBACKWARDz-Instruction is not a forward or backward jump)rM   rN   r@   r*   replacere   rB   rC   r)   
_REL_JUMPSr   )r   r   r   r   flip_jump_directionG  s    


r   )r   idxc                 C   sD   | | }dD ]2}||kr:| ||  j tjkr:| ||  }q q@q|S )zp
    i.e. get the first EXTENDED_ARG instruction (if any) when targeting
    instructions[idx] with a jump.
    r   r   )r   r   r   r-   r   r   r   _get_instruction_frontT  s    r   c                 C   s>  t | }ttjttj}| D ]}|j|kr"t| ||j }|jtjkrt	j
dk rb|j|_n$t	j
dk r~t|jd |_ntdnt|j|j t| |_|jdk rt	j
dk rtd|j |_d|jkrt| n,|jdkrt	j
dkrd|jkrt| t	j
dkr"| jd  _|j|_d	|j |_q"d
S )zJFill in args for virtualized jump target after instructions may have movedr`   rF   rc   z+Python 3.11+ should not have absolute jumpsr   z*Got negative jump offset for Python < 3.11r   r   zto N)r   setrB   r   unionr   r)   r   r   rM   rN   r-   r+   r&   r@   r   r*   r   r,   argrepr)r   indexofZjumpsrO   r   r   r   r   devirtualize_jumpsb  s2    










r   )exn_tab_bytesr   c                    s   t | }dd |D t d t|zZ fdd}| \}}|D ]4}|j|jkrl| \}}qT|j|jkrPt||_qPW n t	k
r   Y nX dS )zDReplace exception table entries with pointers to make editing easierc                 S   s   i | ]}t t|j|qS r   )r   r&   r-   r   r   r   r   r     s     
 z.virtualize_exception_table.<locals>.<dictcomp>r   c                     sv   t }  tk r,  | jkr, d7  q dks8t d  }tt| jt|t| j| j| j	}| |fS )Nr
   r   )
r   r   r   r   r   r   r   r   r   r   )r   
end_offset
inst_entryZend_offset_idxZexn_tab_iterr   offsetsr   r   step  s     



z(virtualize_exception_table.<locals>.stepN)
r   sortedkeysr   r-   r   r   copyr2   r   )r   r   exn_tabr   r   r   rO   r   r   r   virtualize_exception_table  s    
r   )r   r   c                    s  i  t | }| D ]}|jrt| ||jj j}tt|jjjt|jj d }t| ||jj	 j}||f}||jj
|jjf}| kr | |kst| |< qt  dd d}dg g  fdd}	|D ]}rd d	 |d k r|	  q؈rd d |d   kr:|d	   kr:d d	 ks@n ttd d }
|
|d k rt|
|d d f d    |d | qԈr|	  qt S )
zMCompute exception table in list format from instructions with exn_tab_entriesrc   c                 S   s   | d | d  fS Nr   r
   r   tr   r   r   <lambda>      z)compute_exception_table.<locals>.<lambda>keyr   c                     sP   rL  } | d krLtt| d | d f |    | d d dS )zT
        Pop the key_stack and append an exception table entry if possible.
        r
   r   rc   N)poprn   r   r   r   Zexn_dictr   Z	key_stacknextir   r   r     s     z$compute_exception_table.<locals>.popr]   r
   )r   r2   r   r   r-   r   r&   r   r   r   r   r   r   r   r   r   rn   r   r   )r   r   rO   r   r   r   r   r   Zkeys_sortedr   leftr   r   r   compute_exception_table  sX     

 

B
r   c                 C   s   g }| D ]}||j  ||j f}|rB|d d |d k rB|  q |r|d d |d   kr||d   kr||d d ksn t|| qdS )z
    Checks `tab` is a properly sorted list of nested InstructionExnTabEntry's,
    i.e. no entries partially overlap.
    "Properly sorted" means entries are sorted by increasing starts, then
    decreasing ends.
    r]   r
   r   N)r   r   r   r   rn   )r   r   Zentry_stackr   r   r   r   r   !check_inst_exn_tab_entries_nested  s    	
<r   c                    s   t | }i  | D ]F}|jr||jj ||jj f}| krL|j | ksLt|j |< q fddt  dd dD }t|| |D ]4}t||j ||j d D ]}t		|| | _qqdS )z~
    Copies exception table entries to all instructions in an entry's range.
    Supports nested exception table entries.
    c                    s   g | ]} | qS r   r   )r[   r   entriesr   r   r\     s    z4propagate_inst_exn_table_entries.<locals>.<listcomp>c                 S   s   | d | d  fS r   r   r   r   r   r   r     r   z2propagate_inst_exn_table_entries.<locals>.<lambda>r   r
   N)
r   r2   r   r   r   r   r   r   rd   r   )r   r   rO   r   Zsorted_entriesr   r8   r   r   r    propagate_inst_exn_table_entries  s"    



r   r   c                 C   s   t | }t }t| D ]\}}|jrtjdks2tt|j|ksDt|t|j |j}|j	|ksht|j
|ksvt|j|kst||j	 |  kr||j
 ksn tqdS )aJ  
    Checks that exn_tab_entries of instructions are valid.
    An entry's start, end, and target must be in instructions.
    Instructions with an exn_tab_entry are located within
    the entry's start and end instructions.
    Instructions do not share exn_tab_entries.

    Implicitly checks for no duplicate instructions.
    rF   N)r   r   r   r2   rM   rN   r   r4   addr   r   r   )r   r   Zexn_tab_entry_setr8   rO   r   r   r   r    check_inst_exn_tab_entries_valid)  s    
r   c                 C   s   dd | D | d d < d S )Nc                 S   s   g | ]}|j tjkr|qS r   r   rZ   r   r   r   r\   B  s      z'strip_extended_args.<locals>.<listcomp>r   r   r   r   r   strip_extended_argsA  s    r   c                 C   sJ   t jdk stddd}| D ](}|j|kr||j |_tj|j |_q| S )zFLOAD_METHOD puts a NULL on the stack which causes issues, so remove itrF   r>   rm   )rw   rs   )rM   rN   r   r*   rB   rC   r)   )r   ZrewritesrO   r   r   r   remove_load_call_methodE  s    

r   c                 C   s   g }| D ]}| | d|jkrtdtd|jkd}|j|_|j|_tjdk rntd|jkr`dnd|j	d	}ntd
|j	d	}|j|_|j
r|j
j|kr||j
_t|j
|_
t|j
|_
tjd |_d|_d |_d |_|||g q|| d d < d S )NZ_NONEZIS_OPNOTrV   ri   r   ZPOP_JUMP_FORWARD_IF_TRUEZPOP_JUMP_BACKWARD_IF_TRUErK   POP_JUMP_IF_TRUEr}   )rn   r*   rE   r&   r+   r,   r1   rM   rN   r   r2   r   r   rB   rC   r)   ro   )r   	new_instsrO   Zis_opZjump_opr   r   r   remove_jump_if_noneP  s4    


r  c                 C   s   g }| D ]}| | |jdkrt|jdd}|jrL|jj|krL||j_t|j|_|j|_tj	d |_
d|_d|_d|_| | q|| d d < d S )N)ZBINARY_SLICEZSTORE_SLICEZSLICEZSUBSCRBUILD_SLICErc   )rn   r*   rE   r   r2   r   r   r1   rB   rC   r)   r+   r,   )r   r  rO   Zsubscr_instr   r   r   remove_binary_store_sliceq  s    

r  )r   r   r   c           	      C   sN  | j p
t | jpt  }t| js&dS g }t|D ]\}}|| |jdkr2|jdkr2||d  }|j	dkr2t
jdkr|jdkst
jdkrt
jdk r|jd	kst
jdk r2|jd
kr2d|kst|tddd | jd }||k r|td|d n|td|d d|_	d|_|jd	kr2||d  }d|_	d|_q2||dd< dS )z3convert super() with no args into explicit arg formNr=   superr
   r   ri   rl   rF   rk   rm   	__class__
LOAD_DEREFrx   	LOAD_FASTrc   )co_cellvarstupleco_freevarsr   co_varnamesr   rn   r*   r,   r+   rM   rN   r   rE   )	r   r   Zcell_and_freerq   r   rO   r   Z	first_varZ	call_instr   r   r   explicit_super  sH    


	


r  c                    sH  g   fdd}| D ]}|j tjkr.d|_n|jr|jdkr|d  td|jd? d  td|jd	? d  td|jd
? d n~|jr|jdkr|d  td|jd	? d  td|jd
? d n4|jr|jdkr|d  td|jd
? d  | qt t|  }|dks8t | dd< |S )z,Fill in correct argvals for EXTENDED_ARG opsc                    s.   t | D ] } r d jtjkr   qd S )Nr]   )rd   r)   rB   r   r   )rg   r   rq   r   r   maybe_pop_n  s    z&fix_extended_args.<locals>.maybe_pop_nr   i rG   r      rV      r^   i  rc   r   r
   N)r)   rB   r   r+   rn   rE   r   r   )r   r  rO   addedr   r  r   fix_extended_args  s,    
r  c                 C   s0   dd l }tjdkr,d|jjjj| j d  S dS )Nr   rF   rc   r
   )torchrM   rN   Z_CZ_dynamoZ
eval_frameZpy_opcode_cachesr)   )rO   r  r   r   r   r     s    
r   c                 C   s,   d}| D ]}|j |kst|t|7 }qd S Nr   )r-   r   r   r   r-   rO   r   r   r   check_offsets  s    r  c                 C   s$   d}| D ]}||_ |t|7 }qd S r  )r-   r   r  r   r   r   update_offsets  s    r  c                  G   sp   t ttt| }g }|gt|  dd t| d | d D g D ]}|ddd |D  qBdd	| S )
Nc                 S   s   g | ]\}}t ||kqS r   )r&   )r[   ar   r   r   r   r\     s     zdebug_bytes.<locals>.<listcomp>r]    c                 s   s   | ]}|d V  qdS )Z03Nr   )r[   xr   r   r   	<genexpr>  s     zdebug_bytes.<locals>.<genexpr>zbytes mismatch

)rd   r   mapr   listziprn   join)argsindexresultr+   r   r   r   debug_bytes  s    *r'  c                 C   sR   t | dd dd}| j|jks0tt| j|j| j|jksNtt| j|jdS )z<Make sure our assembler produces same bytes as we start withc                 S   s   d S r   r   )r  yr   r   r   r     r   zdebug_checks.<locals>.<lambda>T)safeN)transform_code_objectco_coder   r'  	co_lnotab)r   Zdoder   r   r   debug_checks  s    r-  c                 C   sH   t | d D ]\}}||kr|  S q| d  |f7  < t| d d S )N	co_constsr
   )r   r   )code_optionsr   r8   vr   r   r   get_const_index  s
    
r1  c           	   	      sp  dd t d D tdfdd}tjdk rv|d ks@tdd t d	 D }d
d t d d  D }nt|sti  t D ]4}z||}| |< W q tk
r   Y  qY qX q fddd	 D } fddd d  D }t	t
D ]dfdd} jdkr jd k	s<t jtk	sPttjdkr| jd> tt jd   _n| j _q jdkr, jd k	st jtk	sttjdkr| jd> tt jd   _n| j _q jdkr jd k	sPt jtk	sdt| jd> tt jd  d  _n҈ jtkr| rh| j  _n jtkr| rh| j _nv jtkr | rh| j  _nH jtkr jd krt j}|dks^t| _qd S )Nc                 S   s   i | ]\}}||qS r   r   r[   r   rD   r   r   r   r     s      zfix_vars.<locals>.<dictcomp>co_namesr   c                    s`   z|  }W nN t k
rZ   t }| <  d | f d< t d tksVtY nX |S )Nr3  )KeyErrorr   r   )rD   r   )r/  namesr   r   get_name_index
  s    z fix_vars.<locals>.get_name_indexrF   c                 S   s   i | ]\}}||qS r   r   r2  r   r   r   r     s      r  c                 S   s   i | ]\}}||qS r   r   r2  r   r   r   r     s    r
  r  c                    s   i | ]}| | qS r   r   r[   rD   allnamesr   r   r   &  s      c                    s   i | ]}| | qS r   r   r7  r8  r   r   r   '  s    c                      s     j tk	S r   )r,   r;   r   )r8   r   r   r   should_compute_arg-  s    z$fix_vars.<locals>.should_compute_argr=   r
   rc   r>   ri   r?   r   )r   r&   rM   rN   r   callable	itertoolscount
IndexErrorrd   r   r*   r+   r,   r;   r   r)   	HAS_LOCALHAS_NAMEHAS_FREE	HAS_CONSTr1  )	r   r/  varname_from_opargr6  varnamesZ	freenamesr   rD   r:  r   )r9  r/  r8   r   r5  r   fix_vars  s~    



rE  c                 C   sP   | D ]F}|j tk	r|jtks:|jtks:|jtks:|jtkr|jdkrd |_qd S )Nr<   )	r,   r;   r)   r?  r@  rA  rB  r*   r+   )r   rO   r   r   r   clear_instruction_argsa  s    
rF  c                  C   s   dg} |  d | ddddddd	d
ddg
 tjdkrB|  d |  d tjdkrb|  d n
|  d tjdkr|  d | ddg | S )Nco_argcountco_posonlyargcountco_kwonlyargcount
co_nlocalsco_stacksizeco_flagsr+  r.  r3  r  co_filenameco_namerF   Zco_qualnameco_firstlinenor`   co_linetabler,  co_exceptiontabler  r
  )rn   ro   rM   rN   )r   r   r   r   get_code_keysr  s:    







rR  Fc                    s\   t  } fdd|D }t|d |d ks0tt |}t| ||| t|||d S )Nc                    s   i | ]}|t  |qS r   )r9   r[   kr   r   r   r     s      z)transform_code_object.<locals>.<dictcomp>r  rJ  r
   )rR  r   r   cleaned_instructionsr   clean_and_assemble_instructions)r   Ztransformationsr)  r   r/  r   r   rU  r   r*    s    

r*  )r   r   r/  r   c                    s  t |  t d  d< d }tjdkrDtj fdd|D  }|j}t|  |d d}|rxt|  t	|  t
t| }qVt|  t|  d \}}tjd	k r| d
< n| d< | d< t|  d< t|dh t  dh ksttjdkrtt|  d< | tj fdd|D  fS )Nr  rJ  rF   c                    s   g | ]} | qS r   r   rS  r/  r   r   r\     s     z3clean_and_assemble_instructions.<locals>.<listcomp>)rC  TrO  r`   r,  rP  r+  rK  rH  rQ  c                    s   g | ]} | qS r   r   rS  rX  r   r   r\     s     )r   r   rM   rN   typesCodeTypeZ_varname_from_opargrE  r  r   r'   r  r   r   r   r   r   r   r   r   )r   r   r/  rC  Ztmp_codeZdirtybytecoder   r   rX  r   rW    s6    


rW  c                 C   s$   | D ]}|j dkr||j |_qd S )NZKW_NAMES)r*   r+   r,   )r   ZconstsrO   r   r   r   populate_kw_names_argval  s    
r\  c                 C   s   t ttt| }t| tjdkr>t|| j	 t
| j| t| t| |sxtjdk rdt| tjdk rxt| | tjdkrt| tjdkrt| t| t| |S )NrF   ri   )r!  r   r:   rB   get_instructionsr  rM   rN   r\  r.  r   rQ  r   r   r   r  r  r  r  r   )r   r)  r   r   r   r   rV    s&    





rV  c                 C   s   |  dt t S )Nr   )r   _unique_id_counterru   r   r   r   	unique_id  s    r_  )r   r   c                 C   s   d}| j |@ dkS )N    r   )rL  )r   Zco_generatorr   r   r   is_generator  s    ra  Tc           
      C   s  t | j}t| |rFt|D ]&\}}|jdkr||d d } qFq|D ]$}d|_|rJ|j|krJ||j |_qJ|rtjdkrg }|D ]D}|jdkrt	j
d |_d|_|| |td q|| q|}g }|D ]}|jdkr|| qt|dkr |d |d	 kr |d	 nt|dkr|d	 |d	 krzd
|d	 _t	j
d
 |d	 _d|d	 _t|d	 _|d	 n|td
 |D ]:}t|d	 }	|	j|_|	j|_|	j|_|	j|_|	j|_q|S )a  Generates bytecode from a template function `fn` for use in
    dynamo bytecode generation.

    For example, we can generate Python-version-independent bytecode
    for looping through a dictionary and copying the values to a new dictionary.

    def template(d1, d2):
        for k, v in d1.items():
            d2[k] = v


    or a try block:

    def template():
        try:
            dummy1
        except:
            dummy2
            raise
        dummy3

    Args:
        fn: a function template to generate bytecode from
        varname_map: a mapping of `fn`'s varnames to new names. This
            map will be applied to the generated bytecode's varnames.
            For example, local variables in `fn` can be replaced with
            new names that are generated by `OutputGraph.new_var`.
        noreturn: remove all RETURN_* bytecodes and replace them with a jump
            to the end of the bytecode.
        noprefix: remove prefix bytecodes (all bytecode before the first RESUME, inclusive).
    RESUMEr
   Nri   ZRETURN_CONSTr}   RETURN_VALUEr   r]   NOP)rV  __code__rF  r   r*   r.   r,   rM   rN   rB   rC   r)   rn   rE   r   r   r+   r;   rP   r   )
fnZvarname_mapZnoreturnZnoprefixZinstsr8   rO   r  ZreturnsZ	jump_instr   r   r   bytecode_from_template  sX     





 


rg  )r   )N)F)F)NTT)ar   dataclassesrB   r<  rM   rY  typingr   r   r   r   r   r   r   r	   Zbytecode_analysisr   r   r   r   	dataclassr   r   r:   r;   rE   rP   rT   rX   rh   rr   rt   rv   ry   r{   r   r&   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  rZ  r  r  r   r  r  r(   r'  r-  haslocalr?  hasnamer@  hasfreerA  hasconstrB  r1  rE  rF  rR  r*  rW  r\  rV  r=  r^  r_  r'   ra  rg  r   r   r   r   <module>   s   (   
+  #;*
	
&*K!&!



['  
)