o
     Ǝi                    @   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Zddl	m
Z
mZmZmZ ddlmZmZmZmZmZmZ ddlmZ ddlmZ dd	lmZmZmZmZ dd
lmZ erdddl m!Z! eej"G dd dZ#eej"G dd dZ$ej%dkrd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e(de)fddZ*nej%dkrde(de)fddZ*nde(fddZ*de'dd de(d!ee+ d"ee d#ee$ de$f
d$d%Z,d#e$de$fd&d'Z-d#e$de)fd(d)Z.dd+ed,e)de$fd-d.Z/de$fd/d0Z0d1e+de1e$ fd2d3Z2d4ee$e1e$ f de1e$ fd5d6Z3d4ee$e1e$ f de1e$ fd7d8Z4d9e+d:e)de1e$ fd;d<Z5d9e+de1e$ fd=d>Z6de(de$fd?d@Z7d#e$de$fdAdBZ8d1e+de1e$ fdCdDZ9	EddFee+ dGee+ dHe)de1e$ fdIdJZ:de+de1e$ fdKdLZ;dMe+de1e$ fdNdOZ<dPede1e$ fdQdRZ=	ddSe+dTe+de>e1e+ ee+e+gdf f fdUdVZ?dWe+de>e1e+ ee+e+gdf ee+gdf f fdXdYZ@d1e+de1e+ fdZd[ZAdWe+de>e1e+ eed\ e+gdf f fd]d^ZBeej"G d_d` d`ZCd1e+de1e+ fdadbZDdcee+ de+fdddeZEdfe1eC ddfdgdhZFdieGde1eC fdjdkZHdfe1eC deGfdldmZIdne1e$ doe+de>eGeGf fdpdqZJdreKe+e$f dse+dee$ fdtduZLdne
e$ ddfdvdwZMeNejOZPdxe$ddfdydzZQdne1e$ d{e+de$fd|d}ZRdne1e$ ddfd~dZSdeGdne1e$ ddfddZTdne1e$ de1eC fddZUdfe1e# deKe$e+f ddfddZVdne1e$ ddfddZWdne1e$ ddfddZXdne1e$ ddfddZYde$de1e$ de1e$ fddZZdne1e$ de1e$ fddZ[dne1e$ ddfddZ\dne1e$ ddfddZ]ddddZ^dne1e$ ddfddZ_dne1e$ ddfddZ`dne1e$ ddfddZadejbdne1e$ ddfddZcdne1e$ de+fddZdde$de+fddZednee$ ddfddZfdnee$ ddfddZgdeGde(fddZhdejbddfddZieNejjZkeNejlZmeNejnZoeNejpZqdeKe(ef d+ede+fddZr	ddne1e$ deKe(ef deedef  ddfddZsdne1e$ ddfddZtejude1e( fddZv	Eddejbdee1e$ eKe(ef ged f de)de>ejbed f fddZwdne1e$ de1e( deKe(ef de>e1e$ ejbf fddńZxdnee$ deddfddȄZyddejbde)de1e$ fddʄZzdnee$ de1e$ fdd̄Z{eju	Eddejbde)dee$ fdd΄Z|e} Z~dde(de)de(fddфZdejbde)fddӄZ		*	*ddedef deeeef  de)de)de1e$ f
ddلZd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)IterableIteratorMappingSequence)AnyCallablecastOptionalTYPE_CHECKINGUnion   )dataclass_slots   )config)get_indexofpropagate_line_numsremove_extra_line_numsstacksize_analysis)is_safe_constant)DynamoTracerOutputc                   @   sV   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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"   a/home/jeff/fluffinator/venv/lib/python3.10/site-packages/torch/_dynamo/bytecode_transformation.py__repr__3   s   zInstructionExnTabEntry.__repr__oc                 C   sJ   t |tsdS | j|ju o$| j|ju o$| j|ju o$| j|jko$| j|jkS NF)
isinstancer   r   r   r   r   r   )r!   r%   r"   r"   r#   __eq__;   s   




zInstructionExnTabEntry.__eq__N)
__name__
__module____qualname____annotations__intboolstrr$   objectr(   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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 Nidr    r"   r"   r#   __hash__Y      zInstruction.__hash__otherc                 C   s   t | t |kS r<   r=   r!   rA   r"   r"   r#   r(   \   s   zInstruction.__eq__c                 C   s   d| j  d| j dS )NzInstruction(opname=z	, offset=r   )r2   r5   r    r"   r"   r#   r   _   s   zInstruction.short_inst_reprc                 C   s   |j | _ |j| _d S r<   )r6   r9   rB   r"   r"   r#   copy_positionsb   s   zInstruction.copy_positions)rA   r   r   N)r)   r*   r+   __doc__r-   r,   r/   r	   r   r5   r6   r7   r.   r9   r   r:   r   r;   r?   r0   r(   r   rC   r"   r"   r"   r#   r   G   s"   
 r         ir   c              	   C   &   t | j| j| j| j| j| j| j| jS r<   )	r   r1   r2   r3   r4   r5   line_numberr7   r9   rH   r"   r"   r#   convert_instructioni      rL   rF      c              	   C   rI   r<   )	r   r1   r2   r3   r4   r5   r6   r7   r9   rK   r"   r"   r#   rL   w   rM   c              	   C   s$   t | j| j| j| j| j| j| jd S r<   )r   r1   r2   r3   r4   r5   r6   r7   rK   r"   r"   r#   rL      s   c                   @   s   e Zd ZdefddZdS )_NotProvidedr   c                 C      dS )NrP   r"   r    r"   r"   r#   r$         z_NotProvided.__repr__N)r)   r*   r+   r/   r$   r"   r"   r"   r#   rP      s    rP   rF      namec                 C   s   | dv S )N)	LOAD_ATTRLOAD_GLOBALLOAD_SUPER_ATTRr"   rU   r"   r"   r#   inst_has_op_bits   r@   rZ   c                 C   s   | dkS )NrW   r"   rY   r"   r"   r#   rZ      r@   c                 C   rQ   r&   r"   rY   r"   r"   r#   rZ      rR   )r3   r4   r   r3   r4   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)r1   r2   r3   r4   r   )rZ   RuntimeErrorrP   r'   r-   r   disopmap)rU   r3   r4   r   cntr"   r"   r#   create_instruction   s    r_   c                 C      t jdkrdnd}t|| dS )NrN   JUMP_FORWARDJUMP_ABSOLUTEr   sysversion_infor_   )r   instr"   r"   r#   create_jump_absolute      rh   c                 C   s
   | j dv S )N)ra   rb   )r2   rc   r"   r"   r#   is_jump_absolute   s   
rj   Tvalcheckedc                 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r4   )r   r_   )rk   rl   r"   r"   r#   create_load_const   s   ro   c                   C   s   t jdkrtdddS tdS )NrN   COPYr   r3   DUP_TOPrd   r"   r"   r"   r#   create_dup_top   s   
rs   nc                 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	td
| d	td| d d	td
| d d	gS | dkrKt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   rN   c                 S   s   g | ]}t d |dqS )SWAPrq   )r_   .0rH   r"   r"   r#   
<listcomp>       z create_rot_n.<locals>.<listcomp>rF   
      BUILD_TUPLErq   UNPACK_SEQUENCE   ROT_)TWOTHREEFOURr   ROT_N)re   rf   ranger_   rt   r"   r"   r#   create_rot_n   s   	


r   inst_or_instsc                    s,  t | tr	| g n	t | tsJ |  dtdtf fdd}dtddf fdd}tjdkrGt d	 jr>|d	s>|d	  S  t	d
g   S tjdkrwt d	 jr]|d	s]|d	  S  d jdkrn|dsn|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.
    idxr   c                    s$    |  j d us	J  |  j d@ dkS Nr   rq   r   instsr"   r#   inst_has_bit_set*  s   z'add_push_null.<locals>.inst_has_bit_setNc                    s(    |  j d us	J  |   j dO  _ d S r   rq   r   r   r"   r#   set_inst_bit.  s   z#add_push_null.<locals>.set_inst_bitrE   rz   	PUSH_NULLrS   r   rW   rN   )
r'   r   listr-   r.   re   rf   rZ   r2   r_   )r   r   r   r"   r   r#   add_push_null  s6   


	
r   c                 C   s   t | tr	| g}n	t | tsJ | }tjdk r|S tjdkr dnd}|| jdkrF|| jdus2J || jd@ dkrF||  jdO  _|S tjdkrT|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.
    rN   rE   rz   r   rW   Nr   r   )r'   r   r   re   rf   r2   r3   r_   )r   r   r   r"   r"   r#   add_push_null_call_function_exN  s"   


r   nargs	push_nullc                 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),
            )
    rN   r   rE   r   r   rS   PRECALLrq   CALLCALL_FUNCTION)re   rf   appendr_   extendr   )r   r   outputrotsr"   r"   r#   create_call_functionl  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 )NrS   r   rq   rN   r   CALL_METHODrd   )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 )NrS   rV   r   )r3   r4   LOAD_METHODrn   rd   rY   r"   r"   r#   create_load_method  s   
r   c                 C   r`   )NrN   BEFORE_WITH
SETUP_WITHrc   rd   )r   r2   r"   r"   r#   create_setup_with  ri   r   c                 C   s   t jdkrtd| dgS | dkrg S | dkrtdgS | dkr'tdtd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 )NrN   ru   rq   r   r   ROT_TWOrF   	ROT_THREE
BUILD_LISTrr   rm   rz   rn   BINARY_SUBSCRSTORE_SUBSCRreverser   POP_TOPr   )re   rf   r_   r   r   r   r"   r"   r#   create_swap  s6   



r   Fr   r   storec                 C   sX   t jdkr|r	dnd}t| t|t|gS |rdnd}t| t|tdddt|gS )	zQ
    BINARY_SLICE and STORE_SLICE (if `set` is True) for all Python versions
    rS   STORE_SLICEBINARY_SLICEr   r   BUILD_SLICEr   rq   )re   rf   ro   r_   )r   r   r   	inst_namer"   r"   r#   create_binary_slice  s   

r   c                 C   s>   t jdkrtd| dgS g t| t t| d tdS )NrN   rp   rq   r   r   )re   rf   r_   r   rs   rK   r"   r"   r#   create_copy  s   

r   r   c                 C   s@   g t tdtdt| tjdkrdnd tddtdS )Nrm   rn   rN   r   r   Fr   )r   r_   printr   re   rf   r   )r   r"   r"   r#   create_print_on_stack  s   r   valuec                 C   s2   g t tdtdtd| dtddtdS )Nrm   rn   r   Fr   )r   r_   r   r   )r   r"   r"   r#   create_print_value  s   
r   linenobytenoc                    s8   t jdk sJ g dtdtddf 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{   
lineno_new
byteno_newr   Nc                    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   )r   r   byte_offsetline_offsetr   r   lnotabr"   r#   update/  s   zlnotab_writer.<locals>.updatere   rf   r-   )r   r   r   r"   r   r#   lnotab_writer$  s   
r   first_linenoc                    s   t jdkr
t jdk sJ g | dddtdtddffdd	 d
tdtddf fdd}dtddf 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{   rN   r   byteno_deltalineno_deltar   Nc                    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   )r   r   r   r   )	linetabler"   r#   _updateJ  s   z%linetable_310_writer.<locals>._updater   r   c                    s&   | }| | |  | d S r<   r"   )r   r   r   )r   r   r   r   r"   r#   r   S  s
   
z$linetable_310_writer.<locals>.updatetotal_bytesc                    s    |   d S r<   r"   )r   )r   r   r   r"   r#   r   [  s   z!linetable_310_writer.<locals>.endr   )r   r   r   r"   )r   r   r   r   r   r#   linetable_310_writer<  s    	
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   ?      rz   @   )r   )rt   br"   r"   r#   encode_varinta  s   
r   r8   c                    s>   t jdksJ g |  dtd dtddf 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
    rN   r9   r8   	inst_sizer   Nc                    st    r j nd }dtdtdd f fdd}|d u rd}n| }||dkr3||d |d8 }|dks&||| d S )Ndeltasizer   c                    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   )r   r   other_varintsrt   )r   r9   r"   r#   r     s*   




z5linetable_311_writer.<locals>.update.<locals>._updater   r   )r   r-   )r9   r   r   r   r   r   r   )r9   r#   r   |  s    
z$linetable_311_writer.<locals>.update)re   rf   r	   r-   )r   r   r"   r   r#   linetable_311_writerp  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   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)rt   r   rH   r"   r"   r#   encode_exception_table_varint  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   rk   r"   r"   r#   decode_exception_table_varint  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   rH   r"   r"   r#   check_exception_table  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()rN   r   EXTENDED_ARGr   r   r   rF   r   r   )r   r   r{   N)re   rf   r   	enumerater2   r9   instruction_sizer3   r   r1   r   r   r   r6   r   r   )r   r   coder   update_linenonum_extrH   rg   r   jr3   _r   r"   r"   r#   assemble	  sF   






r  offset_to_instr5   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   r   r   Nr1   r\   r   )r  r5   rt   r"   r"   r#   _get_instruction_by_offset3  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 d ur|j |qS r<   )r5   rw   rg   r"   r"   r#   
<dictcomp>A  s    z$virtualize_jumps.<locals>.<dictcomp>N)r1   r\   hasjabshasjrelr  r4   r   )r   jump_targetsrg   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 )NrN   z+Cannot flip jump direction in Python < 3.11FORWARDBACKWARDz-Instruction is not a forward or backward jump)
re   rf   r[   r2   replaceAttributeErrorr\   r]   r1   
_REL_JUMPS)r  r"   r"   r#   flip_jump_directionM  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   r5   r"   r"   r#   _get_instruction_frontZ  s   r  c                 C   s  t tjt tj}| D ]G}|j|v rT|jtjvrT|jdur*|jjdur*|jdus,J |jj|jk rFtj	dk r<t
dd|jv rEt| qtj	dkrTd|jv rTt| qt|  t| }| D ]j}|j|v r|jdusmJ t| ||j }|jtjv rtj	dk r|j|_n9tj	dk rt|jd |_n+t
d|jdur|jdusJ tt|j|j 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 movedNrN   z*Got negative jump offset for Python < 3.11r  r  r{   r   z+Python 3.11+ should not have absolute jumpszto )setr\   r  unionr  r1   r   r5   re   rf   r[   r2   r  update_offsetsr   r  r3   r-   absr   r4   r;   )r   jumpsrg   indexofr   r"   r"   r#   devirtualize_jumpsh  sL   








r  exn_tab_bytesc                    s   t | }dd |D t d t|zAdtttf f fdd}| \}}|D ]&}|jdus8J |j|jkrI| \}}|j|jks>|j|j	krUt

||_q/W dS  tyb   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-   r5   r  r"   r"   r#   r    s    z.virtualize_exception_table.<locals>.<dictcomp>r   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   tupler   r   r5   r   r   copyr:   r   )r  r   exn_tabr!  r   r  rg   r"   r  r#   virtualize_exception_table  s(    

r'  c                    s  i  t | }| D ]X}|jr`t| ||jj j}|dusJ tt|jjjt|jj d }|dus3J t| ||jj	 j}|dusCJ ||f}||jj
|jjf}| v r\ | |ks\J | |< qt  dd d}dg g d fdd	}	|D ]j}rd
 d |d k r|	  rd
 d |d k s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 | q}r|	  st S )zMCompute exception table in list format from instructions with exn_tab_entriesNr   c                 S      | d | d  fS Nr   r   r"   tr"   r"   r#   <lambda>      z)compute_exception_table.<locals>.<lambda>keyr   r   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#   r0    s   "z$compute_exception_table.<locals>.poprz   r   )r   N)r   r:   r  r   r5   r   r-   r   r   r   r   r   r"  r#  r   r   r   r   )r   r  rg   r   r   r   r/  rk   keys_sortedr0  leftr"   r1  r#   compute_exception_table  sh   
> r7  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.
    rz   r   r   N)r   r   r0  r   )r   r  entry_stackr   r/  r"   r"   r#   !check_inst_exn_tab_entries_nested  s   	>r9  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"   )rw   r/  entriesr"   r#   rx   ;  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   r:   r   r   r"  r#  r9  r   r%  )r   r  rg   r/  sorted_entriesr   rH   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.
    rN   N)r   r  r   r:   re   rf   r>   addr   r   r   )r   r  exn_tab_entry_setrH   rg   r   r"   r"   r#    check_inst_exn_tab_entries_validF  s   
(rA  c                 C   s   dd | D | d d < d S )Nc                 S   s   g | ]
}|j tjkr|qS r"   r  rv   r"   r"   r#   rx   _      z'strip_extended_args.<locals>.<listcomp>r"   )r   r"   r"   r#   strip_extended_args^  s   rC  old_inst	new_instsc                 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   rz   r   )
r:   r   r   r%  r9   r1   r2   r3   r4   r   )rD  rE  rg   r"   r"   r#   overwrite_instructiong  s   
rF  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 itrN   rV   r   )r   r   )re   rf   r2   r\   r]   r1   )r   rewritesrg   r"   r"   r#   remove_load_call_method~  s   

rH  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NOTrq   rS   r  POP_JUMP_FORWARD_IF_TRUEPOP_JUMP_BACKWARD_IF_TRUErc   POP_JUMP_IF_TRUErm   rn   )r2   r_   r-   r3   r4   re   rf   r   r   rF  r   )r   rE  rg   is_opjump_opreplace_instsr"   r"   r#   remove_jump_if_none  s(   


	
rR  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)r   r   SLICESUBSCRr   r   )r   r2   r_   r  r:   r   r%  r9   r\   r]   r1   r3   r4   )r   rE  rg   subscr_instr"   r"   r#   remove_binary_store_slice  s    


rV  )	LOAD_FASTrW  )
STORE_FASTrX  )rX  rW  )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 )Nrn   )r2   FUSED_INSTSr4   r_   r   rF  r   )r   rE  rg   inst0inst1argval0argval1rQ  r"   r"   r#   remove_fused_load_store  s   



ra  c                 C   s`   g }| D ]#}d|j v r"tdddt|j |jdg}|t|| q|| q|| d d < d S )NRETURNNOPGRAPH_BREAK_IF_LEAFrn   )r2   r_   r4   r   rF  r   )r   rE  rg   rQ  r"   r"   r#   $add_graph_break_if_leaf_instructions  s   

re  c                 C   s   g }t | | dd  D ]^\}}|jdkrd|jdkrd|jdrdtt| D ]=}| | j|u r3|| | _| | jrb| | jj|u rF|| | j_| | jj	|u rT|| | j_	| | jj|u rb|| | j_q%q|
| q|
| d  || d d < d S )Nr   rc  rd  rb  rz   )zipr2   r4   
startswithr   r   r   r:   r   r   r   )r   rE  rg   	next_instrH   r"   r"   r#   'remove_graph_break_if_leaf_instructions  s*   




ri  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"   NrW   superr   r   rS   r   rN   r   r   	__class__
LOAD_DEREFrn   rW  r   )co_cellvarsco_freevarsr   co_varnamesr   r   r2   r4   r3   re   rf   r_   )	r   r   cell_and_freer   r   rg   r4  	first_var	call_instr"   r"   r#   explicit_super  s8   







rs  c                    sJ  g  dt ddf fdd}| D ]}|jtjkrd|_nn|jrL|jdkrL|d  td	|jd
? d  td	|jd? d  td	|jd? d n=|jrq|jdkrq|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 opsrt   r   Nc                    s.   t | D ]} r d jtjkr   qd S )Nrz   )r   r1   r\   r   r0  )rt   r   r   r"   r#   maybe_pop_n)  s
   z&fix_extended_args.<locals>.maybe_pop_nr   i rF   r      rq      r   i  r   r   r   )r-   r1   r\   r   r3   r   r_   r   )r   ru  rg   addedr"   rt  r#   fix_extended_args%  s,   ry  rg   c                 C   s0   dd l }tjdkrd|jjjj| j d  S dS )Nr   rN   r   r   )torchre   rf   _C_dynamo
eval_framepy_opcode_cachesr1   )rg   rz  r"   r"   r#   r   F  s   
r   c                 C   s,   d}| D ]}|j |ksJ |t|7 }qd S Nr   r5   r   r   r5   rg   r"   r"   r#   check_offsetsN  s
   r  c                 C   s$   d}| D ]}||_ |t|7 }qd S r  r  r  r"   r"   r#   r  U  s
   r  argsc                  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"   )rw   xr"   r"   r#   	<genexpr>_  s    z)debug_bytes.<locals>.<listcomp>.<genexpr>)join)rw   r3   r"   r"   r#   rx   ^  s    zdebug_bytes.<locals>.<listcomp>c                 S   s   g | ]
\}}t ||kqS r"   )r-   )rw   ar   r"   r"   r#   rx   b  rB  rz   zbytes mismatch

)r   r   mapr   r   rf  r  )r  indexresultr"   r"   r#   debug_bytes\  s   r  c                 C   sV   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"   )r  yr"   r"   r#   r,  j  s    zdebug_checks.<locals>.<lambda>T)safeN)transform_code_objectco_coder  	co_lnotab)r   doder   r"   r"   r#   debug_checksh  s   "r  code_optionsc                 C   sH   t | d D ]\}}||u r|  S q| d  |f7  < t| d d S )N	co_constsr   )r   r   )r  rk   rH   vr"   r"   r#   get_const_indexu  s   r  varname_from_oparg.c              	      s  dd t d D dt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|sCJ i  t D ]}z
||}| |< W qI ty_   Y  nw  fddd
 D  fddd d  D t	t
D ]dtf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rD 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sTJ t jts_J t
 jdkskJ 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 | _qd S )Nc                 S      i | ]\}}||qS r"   r"   rw   r   rU   r"   r"   r#   r        zfix_vars.<locals>.<dictcomp>co_namesrU   r   c                    sb   z|  }W |S  t y0   t }| < g  d | R  d< t d tks-J Y |S w )Nr  )KeyErrorr   )rU   r   )r  namesr"   r#   get_name_index  s   
z fix_vars.<locals>.get_name_indexrN   c                 S   r  r"   r"   r  r"   r"   r#   r    r  ro  c                 S   r  r"   r"   r  r"   r"   r#   r    s    rm  rn  c                       i | ]}| | qS r"   r"   rw   rU   allnamesr"   r#   r    r  c                    r  r"   r"   r  r  r"   r#   r    s    c                      s     j tuS r<   )r4   rP   r"   )rH   r   r"   r#   should_compute_arg  s   z$fix_vars.<locals>.should_compute_argrW   r   r   rV   rS   rX   rE   c                 3   s(    | ]}|v r| n | V  qd S r<   r"   r  )	freenamesvarnamesr"   r#   r    s
    
zfix_vars.<locals>.<genexpr>r   r      )r   r/   r-   re   rf   callable	itertoolscount
IndexErrorr   r   r.   r2   r4   rP   r3   r   r\  r'   r$  r1   	HAS_LOCALHAS_NAMEHAS_FREE	HAS_CONSTr  )r   r  r  r  r   rU   r  	arg_tupler"   )r  r  r  rH   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)rW   rV   rX   )	r4   rP   r1   r  r  r  r  r2   r3   )r   rg   r"   r"   r#   clear_instruction_args  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  ro  co_filenameco_namerN   co_qualnameco_firstlinenor{   co_linetabler  co_exceptiontablern  rm  )r   r   re   rf   )r#  r"   r"   r#   get_code_keys  s&   







r  transformationsr   r  c           	         sd   t  } fdd|D }t|d |d ksJ t |}t| |||}t|||\}}||fS )Nc                    s   i | ]}|t  |qS r"   )getattrrw   kr   r"   r#   r  1  ry   z)transform_code_object.<locals>.<dictcomp>ro  r  )r  r   cleaned_instructionsr   clean_and_assemble_instructions)	r   r  r  r#  r  r   tracer_outputr   bytecoder"   r  r#   r  )  s   

r  r#  c                    s&  t |  t|  t d  d< d }tjdkr&tj fdd|D  }|j}t|  |d d}|rAt	|  t
|  tt| }|s1t|  t|  d \}}tjd	k rX| d
< n| d< | d< t|  d< t|dh t  dh ksxJ tjdkrtt|  d< | tj fdd|D  fS )Nro  r  rN   c                    r:  r"   r"   r  r  r"   r#   rx   H      z3clean_and_assemble_instructions.<locals>.<listcomp>)r  Tr  r{   r  r  r  r  r  r  c                    r:  r"   r"   r  r  r"   r#   rx   d  r  )ri  rA  r   re   rf   typesCodeType_varname_from_opargr  r  r  r.   ry  r   r  r   r  r#  r   r7  )r   r#  r  r  tmp_codedirtyr  r   r"   r  r#   r  =  s:   



r  constsc                 C   s$   | D ]}|j dkr||j |_qd S )NKW_NAMES)r2   r3   r4   )r   r  rg   r"   r"   r#   populate_kw_names_argvalg  s
   
r  c                 C   s   t | |}t|S r<   )_cached_cleaned_instructions_clone_instructionsr   r  r   r"   r"   r#   r  o  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   r1   r2   r3   r4   r5   r6   r7   r9   r   r:   r;   rv   r"   r"   r#   rx   z  s     z'_clone_instructions.<locals>.<listcomp>)	dictrf  r   r:   r   r   r   r   r   )r   copiedremaprH   r   r"   r"   r#   r  w  s"   
r  c                 C   s   t ttt| }t| t| tjdkr#t	|| j
 t| j| t| t| |sbtjdk r6t| tjdk r@t| | tjdkr[t| tjdkrRt| tjdkr[t| tjrbt| tjdkrot| t| |S )NrN   rS   rE   )r   r  rL   r\   get_instructionsr   r  re   rf   r  r  r'  r  r
  rC  rH  rs  rR  rV  ra  r   &debug_force_graph_break_on_leaf_returnre  r  r  r  r"   r"   r#   r    s2   







r  	with_uuidc                 C   s4   |  dt t }|r|dt  dd7 }|S )Nr   -)r   _unique_id_counteruuiduuid4r  )rU   r  retr"   r"   r#   	unique_id  s   r  c                 C   s   d}| j |@ dkS )N    r   )r  )r   co_generatorr"   r"   r#   is_generator  s   r  fnvarname_mapnoreturnnoprefixc           
      C   s  t | j}t| |r#t|D ]\}}|jdkr"||d d } nq|D ]}d|_d|_|r:|j|v r:||j |_q%|rtj	dkrkg }|D ]"}|jdkrct
jd |_d|_|| |td qF|| qF|}g }|D ]}|jdkr{|| qot|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   NrS   RETURN_CONSTrm   RETURN_VALUEr   rz   rc  )r  __code__r  r   r2   r6   r9   r4   re   rf   r\   r]   r1   r   r_   r   r0  r3   rP   rh   r   )
r  r  r  r  r   rH   rg   rE  returns	jump_instr"   r"   r#   bytecode_from_template  sb   
'










r  )T)F)r   r<   )NTT)rD   r%  dataclassesr\   	functoolsr  re   r  r  collections.abcr   r   r   r   typingr   r   r   r	   r
   r   utils._backport_slotsr    r   bytecode_analysisr   r   r   r   utilsr   output_graphr   	dataclassr   r   rf   rL   rP   r/   r.   rZ   r-   r_   rh   rj   ro   rs   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'  r7  r9  r>  rA  rC  rF  rH  rR  rV  r\  ra  re  ri  r  rs  ry  r   r  r  r  r  haslocalr  hasnamer  hasfreer  hasconstr  r  r  r  	lru_cacher  r  r  r  r  r  r  r  r  r  r  r  r"   r"   r"   r#   <module>   s    




+'
;
7/



&
%
="*


7
,
M

	
&!





o,


*%
