U
    dS                     @   sZ  d dl mZ d dl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 d dlmZmZmZmZmZ d dlm  mZ d dlmZmZmZmZmZ d d	lmZ eed
ddZ eedddZ!eeedddZ"eedddZ#eddG dd deZ$eddG dd de$Z%eddG dd dZ&G dd dZ'eddG dd  d Z(dS )!    )ABC)ListOptionalUnion)	dataclass)method_with_native_function)BackendIndexNativeFunctionNativeFunctionsGroup)	BaseCTypeOptionalCTypeVectorCTypekernel_signaturedeviceTN)LazyIrSchemaLazyArgument	getValueTisValueTypetensorListValueTts_lowering_body)argreturnc                 C   sR  t | jrt| jtrr| jr(d| j S | jjtkrBd| j dS | jrd| j	 }| d| j dS d| j dS t| jt
r| jrd| j S d| j d| j dS td	| j d
nt| jt rt| jjt rd| jjj d| j d| j dS t| jt
rFt| jjtrFt| jjjtrFd| jjjj d| j d
S | j S dS )z
    Given a LazyArgument,
    generate a c++ string for materializing an rvalue of that arg for passing into
    a lazy Node constructor.
    Znode_lazy_Z_tensorlistz9(std::dynamic_pointer_cast<torch::lazy::SymbolicIntNode>(z .toSymbolicIntNode())->node_, 0)z->GetIrValue()z ? c10::make_optional(lazy_z->GetIrValue()) : c10::nullopt=TODO not sure if there are other valid types to handle here ()std::vector<>(z
.begin(), z.end())ztorch::lazy::ToOptionalVector<N)r   	lazy_type
isinstancer   is_wrapped_scalarnametyper   is_symint_or_listcpp_typer   AssertionErrorr   elem)r   r$    r'   9/tmp/pip-unpacked-wheel-ua33x9lu/torchgen/dest/lazy_ir.pynode_ctor_arg_rvalue_string   s@    

 "
r)   schemar   c                 C   s   dd |   D }d|S )zg
    Produce a formatted string with the arguments as passed into the constructor of a node class.
    c                 S   s   g | ]}t |qS r'   )r)   .0r   r'   r'   r(   
<listcomp>K   s    z$node_ctor_inputs.<locals>.<listcomp>, )filtered_argsjoin)r+   Znode_ctor_valuesr'   r'   r(   node_ctor_inputsG   s    r2   )r+   overload_namer   c              	   C   s   d dd | jddD }t|r:d| j d| d}nd	| j d}d
}| jrld| jj d| jj d}dt|  d| d| d| d	S )zK
    Generate code that falls back to eager conditioned on a predicate
    z,
                c                 S   s   g | ]}t |jqS r'   strr!   r,   r'   r'   r(   r.   V   s     z%gen_fallback_code.<locals>.<listcomp>T	generatorz	ATEN_OP2(r/   r   zATEN_OP( z || (z.has_value() && z->defined())z"
        if (force_eager_fallback(zI) {
            return at::native::call_fallback_fn<&ltc_eager_fallback, z>::call(
                z
            );
        }
)r1   r0   len	aten_nameZgenerator_argr!   aten_symbol)r+   r3   Zfallback_argsZaten_op_strZor_has_generatorr'   r'   r(   gen_fallback_codeQ   s$    r<   c                 C   s*   dh}| j |krd| j  dS d| j  S )NZsigmoid_backwardz#c10::Symbol::fromQualString("aten::z")z
at::aten::)r:   )r+   Zmissing_interned_stringsr'   r'   r(   r;   i   s
    
r;   T)frozenc                   @   s   e Zd ZU eed< eed< eeee	f e
e dddZeee	f edddZeee	f eedd	d
ZeedddZeee	f e
e dddZdS )	GenLazyIRbackend_index	node_basefr   c                 C   s"   t |tr|jjn|j}| |S N)r   r
   
functionalfuncgen)selfrB   rE   r'   r'   r(   __call__w   s    zGenLazyIR.__call__c                 C   s   dS )Nr8   r'   rG   rB   r'   r'   r(   lowering_function~   s    zGenLazyIR.lowering_functionrB   node_ctor_argsr   c                 C   s   d| dS )Nbool CanBeReused(z!) const {
    return false;
    }r'   )rG   rB   rL   r'   r'   r(   can_be_reused_function   s    z GenLazyIR.can_be_reused_functionr*   c              
   C   s   g }|j dddD ]^}t|jts.t|jtr>||j  qt|jtr^||j d qtd|j dqd	|}|j ddd}d	dd	 |D }| j
 d
t| d| dt|j d| d
S )NTFvaluesZscalars.value_or(kNullValue)zUnsupported type (z) - add support if necessaryr/   c                 S   s   g | ]}|j  qS r'   r!   r-   ar'   r'   r(   r.      s     z1GenLazyIR.node_base_ctor_call.<locals>.<listcomp>z(torch::lazy::OpKind(z),
              {z6}, std::move(shapes),
              /* num_outputs */ z#,
              torch::lazy::MHash(z)))r0   r   r   r   r   appendr!   r   r%   r1   r@   r;   r9   returns)rG   r+   Zbase_ctor_value_args_listr   Zbase_ctor_value_argsscalar_argsZscalar_hashesr'   r'   r(   node_base_ctor_call   s,     
zGenLazyIR.node_base_ctor_callc                 C   s  t |tr|jjn|j}t|}| }|jddd}|jddd}ddd |D }ddd |D }t|rxd	nd
}	ddd |D }
dd |jdddD }ddd |D }ddd |D }g }|D ]\}t |jt	r|
d|j d|j d|j d|j d	 q|
d|j d|j d qd|}d|j d| j dt| d|j d| d| | |	 d| d| d | j d!| d"| || d#| | d#|
 d| d$gS )%NTFrO   r/   c                 S   s$   g | ]}d |j   d|j qS )zconst z& r   r$   r!   r-   ir'   r'   r(   r.      s     z!GenLazyIR.gen.<locals>.<listcomp>z
,
        c                 S   s    g | ]}|j  d |j  dqS )(r   rR   rS   r'   r'   r(   r.      s     z,
r8   z
  c                 S   s@   g | ]8}|j  d kr$d|j dn|j   d|j dqS )zc10::string_viewzstd::string ; rY   rS   r'   r'   r(   r.      s   c                 S   s   g | ]}t |jtr|jqS r'   )r   r   r   r!   r,   r'   r'   r(   r.      s   c                 S   s   g | ]}d | dqS )z	bool has_z: 1;r'   r-   valuer'   r'   r(   r.      s     z
    c                 S   s   g | ]}d | d| dqS )Zhas_z = !!r]   r'   r_   r'   r'   r(   r.      s     zif (z.has_value()) {
      ss << ", z=" << z&.value();
    } else {
      ss << ", z=null";
    }z	ss << ", r]   zclass z
 : public zX {
 public:
  static torch::lazy::OpKind ClassOpKind() {
    return torch::lazy::OpKind(z
);
  }

  r\   z5, std::vector<torch::lazy::Shape>&& shapes)

      : 	
        z


  {
    zT
  }

  std::string ToString() const override {
    std::stringstream ss;
    ss << z::ToString();
    z
    return ss.str();
  }

  z

  z

};

)r   r
   rD   rE   r   r0   r1   r9   r   r   rU   r!   	node_namer@   r;   rX   rN   rJ   )rG   rB   rE   r+   all_args
value_argsrW   rL   Zscalar_initializersZcomma_if_scalar_initializersZscalar_declsZoptional_valuesZhas_optional_declsZhas_optional_defsZmembers_to_stringr   Zmembers_to_string_strr'   r'   r(   rF      s    $
		

zGenLazyIR.genN)__name__
__module____qualname__r   __annotations__r5   r   r   r
   r	   r   rH   rJ   rN   r   rX   rF   r'   r'   r'   r(   r>   r   s   

 r>   c                   @   s>   e Zd Zeeef edddZeeef eedddZdS )GenTSLazyIRrA   c                 C   s   dt | dS )Nztorch::lazy::TSOpVector Lower(std::shared_ptr<torch::jit::GraphFunction> function,
    torch::lazy::TSLoweringContext* loctx) const override {
    z
  }r   rI   r'   r'   r(   rJ      s    zGenTSLazyIR.lowering_functionrK   c                 C   s   t |tr|jjn|j}t|}g }|jD ]8}t |jtrP|d|j	 d q*|d|j	  q*|j
D ]}|d|j	 d|j	  qj|jD ]}|d|j	  q|jD ]}|d|j	 d|j	  qd|}d| d| dS )	Nzoperand(i++) == rQ   zthis->z == z &&
        rM   z() const {
    size_t i = 0;
    return (z);
  })r   r
   rD   rE   r   Zpositional_valuesr   r   rU   r!   Zpositional_scalarsZkeyword_valuesZkeyword_scalarsr1   )rG   rB   rL   rE   r+   Zvalue_comparsionr   Zvalue_comparsion_strr'   r'   r(   rN      s&    




z"GenTSLazyIR.can_be_reused_functionN)	re   rf   rg   r   r
   r	   r5   rJ   rN   r'   r'   r'   r(   ri      s
   
 ri   c                   @   s2  e Zd ZU eed< eed< eed< eed< eed< eed< eed< eed< eed	< eed
< eed< eed< eed< eed< eed< eeedddZ	eeedddZ
eeedddZeeedddZeeedddZeeedddZd&ee eddd Zeeedd!d"Zeeee d#d$d%ZdS )'GenLazyNativeFuncDefinitionclass_method_namer?   tensor_classgen_forced_fallback_codebackend_namespaceget_tensorlistget_tensor_or_wrap_numbertry_get_tensormetrics_countercreate_tensorcreate_from_first_tensorcreate_aten_from_ltc_tensortuple_aten_from_ltc_tensorslazy_tensor_ptrget_device_fn)rE   r+   r   c                 C   sV  |j ddd}g }|D ]2}|jrrt|jtrT|d|j d|j d|j d n|d|j d|j d	 q|jr|qqt|jtr|jj	t
kr|d
|j d| j d| j d|j d		 n2|| j d|j d| j d| j d|j d
 qt|jtr8|| j d|j d| j d| j d|j d
 qtd|j dqd|S )NTFrO   z
auto node_z = zm ?
                c10::make_optional(torch::lazy::LazyGraphExecutor::Get()->GetIrValueForScalarFromCodegen(*z!)):
                c10::nullopt;zY =
                torch::lazy::LazyGraphExecutor::Get()->GetIrValueForScalarFromCodegen();z
auto lazy_z_tensorlist = ::r\   z lazy_z, *common_device);z.value_or(at::Tensor()));r   r   ra   )r0   r    r   r   r   rU   r!   r#   r   r"   r   rn   ro   rw   rp   rq   r%   r1   )rG   rE   r+   rd   lazy_tensor_declsr   r'   r'   r(   r{   -  s:    
$**z-GenLazyNativeFuncDefinition.lazy_tensor_declsc                 C   s   | j rt||jjjdS dS )N)r3   r8   )rm   r<   rE   r!   r3   rG   rE   r+   r'   r'   r(   force_eager_fallbackX  s    z0GenLazyNativeFuncDefinition.force_eager_fallbackc                 C   s   | j  dS )Nr]   )rr   r|   r'   r'   r(   metrics]  s    z#GenLazyNativeFuncDefinition.metricsc                    s   |j ddd}|j ddd}dd |D }ttt  fdd|D }t|dksht|dkshtd| j d	d
||  d}d| dS )NTFrO   c                 S   s   g | ]}|j s|j qS r'   r    r!   rS   r'   r'   r(   r.   c  s      z:GenLazyNativeFuncDefinition.get_device.<locals>.<listcomp>c                    s   g | ]}|j  kr|jqS r'   )r   r!   rS   Zoptional_devicer'   r(   r.   e  s    
 r   z*Expected at least one Value or Device typer\   r/   r   zauto common_device = z8;
        TORCH_INTERNAL_ASSERT(common_device);
        )r0   r   r   r   r9   r%   rx   r1   )rG   rE   r+   rd   rW   value_types_namesZoptional_devicesZget_device_strr'   r   r(   
get_device`  s     


z&GenLazyNativeFuncDefinition.get_devicec                    s
  | j |}|d k	st| }t|j}|js:|jd k	rd}|dkr~tt	ddd d
 fddt|D }d	| d
 }d|j dd
dd |D  d| }nt|j|}	d|	j d}|d| d7 }dt	|j }
|dd
dd |D  d|
 d7 }|S )Nztstd::vector<torch::lazy::Shape> shapes{
        torch::lazy::Shape(out_meta.scalar_type(), out_meta.sizes().vec())};   )r[   r   c                 S   s   d|  d|  dS )Nztorch::lazy::Shape(std::get<z$>(out_meta).scalar_type(), std::get<z>(out_meta).sizes().vec())r'   )r[   r'   r'   r(   
this_shape}  s    z?GenLazyNativeFuncDefinition.shape_inference.<locals>.this_shape,c                    s   g | ]} |qS r'   r'   rZ   r   r'   r(   r.     s     z?GenLazyNativeFuncDefinition.shape_inference.<locals>.<listcomp>z'std::vector<torch::lazy::Shape> shapes{z};zauto out_meta = at::meta::r\   r/   c                 s   s   | ]}t |jV  qd S rC   r4   rS   r'   r'   r(   	<genexpr>  s     z>GenLazyNativeFuncDefinition.shape_inference.<locals>.<genexpr>z);
            z
            auto shapes = r]   z4
            TORCH_INTERNAL_ASSERT(shapes.size() == ry   zaten::zq
            if(torch::lazy::symbolicShapeEnabled()){
                std::vector<torch::jit::IValue> inputs = { c                 s   s   | ]}t |jV  qd S rC   r4   rS   r'   r'   r(   r     s     z( };
                char* schema_str = "z^";
                applySymbolicShapesOnLT(schema_str, inputs, shapes);
            }
        )r?   
get_kernelr%   r0   r9   rV   
structuredstructured_delegateintr5   r1   ranger:   ComputeShapeSignaturekernel
shape_callrE   )rG   rE   r+   metadatarc   returns_lengthZmeta_outZ
shapes_strZ	shape_str	shape_sigZfunc_schema_strr'   r   r(   shape_inferencer  s6    
 

z+GenLazyNativeFuncDefinition.shape_inferencec                 C   s8   t |}d|j d| d| || d|j d| dS )Nz3torch::lazy::NodePtr node = torch::lazy::ReuseNode<r   z$);
        if (!node) {
            z*
            node = torch::lazy::MakeNode<zE, std::move(shapes));
            CacheNode(node);
        }
        )r2   rb   r   )rG   rE   r+   Znode_ctor_input_strr'   r'   r(   build_ir_node  s    
z)GenLazyNativeFuncDefinition.build_ir_nodeN)first_tensor_namer   c                 C   s8   | j r&|d k	std| d| j S | j d| j S )Nz+Requires first tensor to create lazy tensor.rz   )rt   r%   rs   rn   )rG   r   r'   r'   r(   create_lazy_tensor  s    z.GenLazyNativeFuncDefinition.create_lazy_tensorc                 C   s   t |j}|jddd}dd |D }t |dkr:|d nd }d| j d| | d	}|d
krt |dksttdd| j d| d| | dt  d| j d| d}|j	j	j
s|j r|d
kstd| dd| d| d}|d7 }|S )NTFrO   c                 S   s   g | ]}|j s|j qS r'   r   rS   r'   r'   r(   r.     s      zBGenLazyNativeFuncDefinition.return_aten_tensor.<locals>.<listcomp>r   zauto result = z(
                z#(std::move(node), *common_device));r   z3Code below assumes there is at least one tensor argr   z,> lazy_tensors;
        for (int i = 0; i < z,; i++) {
            lazy_tensors.push_back(r\   z=(node, i), *common_device));
        }
        auto result = <z>(lazy_tensors);zqWe assumed there was no such case where an op is an in-place variant and has tuple outputs, but got tuple of len r   r   z2->SetInPlaceIrValue(node);
        auto& result = r]   z
        return result;)r9   rV   r0   ru   r   r%   rw   r   rv   r!   ZinplacerE   Z	is_out_fn)rG   rE   r+   r   rd   r   r   Z
bridge_strr'   r'   r(   return_aten_tensor  s<    





z.GenLazyNativeFuncDefinition.return_aten_tensor)rE   r   c                 C   s   t || j}| j|}|d k	s$tt|j}d|j| j d|j d d| 	|| d| 
|| d| || d| || d| || d| || dgS )Nz    rz   rR   z {
        ra   z
    };

    )r   r?   r   r%   r   rE   declrk   r   r}   r~   r   r{   r   r   )rG   rE   sigr   r+   r'   r'   r(   rH     s(    






z$GenLazyNativeFuncDefinition.__call__)N)re   rf   rg   r5   rh   r   boolr	   r   r{   r}   r~   r   r   r   r   r   r   r   r   rH   r'   r'   r'   r(   rj     s2   
+&

rj   c                   @   s`   e Zd ZdZeedddZedddZeddd	Ze	edd
dZ
e	edddZdS )r   zm
    Here we use the base name as the suffix of the signature to avoid generating for in-place variants.
    )kernel_namerB   c                 C   sT   t |j| _ddd t|jD | _ddd | jjddD | _|| _	d S )Nr/   c                 S   s   g | ]}|  qS r'   )r   rS   r'   r'   r(   r.     s     z2ComputeShapeSignature.__init__.<locals>.<listcomp>c                 S   s   g | ]}|j  qS r'   rR   r,   r'   r'   r(   r.     s     Tr6   )
r   rE   Z_ComputeShapeSignature__schemar1   
dispatcher	arguments%_ComputeShapeSignature__dispatch_argsr0   !_ComputeShapeSignature__call_args#_ComputeShapeSignature__kernel_name)rG   r   rB   r'   r'   r(   __init__  s    zComputeShapeSignature.__init__)r   c                 C   s   | j  d| j dS Nr\   r   )r   r   rG   r'   r'   r(   Z__decl_suffix  s    z#ComputeShapeSignature.__decl_suffixc                 C   s   | j  d| j dS r   )r   r   r   r'   r'   r(   Z__call_suffix  s    z#ComputeShapeSignature.__call_suffixc                 C   s   d|    S )Nz8TORCH_API std::vector<torch::lazy::Shape> compute_shape_)#_ComputeShapeSignature__decl_suffixr   r'   r'   r(   
shape_decl  s    z ComputeShapeSignature.shape_declc                 C   s   d|    S )Nztorch::lazy::compute_shape_)#_ComputeShapeSignature__call_suffixr   r'   r'   r(   r     s    z ComputeShapeSignature.shape_callN)re   rf   rg   __doc__r5   r	   r   r   r   propertyr   r   r'   r'   r'   r(   r     s   
r   c                   @   s6   e Zd ZU eed< eed< eeee dddZ	dS )GenLazyShapeInferenceDefinitionr?   rl   rA   c                 C   s^   t || j}| j|}|d k	s$t|jsV|jd krVt|j|}d|j	 dggS g S d S )N
r]   )
r   r?   r   r%   r   r   r   r   r1   r   )rG   rB   r   r   r   r'   r'   r(   rH     s    z(GenLazyShapeInferenceDefinition.__call__N)
re   rf   rg   r   rh   r5   r   r	   r   rH   r'   r'   r'   r(   r     s   
r   ))abcr   typingr   r   r   Zdataclassesr   Ztorchgen.contextr   Ztorchgen.modelr   r	   r
   Ztorchgen.api.typesr   r   r   r   r   Ztorchgen.api.dispatcherapir   Ztorchgen.api.lazyr   r   r   r   r   Ztorchgen.dest.lazy_ts_loweringr   r5   r)   r2   r<   r;   r>   ri   rj   r   r   r'   r'   r'   r(   <module>   s.   /
	 # C