o
    Zh                     @   s,  d Z 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Zddlm	Z	m
Z
 ddlmZmZmZ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ejG d
d dZeejG dd dZejdkrtdejdefddZnejdkrdejdefddZn
dejdefddZG dd dZejdkrdd Z nejdkrdd Z ndd Z dedddefddZ!defd d!Z"ddefd#d$Z#defd%d&Z$de%e fd'd(Z&d)eee%e f de%e fd*d+Z'd)eee%e f de%e fd,d-Z(de%e fd.d/Z)de%e fd0d1Z*defd2d3Z+defd4d5Z,de%e fd6d7Z-	dd8e.d9e.de/e%e. ee.e.gdf f fd:d;Z0d<d= Z1d>e.de%e. fd?d@Z2dAe.fdBdCZ3eejG dDdE dEZ4d>e.de%e. fdFdGZ5dHe	e. de.fdIdJZ6dKe%e4 ddfdLdMZ7dNe8de%e4 fdOdPZ9dKe%e4 de8fdQdRZ:dSe%e dTe.de/e8e8f fdUdVZ;dWe<e.ef dXe.fdYdZZ=dd[d\Z>e?ej@ZAd]eddfd^d_ZBdSe%e d`e.fdadbZCdcdd ZDdee8dSe%e fdfdgZEdSe%e de%e4 fdhdiZFdKe%e ddfdjdkZGdSe%e ddfdldmZHdSe%e fdndoZIdSe%e ddfdpdqZJdrds ZKdSe%e de%e fdtduZLdSe%e ddfdvdwZMdSe%e ddfdxdyZNdzd{d|d}ZOdSe%e ddfd~dZPdejQdSe%e ddfddZRdSe%e de.fddZSde.fddZTdddZUdddZVdeWfddZXdd ZYe?ejZZ[e?ej\Z]e?ej^Z_e?ej`Zade.fddZbddSe%e fddZcdd Zdde%eW fddZeddejQfddZfdSe%e de%eW de<eWef de/e%e ejQf fddZgdd Zhdde%e fddZidd Zjejkdde
e fddZlem ZndeWfddZodejQdepfddZqdddZrdS )a  
This module provides utilities for analyzing, transforming and manipulating Python bytecode.
It includes functionality for:
- Converting between different bytecode formats and versions
- Virtualizing jumps and managing jump targets
- Handling exception tables and their entries
- Managing instruction offsets and extended arguments
- Providing a clean API for bytecode modification and transformation
- Supporting Python version-specific bytecode features
- Generating bytecode from template functions

The module is designed to work across different Python versions (3.7+) and handles
version-specific bytecode differences transparently.
    N)IteratorSequence)AnyCallablecastOptionalUnion   )dataclass_slots   )get_indexofpropagate_line_numsremove_extra_line_numsstacksize_analysis)is_safe_constantc                   @   sR   e Zd ZU ded< ded< ded< eed< eed< defdd	Zdef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   T/var/www/auris/lib/python3.10/site-packages/torch/_dynamo/bytecode_transformation.py__repr__/   s   zInstructionExnTabEntry.__repr__c                 C   s<   | j |j u o| j|ju o| j|ju o| j|jko| j|jkS N)r   r   r   r   r   )r   or   r   r   __eq__7   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< dZee ed< defddZdefddZdefddZ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_entryargreprr   c                 C   s   t | S r    idr   r   r   r   __hash__S      zInstruction.__hash__c                 C   s   t | t |kS r    r5   r   otherr   r   r   r"   V   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   Y   s   zInstruction.short_inst_reprr:   c                 C   s   |j | _ |j| _d S r    )r/   r2   r9   r   r   r   copy_positions\   s   zInstruction.copy_positions)r:   r   r   N)r#   r$   r%   __doc__r'   r&   r)   r   r   r.   r/   r0   r(   r2   r   r3   r   r4   r7   r"   r   r;   r   r   r   r   r   A   s"   
 r         ir   c              	   C   &   t | j| j| j| j| j| j| j| jS r    )	r   r*   r+   r,   r-   r.   line_numberr0   r2   r@   r   r   r   convert_instructionc      rD   r>      c              	   C   rA   r    )	r   r*   r+   r,   r-   r.   r/   r0   r2   rC   r   r   r   rD   q   rE   c              	   C   s$   t | j| j| j| j| j| j| jd S r    )r   r*   r+   r,   r-   r.   r/   r0   rC   r   r   r   rD      s   c                   @   s   e Zd ZdefddZdS )_NotProvidedr   c                 C      dS )NrH   r   r   r   r   r   r         z_NotProvided.__repr__N)r#   r$   r%   r)   r   r   r   r   r   rH      s    rH   r>      c                 C   s   | dv S )N)	LOAD_ATTRLOAD_GLOBALLOAD_SUPER_ATTRr   namer   r   r   inst_has_op_bits   r8   rR   c                 C   s   | dkS )NrN   r   rP   r   r   r   rR      r8   c                 C   rI   )NFr   rP   r   r   r   rR      rJ   )r,   r-   r   c                C   s   t | r|durtd|du rd}n|du|tu |du }|dkr'td|dur4t|ts4tdttj|  | |||dS )a  
    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`.

    Bits in the args of instructions LOAD_GLOBAL, LOAD_ATTR (3.12+), and LOAD_SUPER_ATTR
    modify the behavior of the instruction. In this case, we allow both `arg`
    and `argval` to be set. The value of `arg` here is expected to be the value of
    the op bits and the true value of `arg` will be computed during assembly.
    If `arg` is not set, the bits are assumed to be 0.
    Nz*target cannot be specified for instructionr   r   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   )rR   RuntimeErrorrH   
isinstancer'   r   disopmap)rQ   r,   r-   r   Zcntr   r   r   create_instruction   s    rW   c                 C      t jdkrdnd}t|| dS )NrF   JUMP_FORWARDJUMP_ABSOLUTEr   sysversion_inforW   )r   instr   r   r   create_jump_absolute      r`   Tc                 C   s&   |rt | sJ d|  td| dS )z
    In general we should only create `LOAD_CONST` for immutable objects, but
    sometimes it's convenient _and safe_ for Dynamo create `LOAD_CONST` for
    mutable objects. In such cases, use `checked=False`.
    zunsafe constant 
LOAD_CONSTr-   )r   rW   )valcheckedr   r   r   create_load_const   s   rf   c                   C   s   t jdkrtdddS tdS )NrF   COPYr   r,   DUP_TOPr\   r   r   r   r   create_dup_top   s   
rj   c                 C   s~   | dkrg S t jdkrdd t| ddD S t jdk r'| dkr'td|  d	| d
kr8tdg d| 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 )SWAPrh   )rW   .0r@   r   r   r   
<listcomp>       z create_rot_n.<locals>.<listcomp>r>   
      zrotate z  not supported for Python < 3.10   ZROT_)ZTWOZTHREEZFOURr	   ROT_Nrh   )r]   r^   rangeAttributeErrorrW   nr   r   r   create_rot_n   s   	
rz   inst_or_instsc                    s
  t | tr	| g n|   fdd} fdd}tjdkr6t d jr-|ds-|d  S  tdg   S tjdkrft d jrL|dsL|d  S  d	 jd
kr]|d	s]|d	  S tdg    S tjdkrt d	 jr||d	s||d	  S tdg    S )a  
    Appends or prepends a PUSH_NULL instruction to `inst_or_insts`,
    depending on Python version. Used when you know that
    `inst_or_insts` generates a callable that will be called.

    NOTE: Assumes `inst_or_insts` is a single instruction or sequence of
    instructions that pushes exactly 1 object to the stack that is to
    be called. It is important that you include ALL instructions that
    construct the callable - not just the first instruction/a prefix.

    Will attempt to use the NULL push bit for instructions
    with such bits (LOAD_GLOBAL 3.11+, LOAD_ATTR 3.12+, LOAD_SUPER_ATTR).
    In this case, instructions WILL be modified.
    c                    s$    |  j d us	J  |  j d@ dkS Nr   rh   idxinstsr   r   inst_has_bit_set  s   z'add_push_null.<locals>.inst_has_bit_setc                    s(    |  j d us	J  |   j dO  _ d S r|   rh   r}   r   r   r   set_inst_bit  s   z#add_push_null.<locals>.set_inst_bitr=   rp   	PUSH_NULLrK   r   rN   rF   )rT   r   r]   r^   rR   r+   rW   )r{   r   r   r   r   r   add_push_null   s4   


	
r   c                 C   s   t | tr	| g}n| }tjdk r|S tjdkrdnd}|| jdkr?|| jdus+J || jd@ dkr?||  jdO  _|S tjdkrM|tdg }|S tdg| }|S )	zLike add_push_null, but the low bit of LOAD_ATTR/LOAD_SUPER_ATTR
    is not set, due to an expected CALL_FUNCTION_EX instruction.
    rF   r=   rp   r   rN   Nr   r   )rT   r   r]   r^   r+   r,   rW   )r{   r   r~   r   r   r   add_push_null_call_function_ex3  s    


r   c                 C   s   t jdkr=g }|r$|td t jdkr| d n| d }|t| t jdk r2|td| d |td	| d |S td
| dgS )aS  
    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 be True if no NULL is pushed for the callable.
    Conversely, `push_null` should be False if a NULL was pushed for the callable.
    Prefer using `push_null=False` when possible since we will not need to rotate
    NULL to the right place, which is less efficient.

    Generally, you should codegen a function by using `add_push_null` then
    `create_call_function` with `push_null=False`.

    Example of when to set push_null False:

    insts = [
        create_instruction("LOAD_GLOBAL", argval="torch"),
        create_instruction("LOAD_ATTR", argval="nn"),
        create_instruction("LOAD_ATTR", argval="functional"),
        create_instruction("LOAD_ATTR", argval="relu"),
    ]
    insts = add_push_null(insts)
    insts.append(create_instruction("LOAD_FAST", argval="x"))
    insts.extend(create_call_function(1, False))

    Example of when to set push_null True:

    insts = [create_instruction("LOAD_FAST", x)]
    for should_wrap, wrapper_name in wrappers:
        if should_wrap:
            insts.extend([
                create_instruction("LOAD_GLOBAL", argval="wrapper1"),
                create_instruction("SWAP", arg=2),
                *create_call_function(1, True),
            )
    rF   r   r=   r   r	   rK   PRECALLrh   CALLCALL_FUNCTION)r]   r^   appendrW   extendrz   )nargsZ	push_nulloutputZrotsr   r   r   create_call_functionP  s   
)
r   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 )NrK   r   rh   rF   r   CALL_METHODr\   )r   r   r   r   create_call_method  s   



r   c                 C   s$   t jdkrtdd| dS td| dS )NrK   rM   r   )r,   r-   LOAD_METHODrc   r\   rP   r   r   r   create_load_method  s   
r   c                 C   rX   )NrF   ZBEFORE_WITH
SETUP_WITHr[   r\   )r   r+   r   r   r   create_setup_with  ra   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gtdtdtd| d dS )NrF   rk   rh   r   
BUILD_LISTri   rb   rp   rc   BINARY_SUBSCR	ROT_THREESTORE_SUBSCRreverser   POP_TOPUNPACK_SEQUENCE)r]   r^   rW   r   r   rx   r   r   r   create_swap  s.   


r   linenobytenoc                    s*   t jdk sJ 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
    rq   c                    s   | ks| krAt dt|  d}t dt|  d}|dks&|dks&J  |7  |7 ||d@ f | ks| ksd S d S )Nr      i   maxminr   )
lineno_new
byteno_newbyte_offsetline_offsetr   r   lnotabr   r   update  s   zlnotab_writer.<locals>.updater]   r^   )r   r   r   r   r   r   lnotab_writer  s   
r   c                    s`   t jdkr
t jdk sJ 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
    rq   rF   r   c                    s~   | dks|dkr=t dt| d}t dt|d}|dks"|dks"J | |8 } ||8 } ||d@ f | dks|dksd S d S )Nr      ir   r   r   )byteno_deltalineno_deltar   r   )	linetabler   r   _update  s   z%linetable_310_writer.<locals>._updatec                    s&   | }| | |  | d S r    r   )r   r   r   )r   r   r   r   r   r   r     s
   
z$linetable_310_writer.<locals>.updatec                    s    |   d S r    r   )total_bytes)r   r   r   r   r   r        z!linetable_310_writer.<locals>.endr   )first_linenor   r   r   )r   r   r   r   r   r   linetable_310_writer  s   	
r   ry   c                 C   sX   | dksJ | d@ g}| dL } | dkr*|d  dO  < | | d@  | dL } | dks|S )z~
    6-bit chunk encoding of an unsigned integer
    See https://github.com/python/cpython/blob/3.11/Objects/locations.md
    r   ?      rp   @   )r   )ry   br   r   r   encode_varint  s   
r   r   c                    s.   t jdksJ g |  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   r2   r1   c                    sf    r j nd } fdd}|d u rd}n| }||dkr,||d |d8 }|dks||| d S )Nc                    s   d|  k rdksJ  J d}r?j d ur?jd ur?jd ur?jd ur? d| d  jj  jd jd f}n	 d| d  | dk rT|  d> dB } n| dK }  t|  |D ]	} t| qad S )Nr      r      r      )r   
end_lineno
col_offsetend_col_offsetr   r   r   )deltasizeZother_varintsry   )r   r2   r   r   r      s*   




z5linetable_311_writer.<locals>.update.<locals>._updater   r   )r   )r2   	inst_sizer   r   r   r   r   )r2   r   r     s    
z$linetable_311_writer.<locals>.updateN)r2   r1   r   )r   r   r   r   r   linetable_311_writer  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   M  s   
 r   c                 C   sv   | dksJ | d@ g}| dL } | dkr"| | d@  | dL } | dks|  tt|d D ]
}||  dO  < q.|S )zR
    Similar to `encode_varint`, but the 6-bit chunks are ordered in reverse.
    r   r   r   r   r   )r   r   rv   len)ry   r   r@   r   r   r   encode_exception_table_varintW  s   
r   
bytes_iterc                 C   s@   t | }|d@ }|d@ r|dK }t | }||d@ O }|d@ s|S )z5
    Inverse of `encode_exception_table_varint`.
    r   r   r   )next)r   r   rd   r   r   r   decode_exception_table_varintg  s   r   tabc                 C   sf   t t| d D ](}| | j| | jkr.| | j| |d  jk r.| |d  j| |d  jks0J 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)rv   r   r   r   )r   r@   r   r   r   check_exception_tablet  s
   "r   exntabc           
      C   s   t | }g }z3	 t|d }t|d }|| d }t|d }t|}|d? }t|d@ }	|t|||||	 q tyH   t| | Y S w )z
    Parse the exception table according to
    https://github.com/python/cpython/blob/3.11/Objects/exception_handling_notes.txt
    Tr	   r   )iterr   r(   r   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.
    r	   r      r   )r   r   r   r   r   r   r   bytes)r   r   entryZfirst_entryr   r   r   r   r   assemble_exception_table  s   
r   instructionsfirstlinenoc                 C   sn  g }t jdkrpt|\}}d}t| D ][\}}|jdkr;d}|d7 }dD ]}	| ||	  jdkr9| ||	  j|_ nq$n
t|d | }d}||j| d}|jpQd}
||j	|
d@ f t
t|d d D ]}|d qfqn?t jd	k r|t|\}}nt|\}}}| D ]}|jd
ur||jt| |jpd}
||j	|
d@ f qt jd	kr|t| t|t|fS )z)Do the opposite of dis.get_instructions()rF   r   EXTENDED_ARGr   r   r	   r>   r	   r   )r   r   rq   N)r]   r^   r   	enumerater+   r2   instruction_sizer,   r   r*   rv   r   r   r/   r   r   )r   r   coder   Zupdate_linenoZnum_extr@   r_   r   jr,   _r   r   r   r   assemble  sF   






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   r	   rt   r   Nr*   rU   r   )r   r.   ry   r   r   r   _get_instruction_by_offset  s
   r   c                 C   sB   dd | D }| D ]}|j tjv s|j tjv rt||j|_q	dS )z9Replace jump targets with pointers to make editing easierc                 S   s   i | ]}|j |qS r   )r.   rm   r_   r   r   r   
<dictcomp>      z$virtualize_jumps.<locals>.<dictcomp>N)r*   rU   hasjabshasjrelr   r-   r   )r   Zjump_targetsr_   r   r   r   virtualize_jumps  s   r   instructionc                 C   sr   t jdk r	tdd| jv r| jdd| _nd| jv r%| jdd| _ntdtj| j | _| jt	v s7J d S )NrF   z+Cannot flip jump direction in Python < 3.11FORWARDBACKWARDz-Instruction is not a forward or backward jump)
r]   r^   rS   r+   replacerw   rU   rV   r*   
_REL_JUMPS)r   r   r   r   flip_jump_direction  s   


r   r~   c                 C   sD   | | }dD ]}||kr| ||  j tjkr| ||  }q |S |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_front  s   r   c                 C   sN  t tjt tj}| D ]5}|j|v rB|jtjvrB|jj|jk r4tj	dk r*t
dd|jv r3t| qtj	dkrBd|jv rBt| qt|  t| }| D ]W}|j|v rt| ||j }|jtjv r~tj	dk rl|j|_n-tj	dk rzt|jd |_nt
dtt|j|j t| |_tj	dkr| jd  _|j|_d|j |_qMd	S )
zJFill in args for virtualized jump target after instructions may have movedrF   z*Got negative jump offset for Python < 3.11r   r   rq   r	   z+Python 3.11+ should not have absolute jumpszto N)setrU   r   unionr   r*   r   r.   r]   r^   rS   r+   r   update_offsetsr   r   r,   r'   absr   r-   r4   )r   Zjumpsr_   indexofr   r   r   r   devirtualize_jumps  sB   







r   exn_tab_bytesc                    s   t | }dd |D t d t|z3 fdd}| \}}|D ]}|j|jkr;| \}}|j|jks0|j|jkrGt||_q(W dS  t	yT   Y dS w )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   7  s    z.virtualize_exception_table.<locals>.<dictcomp>r   c                     s   t }  tk r"  | jkr" d7   tk r"  | jks dks(J  d  }tt| jt|t| j| j| j}| |fS )Nr   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   copyr3   r   )r   r   exn_tabr   r   r   r_   r   r   r   virtualize_exception_table4  s&   

r  c                    s  i  t | }| D ]F}|jrNt| ||jj j}tt|jjjt|jj d }t| ||jj	 j}||f}||jj
|jjf}| v rJ | |ksJJ | |< qt  dd d}dg g  fdd}	|D ]j}rd d	 |d k r|	  rd d	 |d k sxrψd d |d   kr|d	   krd d	 ksJ  J td d }
|
|d k rˈt|
|d d g d  R   |d | qjr|	  st S )
zMCompute exception table in list format from instructions with exn_tab_entriesr	   c                 S      | d | d  fS Nr   r   r   tr   r   r   <lambda>      z)compute_exception_table.<locals>.<lambda>keyr   c                     sZ   r)  } | d kr+tt| d | d g |  R   | d d dS dS dS )zT
        Pop the key_stack and append an exception table entry if possible.
        r   r   r	   N)popr   r   r   r  Zexn_dictr   Z	key_stacknextir   r   r
    s   "z$compute_exception_table.<locals>.poprp   r   )r   r3   r   r   r.   r   r'   r   r   r   r   r   r   r   r   r   r   r   )r   r   r_   r   r   r   r	  rd   Zkeys_sortedr
  leftr   r  r   compute_exception_table]  sb   
> r  c                 C   s   g }| D ]N}||j  ||j f}|r,|d d |d k r,|  |r,|d d |d k s|rM|d d |d   krJ|d   krJ|d d ksMJ  J || 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.
    rp   r   r   N)r   r   r
  r   )r   r   Zentry_stackr   r	  r   r   r   !check_inst_exn_tab_entries_nested  s   	>r  c                    s   t | }i  | D ]#}|jr+||jj ||jj f}| v r&|j | ks&J |j |< q fddt  dd dD }t|| |D ]}t||j ||j d D ]
}t|| | _qSqDdS )z~
    Copies exception table entries to all instructions in an entry's range.
    Supports nested exception table entries.
    c                       g | ]} | qS r   r   )rm   r	  entriesr   r   rn     s    z4propagate_inst_exn_table_entries.<locals>.<listcomp>c                 S   r  r  r   r  r   r   r   r    r  z2propagate_inst_exn_table_entries.<locals>.<lambda>r  r   N)	r   r3   r   r   r   r   r  rv   r   )r   r   r_   r	  Zsorted_entriesr   r@   r   r  r    propagate_inst_exn_table_entries  s(   




r  c                 C   s   t | }t }t| D ]K\}}|jrVtjdksJ t|j|vs"J |t|j |j}|j|v s4J |j	|v s;J |j
|v sBJ ||j |  krS||j	 ksVJ  J 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   r3   r]   r^   r6   addr   r   r   )r   r   Zexn_tab_entry_setr@   r_   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   rl   r   r   r   rn         z'strip_extended_args.<locals>.<listcomp>r   )r   r   r   r   strip_extended_args  s   r  c                 C   s   | j r| j j| u rt|dkr|d | j _|dd  D ]}t| j |_ | j|_q|d j| _|d j| _|d j| _|d j| _|d j	| _	| g|dd   S )Nr   rp   r   )
r3   r   r   r   r2   r*   r+   r,   r-   r   )Zold_inst	new_instsr_   r   r   r   overwrite_instruction  s   
r  c                 C   sJ   t jdk sJ ddd}| D ]}|j|v r"||j |_tj|j |_q| S )zFLOAD_METHOD puts a NULL on the stack which causes issues, so remove itrF   rM   r   )r   r   )r]   r^   r+   rU   rV   r*   )r   Zrewritesr_   r   r   r   remove_load_call_method  s   

r  c                 C   s   g }| D ]H}d|j v rGtdtd|j v d}|j|_tjdk r.td|j v r'dnd|jd	}ntd
|jd	}tdd d||g}|t	|| q|
| q|| d d < d S )NZ_NONEIS_OPNOTrh   rK   r   ZPOP_JUMP_FORWARD_IF_TRUEZPOP_JUMP_BACKWARD_IF_TRUEr[   POP_JUMP_IF_TRUErb   rc   )r+   rW   r'   r,   r-   r]   r^   r   r   r  r   )r   r  r_   Zis_opZjump_opreplace_instsr   r   r   remove_jump_if_none  s(   


	
r  c                 C   s   g }| D ]A}| | |jdv rEt|jdd}|jr&|jj|u r&||j_t|j|_|j|_tj	d |_
d|_d|_d|_| | q|| d d < d S )N)ZBINARY_SLICEZSTORE_SLICEZSLICEZSUBSCRBUILD_SLICEr	   )r   r+   rW   r   r3   r   r   r2   rU   rV   r*   r,   r-   )r   r  r_   Zsubscr_instr   r   r   remove_binary_store_slice5  s    


r!  )	LOAD_FASTr"  )
STORE_FASTr#  )r#  r"  )ZLOAD_FAST_LOAD_FASTZSTORE_FAST_STORE_FASTZSTORE_FAST_LOAD_FASTc                 C   st   g }| D ]-}|j tv r,t|j  \}}|j\}}t||dt||dg}|t|| q|| q|| d d < d S )Nrc   )r+   FUSED_INSTSr-   rW   r   r  r   )r   r  r_   Zinst0Zinst1Zargval0Zargval1r  r   r   r   remove_fused_load_storeP  s   



r%  r   c           	      C   sF  | j pd| jpd }t| jsdS g }t|D ]\}}|| |jdkr|jdkr||d  }|jdkrt	j
dkr?|jdksXt	j
d	krNt	j
dk rN|jd
ksXt	j
d	k r|jdkrd|v s^J |tddd | jd }||v rz|td|d n	|td|d d|_d|_|jd
kr||d  }d|_d|_q||dd< dS )z3convert super() with no args into explicit arg formr   NrN   superr   r   rK   r   rF   r   r   	__class__
LOAD_DEREFrc   r"  r	   )co_cellvarsco_freevarsr   co_varnamesr   r   r+   r-   r,   r]   r^   rW   )	r   r   Zcell_and_freer   r~   r_   r  Z	first_varZ	call_instr   r   r   explicit_supera  s8   







r,  c                    s@  g   fdd}| D ]}|j tjkrd|_nn|jrG|jdkrG|d  td|jd? d  td|jd	? d  td|jd
? d n=|jrl|jdkrl|d  td|jd	? d  td|jd
? d n|jr|jdkr|d  td|jd
? d  | q
t t|  }|dksJ  | 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 )Nrp   )rv   r*   rU   r   r
  )ry   r   r   r   r   maybe_pop_n  s
   z&fix_extended_args.<locals>.maybe_pop_nr   i r>   r      rh      r   i  r	   r   r   N)r*   rU   r   r,   r   rW   r   )r   r.  r_   addedr   r-  r   fix_extended_args  s,   r2  c                 C   s0   dd l }tjdkrd|jjjj| j d  S dS )Nr   rF   r	   r   )torchr]   r^   Z_CZ_dynamoZ
eval_frameZpy_opcode_cachesr*   )r_   r3  r   r   r   r     s   
r   c                 C   s,   d}| D ]}|j |ksJ |t|7 }qd S Nr   r.   r   r   r.   r_   r   r   r   check_offsets  s
   r7  c                 C   s$   d}| D ]}||_ |t|7 }qd S r4  r5  r6  r   r   r   r     s
   r   c                  G   sV   t ttt| }dd |gt|  dd t| d | d D g D }dd| S )Nc                 S   s    g | ]}d  dd |D qS ) c                 s   s    | ]}|d V  qdS )Z03Nr   )rm   xr   r   r   	<genexpr>  s    z)debug_bytes.<locals>.<listcomp>.<genexpr>)join)rm   r,   r   r   r   rn     s    zdebug_bytes.<locals>.<listcomp>c                 S   s   g | ]
\}}t ||kqS r   )r'   )rm   ar   r   r   r   rn     r  rp   zbytes mismatch

)rv   r   mapr   listzipr;  )argsindexresultr   r   r   debug_bytes  s   rE  c                 C   sR   t | dd dd}| j|jksJ t| j|j| j|jks'J t| j|jdS )z<Make sure our assembler produces same bytes as we start withc                 S   s   d S r    r   )r9  yr   r   r   r    s    zdebug_checks.<locals>.<lambda>T)safeN)transform_code_objectco_coderE  	co_lnotab)r   Zdoder   r   r   debug_checks  s   "rK  c                 C   sH   t | d D ]\}}||u r|  S q| d  |f7  < t| d d S )N	co_constsr   )r   r   )code_optionsrd   r@   vr   r   r   get_const_index  s   rO  c              	      s  dd t d D dtffdd}tjdk r;|d u s J dd t d	 D d
d t d d  D n=t|sAJ i  t D ]}z
||}| |< W qG ty]   Y  nw  fddd	 D  fddd d  D tt	D ]fdd} j
dkrȈ jtusJ tjdkr jd usJ | jd> tt jd   _q~| j _q~ j
dkr	 jtusJ tjdkr jd usJ | jd> tt jd   _q~| j _q~ j
dkr> jd usJ  jtus%J | jd> tt jd  d  _q~ j
tv rtjdksNJ t jtsYJ t	 jdkseJ tfdd jD }|d d> |d d@   _q~ jtv r| rtjdkr jvr j  _q~ j  _q~ jtv r| r| j _q~ jtv r| r j  _q~ jtv r jd u rt j}|dksJ | _q~d S )Nc                 S      i | ]\}}||qS r   r   rm   r~   rQ   r   r   r   r         zfix_vars.<locals>.<dictcomp>co_namesr   c                    sb   z|  }W |S  t y0   t }| < g  d | R  d< t d tks-J Y |S w )NrS  )KeyErrorr   )rQ   r~   )rM  namesr   r   get_name_index  s   
z fix_vars.<locals>.get_name_indexrF   c                 S   rP  r   r   rQ  r   r   r   r     rR  r+  c                 S   rP  r   r   rQ  r   r   r   r     s    r)  r*  c                       i | ]}| | qS r   r   rm   rQ   allnamesr   r   r     rR  c                    rW  r   r   rX  rY  r   r   r     s    c                      s     j tuS r    )r-   rH   r   )r@   r   r   r   should_compute_arg
  s   z$fix_vars.<locals>.should_compute_argrN   r   r	   rM   rK   rO   r=   c                 3   s(    | ]}|v r| n | V  qd S r    r   rX  )	freenamesvarnamesr   r   r:  /  s
    
zfix_vars.<locals>.<genexpr>r   rt      )r   r'   r]   r^   callable	itertoolscount
IndexErrorrv   r   r+   r-   rH   r,   r   r$  rT   tupler*   	HAS_LOCALHAS_NAMEHAS_FREE	HAS_CONSTrO  )r   rM  varname_from_opargrV  r~   rQ   r[  Z	arg_tupler   )rZ  rM  r\  r@   r   rU  r]  r   fix_vars  s   





 
ri  c                 C   sP   | D ]#}|j tur%|jtv s|jtv s|jtv s|jtv r%|jdvr%d |_qd S )N)rN   rM   rO   )	r-   rH   r*   rd  re  rf  rg  r+   r,   )r   r_   r   r   r   clear_instruction_argsN  s   





rj  c                  C   s   dg} |  d | g d tjdkr|  d |  d tjdkr)|  d n|  d	 tjdkr8|  d
 | ddg | S )Nco_argcountco_posonlyargcount)
co_kwonlyargcount
co_nlocalsco_stacksizeco_flagsrI  rL  rS  r+  co_filenameco_namerF   Zco_qualnameco_firstlinenorq   co_linetablerJ  co_exceptiontabler*  r)  )r   r   r]   r^   )r   r   r   r   get_code_keys_  s&   







rv  Fc                    s\   t  } fdd|D }t|d |d ksJ t |}t| ||| t|||d S )Nc                    s   i | ]}|t  |qS r   )getattrrm   kr   r   r   r     ro   z)transform_code_object.<locals>.<dictcomp>r+  rn  r   )rv  r   cleaned_instructionsr   clean_and_assemble_instructions)r   ZtransformationsrG  r   rM  r   r   rz  r   rH    s   

rH  r   rM  c                    s  t |  t d  d< d }tjdkr"tj fdd|D  }|j}t|  |d d}|r=t|  t	|  t
t| }|s-t|  t|  d \}}tjd	k rT| d
< n| d< | d< t|  d< t|dh t  dh kstJ tjdkrtt|  d< | tj fdd|D  fS )Nr+  rn  rF   c                    r  r   r   rx  rM  r   r   rn     r   z3clean_and_assemble_instructions.<locals>.<listcomp>)rh  Trs  rq   rJ  rt  rI  ro  rl  ru  c                    r  r   r   rx  r}  r   r   rn     r   )r  r   r]   r^   typesCodeTypeZ_varname_from_opargri  r   r   r(   r2  r   r   r   r   r   r   r  )r   r   rM  rh  Ztmp_codeZdirtybytecoder   r   r}  r   r|    s8   



r|  c                 C   s$   | D ]}|j dkr||j |_qd S )NZKW_NAMES)r+   r,   r-   )r   Zconstsr_   r   r   r   populate_kw_names_argval  s
   
r  c                 C   s   t | |}t|S r    )_cached_cleaned_instructions_clone_instructionsr   rG  r   r   r   r   r{    s   
r{  c                 C   sp   dd | D }t t| |}d |d < |D ]!}||j |_|j }r5t||j ||j ||j |j|j|_q|S )Nc                 S   s>   g | ]}t |j|j|j|j|j|j|j|j|j	|j
|jqS r   )r   r*   r+   r,   r-   r.   r/   r0   r2   r   r3   r4   rl   r   r   r   rn     s     z'_clone_instructions.<locals>.<listcomp>)	dictrA  r   r3   r   r   r   r   r   )r   ZcopiedZremapr@   r   r   r   r   r    s"   
r  c                 C   s   t ttt| }t| tjdkrt|| j	 t
| j| t| t| |sWtjdk r2t| tjdk r<t| | tjdkrWt| tjdkrNt| tjdkrWt| tjdkrdt| t| |S )NrF   rK   r=   )r@  r?  rD   rU   get_instructionsr7  r]   r^   r  rL  r  ru  r   r  r  r,  r  r!  r%  r   r   r  r   r   r   r    s,   







r  c                 C   s   |  dt t S )Nr   )r   _unique_id_counterrP   r   r   r   	unique_id  r   r  c                 C   s   d}| j |@ dkS )N    r   )rp  )r   Zco_generatorr   r   r   is_generator  s   r  c           
      C   s  t | j}t| |r#t|D ]\}}|jdkr"||d d } nq|D ]}d|_|r7|j|v r7||j |_q%|rtjdkrhg }|D ]"}|jdkr`t	j
d |_d|_|| |td qC|| qC|}g }|D ]}|jdkrx|| qlt|dkr|d |d	 u r|d	 |S t|dkr|d	 |d	 u rd
|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. NOTE: any items pushed to the stack
            for return WILL remain on the stack! Append a POP_TOP if you don't want
            that item to be present.
        noprefix: remove prefix bytecodes (all bytecode before the first RESUME, inclusive).
    RESUMEr   NrK   ZRETURN_CONSTrb   RETURN_VALUEr   rp   NOP)r{  __code__rj  r   r+   r/   r-   r]   r^   rU   rV   r*   r   rW   r   r
  r,   rH   r`   r   )
fnZvarname_mapZnoreturnZnoprefixr   r@   r_   r  returnsZ	jump_instr   r   r   bytecode_from_template  s`   
"










r  )T)r   )r   Nr    )F)NTT)sr<   r   dataclassesrU   	functoolsr`  r]   r~  collections.abcr   r   typingr   r   r   r   r   Zutils._backport_slotsr
   Zbytecode_analysisr   r   r   r   utilsr   	dataclassr   r   r^   rD   rH   rR   rW   r`   rf   rj   r@  rz   r   r   r   r   r   r   r   r'   rc  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$  r%  r  r,  r2  r   r7  r   r)   rE  rK  haslocalrd  hasnamere  hasfreerf  hasconstrg  rO  ri  rj  rv  rH  r|  r  r{  r  	lru_cacher  ra  r  r  r(   r  r  r   r   r   r   <module>   s  






'
:
7+
#;"*


	0)
J
	&!





k'

)%