o
    ڗi|,                     @   s   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 d dlm	Z	 d dl
mZmZmZmZ d dlmZ i Zdd ZeG dd	 d	Ze	d
dG dd deZG dd dedZdS )    N)ABCMetaabstractmethodabstractclassmethod)	dataclass)DictListTupleUnion)
ModuleTypec                 C   s   | t | j< | S )z9
    Register a descriptor into the descriptor table
    )_descriptor_table__name__)cls r   V/home/ubuntu/transcripts/venv/lib/python3.10/site-packages/triton/backends/compiler.pyregister_descriptor   s   
r   c                   @   s   e Zd ZdZdZd$ddZdd Zd$dd	Zd
d Zde	fddZ
de	fddZdd Zdd Zdd Zedd Zedeeeef  fddZedd Zedd Zed d! Zd"d# ZdS )%AttrsDescriptoraG  
    This class handles compile-time properties for specific function parameters.

    Different backends can add more properties to the common ones. The class
    contains two fields:

    `arg_properties`: a dictionary containing the different compile-time properties for different
        parameters. I.e., the dictionary is a map from property names to parameter indices
        {
        "prop0": (0, 2, 3)
        "prop1": (0, 4, 5)
        }
        Different backends might need different properties on those paraemters to enable
        specific optimizations. The common compile time properties contained in this class
        are :
        - "tt.divisibility", i.e., is the given parameter divisible by 16
        - "tt.equal_to_1", i.e., is the given parameter an integer constant 1

    `property_values`: a dictionary containing the value of the different compile-time properties, like:
        {
            "prop0": val0
            "prop1": val1
        }

    `constant_properties`: a set containing the properties that can be used to determine if a parameter is constant

    )divisibility_16
equal_to_1arg_propertiesproperty_valuesconstant_propertiesNc                 C   s8   i | _ i | _t | _| || | || |   dS )a  
        Initialize the compile-time properties

        We can initialize the AttrsDescriptor class by passing the list of params
        of the function and their `values`. The function will try to apply the properties
        to the values and save the parameters in the `arg_properties` list. If we don't pass
        either the `params` or the `values` we should initialize the class via an alternative method
        (see `from_dict` or `from_hints`)
        N)r   r   setr   _add_common_properties_add_backend_properties_init_slotsselfparamsvaluesr   r   r   __init__8   s   zAttrsDescriptor.__init__c                 C   s   d| j d< d| j d< | jd |du s|du rdS t|t|ks$J dd t||D | jd< dd t||D | jd< dS )	z$ Add common compile-time properties    ztt.divisibility   ztt.equal_toNc                 S   s,   g | ]\}}t |r|js|js|jqS r   )r   is_divisible_by_16do_not_specializedo_not_specialize_on_alignmentnum.0paramargr   r   r   
<listcomp>X   s    z:AttrsDescriptor._add_common_properties.<locals>.<listcomp>c                 S   s&   g | ]\}}t |r|js|jqS r   )r   is_equal_to_1r#   r%   r&   r   r   r   r*   ^   s    )r   r   addlenzipr   r   r   r   r   r   K   s   

z&AttrsDescriptor._add_common_propertiesc                 C   s   dS )zX This method is for different subclasses to implement their own compile-time properties Nr   r   r   r   r   r   d      z'AttrsDescriptor._add_backend_propertiesc                 C   s<   | j  D ]\}}t| |dd t| j|  | qdS )z$ Initialize the slots of this class ztt._N)r   itemssetattrremoveprefixstrr   )r   namevalr   r   r   r   h   s   &zAttrsDescriptor._init_slotsreturnc                 C   sJ   i }| j  D ]\}}| j| }|D ]}||g ||fg ||< qq|S )a  
        Get the function attributes as a dictionary.

        The returned dictionary will look like :
            {
            "arg0" : [(prop_name00, val00), (prop_name01, val01), ...)]}
            "arg1" : [(prop_name10, val10), (prop_name11, val11), ...)]}
            }
        )r   r1   r   get)r   attrs	prop_namearg_setprop_valr)   r   r   r   get_fn_attrsm   s   

zAttrsDescriptor.get_fn_attrsc                 C   s6   i }| j D ]}| j|g D ]	}| j| ||< qq|S )z9 Return a mapping of constant parameters to their values )r   r   r8   r   )r   	constantsr:   pr   r   r   get_constants~   s   
zAttrsDescriptor.get_constantsc                 C   sD   ddl }|| }|jD ]}|j|d |j|d qi |_|S )z? Return the same object, without properties marked as constantsr   N)copydeepcopyr   r   popr   )r   rA   cr:   r   r   r   filter_out_constants   s   

z$AttrsDescriptor.filter_out_constantsc                 C   sP   t | j g}|t | j g7 }|t | jg7 }t|}t|d	 S )Nutf-8)
sortedr   r   r   r   r4   hashlibsha256encode	hexdigest)r   r   keyr   r   r   hash   s
   zAttrsDescriptor.hashc                 C   s   | j t| jdS )zM
        Store the fields of this class in a serializable dictionary
        )r   r   )r   typer   r   r   r   r   to_dict   s   zAttrsDescriptor.to_dictc                 C   s:   t | d   }| d  D ]	\}}||j|< q|  |S )zB
        Create the object from a serializable dictionary
        r   r   )r   r1   r   r   )dataattrs_descriptorr:   	param_idsr   r   r   	from_dict   s
   zAttrsDescriptor.from_dicthintsc                    sB   |  }|j  D ]\}  fdd| D |j|< q|  |S )a  
        Create the class from a set of hints that are passed in.

        Instead of deducing the properties from a list of paramaters and values,
        the user can pass in a list of `hints=[(param_index, val)]` and if `val`
        matches one of the values of the properties (e.g., `prop_val[prop0]`),
        then we insert `param_index` into the correct list (e.g., in
        `arg_properties[prop0]`)
        c                    s   g | ]
\}}| kr|qS r   r   )r'   ihr<   r   r   r*      s    z.AttrsDescriptor.from_hints.<locals>.<listcomp>)r   r1   r   r   )r   rU   rR   r:   r   rX   r   
from_hints   s
   zAttrsDescriptor.from_hintsc                 C   s@   t | dr|  d dkS t| tr| d dkS | du rdS dS )z+ Return if the argument is a multiple of 16data_ptrr    r   NTF)hasattrrZ   
isinstanceintxr   r   r   r"      s   

z"AttrsDescriptor.is_divisible_by_16c                 C   s$   t | trt | ts| dkrdS dS )z' Return if the argument is a constant 1r!   TF)r\   r]   boolr^   r   r   r   r+      s   $zAttrsDescriptor.is_equal_to_1c                 C   s$   |r	t | r	dS t | rdS dS )ND1N)r   r"   r+   )r6   alignr   r   r   get_property_key   s
   
z AttrsDescriptor.get_property_keyc                 C   s   d|   dS )NzAttrsDescriptor.from_dict())rP   rO   r   r   r   __repr__   s   zAttrsDescriptor.__repr__)NN)r   
__module____qualname____doc__	__slots__r   r   r   r   r   r=   r@   rE   rM   rP   staticmethodrT   classmethodr   r   r]   rY   r"   r+   re   rg   r   r   r   r   r      s.    









r   T)frozenc                   @   s.   e Zd ZU eed< eeef ed< eed< dS )	GPUTargetbackendarch	warp_sizeN)r   rh   ri   r4   __annotations__r	   r]   r   r   r   r   ro      s   
 ro   c                   @   s   e Zd ZdeddfddZedefddZedefd	d
Z	e
defddZe
dedefddZe
dededdfddZe
dd Ze
deeef fddZdd Zdd ZdS )BaseBackendtargetr7   Nc                 C   s   || _ | |s
J d S N)ru   supports_target)r   ru   r   r   r   r      s   zBaseBackend.__init__binaryc                 C   s   t jt jtt j}t jd|   ddt j|ddd| g}|D ]<}|	dd }t j
|rat j|ratj|d	gtjd
}|d uratjd|dtjd}|d ura||df  S q%td|  )NTRITON__PATH third_partycudabin r   z	--version)stderrz.*release (\d+\.\d+).*rF   )flagsr!   zCannot find )ospathjoindirname__file__pardirenvironr8   uppersplitexistsisfile
subprocesscheck_outputSTDOUTresearchdecode	MULTILINEgroupRuntimeError)rx   base_dirpathsr?   r~   resultversionr   r   r   _path_to_binary   s   zBaseBackend._path_to_binaryc                 C      t rv   NotImplementedError)ru   r   r   r   rw      r/   zBaseBackend.supports_targetc                 C   r   )z,Returns a unique identifier for this backendr   rO   r   r   r   rM      s   zBaseBackend.hashoptionsc                 C   r   )z
        Converts an `options` dictionary into an arbitrary object and returns it.
        This function may contain target-specific heuristics and check the legality of the provided options
        r   )r   r   r   r   r   parse_options  s   zBaseBackend.parse_optionsstagesc                 C   r   )a  
        Populates `stages` dictionary with entries of the form:
        ir_name [str] => Function[(src: str, metadata: dict) -> str|bytes]
        The value of each entry may populate a `metadata` dictionary.
        Stages will be run sequentially (in inseriton order) and can communicate using `metadata`.
        All stages are expected to return a `str` object, except for the last stage which returns
        a `bytes` object for execution by the launcher.
        r   )r   r   r   r   r   r   
add_stages
  s   
zBaseBackend.add_stagesc                 C   r   )zK
        Load additional MLIR dialects into the provided `context`
        r   )r   contextr   r   r   load_dialects     zBaseBackend.load_dialectsc                 C   r   )z\
        Return a map of interface modules to their device-specific implementations
        r   rO   r   r   r   get_module_map  r   zBaseBackend.get_module_mapc                 C   s
   t ||S )z
        Return an attribute descriptor: given a set of parameters and arguments
        the descriptor stores a set of compile time properties that can improve code
        generation. Different backends might benefit from different properties
        )r   )r   r   argsr   r   r   get_attrs_descriptor$  s   
z BaseBackend.get_attrs_descriptorc                 C   s   t ||S )zZ
        Return the ascii key for a given argument with a given set of properties
        )r   re   )r   r)   rd   r   r   r   compute_spec_key,  s   zBaseBackend.compute_spec_key)r   rh   ri   ro   r   rl   r4   r   r   rw   r   rM   dictobjectr   r   r   r   r
   r   r   r   r   r   r   r   rt      s$    
rt   )	metaclass)r   r   rH   r   abcr   r   r   dataclassesr   typingr   r   r   r	   typesr
   r   r   r   r   ro   rt   r   r   r   r   <module>   s      @