o
    Ih                     @   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   Y/var/www/vscode/kcb/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   cntr   r   r   create_instruction   s    rX   c                 C      t jdkrdnd}t|| dS )NrF   JUMP_FORWARDJUMP_ABSOLUTEr   sysversion_inforX   )r   instr   r   r   create_jump_absolute      ra   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   rX   )valcheckedr   r   r   create_load_const   s   rg   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   
rk   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 )SWAPri   )rX   .0r@   r   r   r   
<listcomp>       z create_rot_n.<locals>.<listcomp>r>   
      zrotate z  not supported for Python < 3.10   ROT_)TWOTHREEFOURr	   ROT_Nri   )r^   r_   rangeAttributeErrorrX   nr   r   r   create_rot_n   s   	
r   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   ri   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   ri   r   r   r   r   set_inst_bit  s   z#add_push_null.<locals>.set_inst_bitr=   rq   	PUSH_NULLrK   r   rN   rF   )rT   r   r^   r_   rR   r+   rX   )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=   rq   r   rN   Nr   r   )rT   r   r^   r_   r+   r,   rX   )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   PRECALLri   CALLCALL_FUNCTION)r^   r_   appendrX   extendr   )nargs	push_nulloutput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   ri   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_METHODrd   r]   rP   r   r   r   create_load_method  s   
r   c                 C   rY   )NrF   BEFORE_WITH
SETUP_WITHr\   r]   )r   r+   r   r   r   create_setup_with  rb   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   rl   ri   r   
BUILD_LISTrj   rc   rq   rd   BINARY_SUBSCR	ROT_THREESTORE_SUBSCRreverser   POP_TOPUNPACK_SEQUENCE)r^   r_   rX   r   r   r}   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
    rr   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
    rr   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   r~   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   ?      rq   @   )r   )r~   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sizeother_varintsr~   )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   r{   len)r~   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   re   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)r{   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   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   entry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   rr   N)r^   r_   r   	enumerater+   r2   instruction_sizer,   r   r*   r{   r   r   r/   r   r   )r   r   coder   update_lineno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	   ru   r   Nr*   rU   r   )r   r.   r~   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.   rn   r`   r   r   r   
<dictcomp>      z$virtualize_jumps.<locals>.<dictcomp>N)r*   rU   hasjabshasjrelr   r-   r   )r   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+   replacer|   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   rr   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   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end_offset_idx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  exn_dictr  	key_stacknextir   r   r    s   "z$compute_exception_table.<locals>.poprq   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  re   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.
    rq   r   r   N)r   r   r  r   )r   r  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   )rn   r  entriesr   r   ro     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$  r{   r  )r   r  r`   r  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  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   rm   r   r   r   ro         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   rq   r   )
r3   r   r   r  r2   r*   r+   r,   r-   r   )old_inst	new_instsr`   r   r   r   overwrite_instruction  s   
r1  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   rewritesr`   r   r   r   remove_load_call_method  s   

r3  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 )N_NONEIS_OPNOTri   rK   r   POP_JUMP_FORWARD_IF_TRUEPOP_JUMP_BACKWARD_IF_TRUEr\   POP_JUMP_IF_TRUErc   rd   )r+   rX   r'   r,   r-   r^   r_   r   r   r1  r   )r   r0  r`   is_op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)BINARY_SLICESTORE_SLICESLICESUBSCRBUILD_SLICEr	   )r   r+   rX   r   r3   r   r  r2   rU   rV   r*   r,   r-   )r   r0  r`   subscr_instr   r   r   remove_binary_store_slice5  s    


rD  )	LOAD_FASTrE  )
STORE_FASTrF  )rF  rE  )LOAD_FAST_LOAD_FASTSTORE_FAST_STORE_FAST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 )Nrd   )r+   FUSED_INSTSr-   rX   r   r1  r   )r   r0  r`   inst0inst1argval0argval1r<  r   r   r   remove_fused_load_storeP  s   



rO  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_DEREFrd   rE  r	   )co_cellvarsco_freevarsr   co_varnamesr   r   r+   r-   r,   r^   r_   rX   )	r   r   cell_and_freer   r   r`   r  	first_var	call_instr   r   r   explicit_supera  s8   







rY  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 )Nrq   )r{   r*   rU   r   r  )r~   r   r   r   r   maybe_pop_n  s
   z&fix_extended_args.<locals>.maybe_pop_nr   i r>   r      ri      r   i  r	   r   r   N)r*   rU   r   r,   r   rX   r   )r   r[  r`   addedr   rZ  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   r	   r   )torchr^   r_   _C_dynamo
eval_framepy_opcode_cachesr*   )r`   r`  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
   rh  c                 C   s$   d}| D ]}||_ |t|7 }qd S re  rf  rg  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 )03Nr   )rn   xr   r   r   	<genexpr>  s    z)debug_bytes.<locals>.<listcomp>.<genexpr>)join)rn   r,   r   r   r   ro     s    zdebug_bytes.<locals>.<listcomp>c                 S   s   g | ]
\}}t ||kqS r   )r'   )rn   ar   r   r   r   ro     r-  rq   zbytes mismatch

)r{   r   mapr   listziprm  )argsindexresultr   r   r   debug_bytes  s   rw  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   )rk  yr   r   r   r    s    zdebug_checks.<locals>.<lambda>T)safeN)transform_code_objectco_coderw  	co_lnotab)r   doder   r   r   debug_checks  s   "r~  c                 C   sH   t | d D ]\}}||u r|  S q| d  |f7  < t| d d S )N	co_constsr   )r   r   )code_optionsre   r@   vr   r   r   get_const_index  s   r  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   rn   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 )Nr  )KeyErrorr   )rQ   r   )r  namesr   r   get_name_index  s   
z fix_vars.<locals>.get_name_indexrF   c                 S   r  r   r   r  r   r   r   r     r  rU  c                 S   r  r   r   r  r   r   r   r     s    rS  rT  c                       i | ]}| | qS r   r   rn   rQ   allnamesr   r   r     r  c                    r  r   r   r  r  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   r  )	freenamesvarnamesr   r   rl  /  s
    
zfix_vars.<locals>.<genexpr>r   ru      )r   r'   r^   r_   callable	itertoolscount
IndexErrorr{   r   r+   r-   rH   r,   r   rJ  rT   tupler*   	HAS_LOCALHAS_NAMEHAS_FREE	HAS_CONSTr  )r   r  varname_from_opargr  r   rQ   r  	arg_tupler   )r  r  r  r@   r   r  r  r   fix_vars  s   





 
r  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*   r  r  r  r  r+   r,   )r   r`   r   r   r   clear_instruction_argsN  s   





r  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_flagsr{  r  r  rU  co_filenameco_namerF   co_qualnameco_firstlinenorr   co_linetabler|  co_exceptiontablerT  rS  )r   r   r^   r_   )r  r   r   r   get_code_keys_  s&   







r  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rn   kr   r   r   r     rp   z)transform_code_object.<locals>.<dictcomp>rU  r  r   )r  r   cleaned_instructionsr   clean_and_assemble_instructions)r   transformationsry  r  r  r   r   r  r   rz    s   

rz  r  r  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 )NrU  r  rF   c                    r%  r   r   r  r  r   r   ro     r   z3clean_and_assemble_instructions.<locals>.<listcomp>)r  Tr  rr   r|  r  r{  r  r  r  c                    r%  r   r   r  r  r   r   ro     r   )r,  r   r^   r_   typesCodeType_varname_from_opargr  r  r  r(   r_  r   r   r   r   r  r   r"  )r   r  r  r  tmp_codedirtybytecoder   r   r  r   r    s8   



r  c                 C   s$   | D ]}|j dkr||j |_qd S )NKW_NAMES)r+   r,   r-   )r   constsr`   r   r   r   populate_kw_names_argval  s
   
r  c                 C   s   t | |}t|S r    )_cached_cleaned_instructions_clone_instructionsr   ry  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   rm   r   r   r   ro     s     z'_clone_instructions.<locals>.<listcomp>)	dictrs  r   r3   r   r   r   r   r   )r   copied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=   )rr  rq  rD   rU   get_instructionsrh  r^   r_   r  r  r  r  r   r.  r3  rY  r=  rD  rO  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   )r  )r   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   RETURN_CONSTrc   RETURN_VALUEr   rq   NOP)r  __code__r  r   r+   r/   r-   r^   r_   rU   rV   r*   r   rX   r   r  r,   rH   ra   r   )
fnvarname_mapnoreturnnoprefixr   r@   r`   r0  returns	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   utils._backport_slotsr
   bytecode_analysisr   r   r   r   utilsr   	dataclassr   r   r_   rD   rH   rR   rX   ra   rg   rk   rr  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)  r,  r.  r1  r3  r=  rD  rJ  rO  r  rY  r_  r   rh  r  r)   rw  r~  haslocalr  hasnamer  hasfreer  hasconstr  r  r  r  r  rz  r  r  r  r  	lru_cacher  r  r  r  r(   r  r  r   r   r   r   <module>   s  






'
:
7+
#;"*


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