U
    ,dI                  	   @   s  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	 d dl
mZ d dlmZ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 d dlmZ d dlmZ d d	lmZ d d
l m!Z! e"ddddddddgZ#dd Z$dd Z%dd Z&G dd de'Z(G dd dedZ)G dd de)Z*G d d! d!e*Z+G d"d# d#e*Z,G d$d% d%e'Z-d&d' Z.G d(d) d)e'Z/G d*d+ d+edZ0G d,d- d-e0Z1G d.d/ d/e1Z2G d0d1 d1e1Z3d2d3 Z4d4d5 Z5dS )6    N)abstractmethodABCMeta)utilsconfigcgutils)create_pass_manager_builder)remove_redundant_nrt_refct)rtsys)require_global_compiler_lock)NumbaInvalidConfigWarning)disassemble_elf_to_cfg)PassTimingsCollectionx86i386Zi486Zi586i686Zi786Zi886Zi986c                 C   s   |  dd }|tkS )N-r   )split_x86arch)triplearch r   6/tmp/pip-unpacked-wheel-eu7e0c37/numba/core/codegen.py_is_x86   s    r   c               	   C   sn   t jd} | sdS d}| D ]L}| }z|ttj| O }W q tk
rf   t	
d|t Y qX q|S )zParse refprune flags from the `config`.

    Invalid values are ignored an warn via a `NumbaInvalidConfigWarning`
    category.

    Returns
    -------
    flags : llvmlite.binding.RefPruneSubpasses
    ,r   zinvalid refprune flags )r   ZLLVM_REFPRUNE_FLAGSr   stripgetattrllZRefPruneSubpassesupperAttributeErrorwarningswarnr   )flagsvalitemr   r   r   _parse_refprune_flags    s    
r$   c           	         s   t jrzdd l}W n  tk
r2   d}t|Y qX ddlm ddlm} ddlm} ddl	m
  ddlm ||d}||  fd	d
}nt}td t| dd || td d S )Nr   z0Please install pygments to see highlighted dumps)	highlight)GasLexer)	LlvmLexer)Terminal256Formatter)by_colorscheme)llvmasmc                    s   t |    d d S )N)style)print)argr(   r)   r%   lexerr   r   printerH   s    

zdump.<locals>.printerzP================================================================================P   r   )r   ZHIGHLIGHT_DUMPSpygmentsImportError
ValueErrorr%   Zpygments.lexersr&   r'   Zpygments.formattersr(   Znumba.misc.dump_styler)   r-   center)	headerbodylangr3   msgZ	gas_lexerZ
llvm_lexerZ	lexer_mapr1   r   r/   r   dump8   s&    
r;   c                   @   s<   e Zd ZdZdd Zddd	ZdddZdd Zdd ZdS )_CFGa  
    Wraps the CFG graph for different display method.

    Instance of the class can be stringified (``__repr__`` is defined) to get
    the graph in DOT format.  The ``.display()`` method plots the graph in
    PDF.  If in IPython notebook, the returned image can be inlined.
    c                 K   s2   || _ || _|| _||}t|| _|| _d S N)cresnamepy_funcget_functionr   get_function_cfgdotkwargs)selfr>   r?   r@   rD   fnr   r   r   __init__[   s    
z_CFG.__init__NTF
   c	           K         sP  ddl ddlddl}	ddl}
ddlm} ddlm} ddlm	} ddl
m} d}|||||||||d}|||d	 d
d }||| | | |dd dd< dd< dd< dd< dd< dd< dd< dd< dd< d d!< d"d#< | j| j}| j }fd$d%}||
fd&d'}|| j| j|}d(}d)}d*d+}|	d,}d-}d.}d/}d0}d1}d2} d3}!d4d5 }"d6d7 i }#i }$ jr|
| j\||d8d9}%|%jd:d;}&|	|&d<}'d}(|'d= D ]})d>\|)d? }*|)d@ }+|)dA },|+|#|,< |*dBdC }*|*dD}-g }.dBd9}/||-dC }0|-}1|0dk	r2|0 d }2|2dE}3t|3dF}4g }5|jrڈd d dG}6ni }6|3D ]8}7||7 \}8}9|6|9dH}:|5 |4!|:|8|9 qd9"|5}/|-ddC }1dI};|. |;!dJ |1d #  dK 	
fdLdM}<|1dBd D ]X}=||=rq j$s jr|<|=|.}>|>dk	r|>\|j%r|&|=rd }?n|j'r
|&|=r
d }?n|j(r(|&|=r(d }?n|j)rF| &|=rFd }?nb|j*rd|!&|=rdd }?nD|j+r|&|=rd! }?n&|j,r|&|=rd# }?ndJ }?|?dJ k	s|s|"|=D ]}@|. !|?|@ qȐq|/r|. dN!|/ d9"|.}A|Ar&dO|(|Af }BdP!|B}*nd9}*|j-|+|*dQ q,dR|'kr|'dR D ]0}C|CdA },|CdSd}D|CdT |CdU |Df|$|,< qN|$. D ]L\},}C|#|CdB  }E|#|Cd  }F|CdV }G|Gdk	r|EdW|G 7 }E|/|E|F q|r g }H. D ]\}I}J|H dX!|J|I q|j-dYdZ!d9"|HdQ |dk	s4|dk	rD|j0|||d[ |jd\d;S )]z
        "Pretty" prints the DOT graph of the CFG.
        For explanation of the parameters see the docstring for
        numba.core.dispatcher::inspect_cfg.
        r   N)binding)List)SimpleNamespace)defaultdictF)increfdecrefreturnsraisesmeminfobranchesllvm_intrin_callsfunction_calls)pythonlineinfoc                 S   s   t |tr$| jD ]}t| || qnt |tr| D ]J\}}|| jkrTtd| t |trlt| || q6d}t|||f q6nNt |tr|D ](}|| jkrtd| qt| |d qnd}t|t| dS )z Parses the kwarg into a consistent format for use in configuring
            the Digraph rendering. _config is the configuration instance to
            update, kwarg is the kwarg on which to base the updates.
            zUnexpected key in kwarg: %sz$Unexpected value for key: %s, got:%sTz)Unhandled configuration type for kwarg %sN)	
isinstancebool__dict__setattrdictitemsr5   settype)_configkwargattrkvr:   r#   r   r   r   parse_config   s$    






z)_CFG.pretty_printer.<locals>.parse_configc                   S   s   dS )Nwhiter   r   r   r   r   <lambda>       z%_CFG.pretty_printer.<locals>.<lambda>ZorangemarkerZyellowrU   ZgreenZtruebrZredZfalsebrZcyanrM   Z	turquoiserN   Z	lightpinkraiseZlightseagreenrQ   ZpurplereturnZ	rosybrownrS   ZtomatorT   c                    sb   i }  d}|  D ]F}||}|dk	r| }|dk	rt|dksLt|d ||d < q|S )z Gets the metadata entries from the LLVM IR, these look something
            like '!123 = INFORMATION'. Returns a map of metadata key to metadata
            value, i.e. from the example {'!123': INFORMATION}z(^[!][0-9]+)(\s+=\s+.*)N      r   )compile
splitlinesmatchgroupslenAssertionError)llvm_strmdZmetadata_entryxro   g)rer   r   get_metadata   s    

z)_CFG.pretty_printer.<locals>.get_metadatac                    sj   d}t ||kr4d| d}t|t |d | } j| |d}|jdd |jddd	t| d
 |S )N   zCFG output filename "z9" exceeds maximum supported length, it will be truncated.)filenameZTB)Zrankdirnodenonez%s)shapefontsize)rq   r   r    r   ZDigraphra   str)r?   fnamer~   ZcmaxZwstrf)gvr   r   init_digraph   s    z)_CFG.pretty_printer.<locals>.init_digraphz
.*{(.*)}.*z.*<(.*)>(.*)z.*!dbg\s+(![0-9]+).*z7.*!DILocation\(line:\s+([0-9]+),\s+column:\s+([0-9]),.*z.*call void @llvm.dbg.value.*z@NRT_incref\bz@NRT_decref\bz@NRT_MemInfoz.*call.*@llvm\..*z.*call.*@.*zret i32.*\!ret_is_raise.*zret i32 [^1],?.*c                 S   s   t j| dddS )Nx   z... )widthsubsequent_indent)textwrapwrap)sr   r   r   r      s    z!_CFG.pretty_printer.<locals>.wrapc                 S   sz   d}t | |kr0tt| }d| d | |} t| } | dd} | dd} | dd} | d	d
} | dd} | S )Ni,  z{}...<hash={}>z\{z&#123;z\}z&#125;\z&#92;%z&#37;!z&#33;)rq   r   hashformathtmlescapereplace)r   nZhsr   r   r   clean   s    
z"_CFG.pretty_printer.<locals>.cleanz\l... Zdot_json)r   utf-8Zobjects)r   labelr?   Z_gvidrl   r   z\l|z<<td BGCOLOR="{}" BORDER="1" ALIGN="center" PORT="{}">{}</td>)TFre   zF<tr><td BGCOLOR="{}" BORDER="1" ALIGN="left" COLSPAN="{}">{}</td></tr>defaultzF<tr><td BGCOLOR="{}" BORDER="0" ALIGN="left" COLSPAN="{}">{}</td></tr>c                    s*  
 | }|dk	r&| }|dk	r&t|dks:t||d }	|d}|dk	r& |}|dk	r&t| dkst|| \}}|ks|kr& jrd}	|	|||f }
d |
}||  jrt	|d  }|d  }d |}|| ||fS dS )z
                Search line `l` for metadata associated with python or line info
                and inject it into `new_lines` if requested.
                Nrl   r   rk   zMarker %s, Line %s, column %srh   rU   )
ro   rp   rq   rr   getrV   r   appendrU   int)l	new_linesmatchedrv   rh   Z
debug_dataZldlinecolZmfmtZ	mark_linelnZlidxZsource_line)_interleaver   col_spancscur_colcur_linefirstlinenofmtlocation_entryrt   metadata_markersrc_coder   r   metadata_interleavei  s8    







z0_CFG.pretty_printer.<locals>.metadata_interleavez<tr>{}</tr>zS<table id="%s" BORDER="1" CELLBORDER="0" CELLPADDING="0" CELLSPACING="0">%s</table>z<{}>)r   edgesZtailportheadtailrk   z:%sz;<tr><td BGCOLOR="{}" BORDER="0" ALIGN="center">{}</td></tr>ZKeyzn<<table BORDER="1" CELLBORDER="1" CELLPADDING="2" CELLSPACING="1"><tr><td BORDER="0">Key:</td></tr>{}</table>>)rz   viewr   svg)1Zgraphvizrw   jsoninspectZllvmliterI   Znumba.typedrJ   typesrK   collectionsrL   r>   rA   r?   get_llvm_strrm   rU   getsourcelinesr@   rB   r   ZSourcepipeloadsdecoder   ro   rp   rq   rR   r   r   r   joinr   rV   rM   searchrN   rQ   rP   rO   rS   rT   r{   r\   edgerender)KrE   rz   r   render_formatr%   Z
interleaveZstrip_irZshow_keyr~   r   r   r   rJ   rK   rL   _defaultZ
_highlightrd   rF   rs   rx   r   r   Z
port_matchZport_jmp_matchZlocation_exprZ	dbg_valueZ
nrt_increfZ
nrt_decrefZnrt_meminfoZll_intrin_callsZll_function_callZll_raiseZ	ll_returnr   Znode_idsZedge_idsZraw_dotZ
json_bytesZjzonZidcobjr   r?   Zgvidlinesr   Z	port_liner   Zsliced_linesZportsZports_tokensZtdfmtZtbl_datacolorstoktargetvaluecolorZ	fmtheaderr   r   Zupdated_lineinfoZcolourru   Zdattabr   tpr   r   portZkey_tabrb   rc   r   )r   r   r   r   r   r   r   r   r   r   rt   r   rw   r   r   pretty_printerc   s>   	


















"+











 

z_CFG.pretty_printerpdfc                 C   s$   | j f |||d| j}|dS )a  
        Plot the CFG.  In IPython notebook, the return image object can be
        inlined.

        The *filename* option can be set to a specific path for the rendered
        output to write to.  If *view* option is True, the plot is opened by
        the system default application for the image format (PDF). *format* can
        be any valid format string accepted by graphviz, default is 'pdf'.
        )rz   r   r   r   r   rD   r   )rE   rz   r   r   Zrawbytr   r   r   display  s    

z_CFG.displayc                 C   s   | j f | jdS )Nr   r   rE   r   r   r   
_repr_svg_  s    z_CFG._repr_svg_c                 C   s   | j S r=   )rC   r   r   r   r   __repr__  s    z_CFG.__repr__)NNNTFFTrH   )Nr   F)	__name__
__module____qualname____doc__rG   r   r   r   r   r   r   r   r   r<   S   s           
   
r<   c                   @   s   e Zd ZdZdZdZdZdedddZe	dd Z
e	d	d
 Ze	dd Ze	dd Zdd Zdd Zdd Zdd Zedd Zedd Zedd Zedd Zedd  Zed!d" Zd#d$ Zd%d& Zd'd( Zd)S )*CodeLibraryz
    An interface for bundling LLVM code together and compiling it.
    It is tied to a *codegen* instance (e.g. JITCPUCodegen) that will
    determine how the LLVM code is transformed and linked together.
    F
CPUCodegen)codegenr?   c                 C   s6   || _ || _| jj d| jd}t|| _g | _d S )N())_codegen_name	__class__r   r   _recorded_timings_dynamic_globals)rE   r   r?   Zptc_namer   r   r   rG     s
    
zCodeLibrary.__init__c                 C   s   |    t| jdkS )Nr   )_ensure_finalizedrq   r   r   r   r   r   has_dynamic_globals  s    zCodeLibrary.has_dynamic_globalsc                 C   s   | j S r=   )r   r   r   r   r   recorded_timings  s    zCodeLibrary.recorded_timingsc                 C   s   | j S )z9
        The codegen object owning this library.
        )r   r   r   r   r   r   "  s    zCodeLibrary.codegenc                 C   s   | j S r=   )r   r   r   r   r   r?   )  s    zCodeLibrary.namec                 C   s   d| j t| f S )Nz<Library %r at 0x%x>)r?   idr   r   r   r   r   -  s    zCodeLibrary.__repr__c                 C   s   | j rtd| f d S )Nz+operation impossible on finalized object %r)
_finalizedRuntimeErrorr   r   r   r   _raise_if_finalized0  s    zCodeLibrary._raise_if_finalizedc                 C   s   | j s|   d S r=   )r   finalizer   r   r   r   r   5  s    zCodeLibrary._ensure_finalizedc                 C   s   |    | j|}|S )zC
        Create an LLVM IR module for use by this library.
        )r   r   _create_empty_modulerE   r?   	ir_moduler   r   r   create_ir_module9  s    zCodeLibrary.create_ir_modulec                 C   s   dS )zk
        Add a library for linking into this library, without losing
        the original library.
        Nr   rE   libraryr   r   r   add_linking_libraryA  s    zCodeLibrary.add_linking_libraryc                 C   s   dS )zC
        Add an LLVM IR module's contents to this library.
        Nr   )rE   r   r   r   r   add_ir_moduleH  s    zCodeLibrary.add_ir_modulec                 C   s   dS )z
        Finalize the library.  After this call, nothing can be added anymore.
        Finalization involves various stages of code optimization and
        linking.
        Nr   r   r   r   r   r   N  s    zCodeLibrary.finalizec                 C   s   dS )z5
        Return the function named ``name``.
        Nr   rE   r?   r   r   r   rA   V  s    zCodeLibrary.get_functionc                 C   s   dS )zA
        Get the human-readable form of the LLVM module.
        Nr   r   r   r   r   r   \  s    zCodeLibrary.get_llvm_strc                 C   s   dS )z2
        Get the human-readable assembly.
        Nr   r   r   r   r   get_asm_strb  s    zCodeLibrary.get_asm_strc                 C   s   d| _ d | _d| _d S )NTF)_object_caching_enabled_compiled_object	_compiledr   r   r   r   enable_object_cachingl  s    z!CodeLibrary.enable_object_cachingc                 C   s2   | j std| f | jd kr,td| f | jS )N object caching not enabled in %szno compiled object yet for %s)r   r5   r   r   r   r   r   r   _get_compiled_objectq  s
    
z CodeLibrary._get_compiled_objectc                 C   s8   | j std| f | jr(td| f || _d| _d S )Nr   zlibrary already compiled: %sT)r   r5   r   r   _disable_inspection)rE   r   r   r   r   _set_compiled_objectx  s    z CodeLibrary._set_compiled_objectN)r   r   r   r   r   r   r   r   rG   propertyr   r   r   r?   r   r   r   r   r   r   r   r   rA   r   r   r   r   r   r   r   r   r   r     s@   









	r   )	metaclassc                       s   e Zd Z fddZdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd2d"d#Zd$d% Zed&d' Zed(d) Zed*d+ Zd,d- Zd.d/ Zed0d1 Z  ZS )3CPUCodeLibraryc                    sH   t  || g | _tt| j| j| _	t
| j| j	_d | _d S r=   )superrG   _linking_librariesr   parse_assemblyr   r   r   r?   _final_moduler   normalize_ir_text_shared_module)rE   r   r?   r   r   r   rG     s    zCPUCodeLibrary.__init__c                 C   sp   | j j|_| j |P}|jD ]B}d|j}| j|  |  |	| |
  W 5 Q R X qW 5 Q R X dS )zP
        Internal: run function-level optimizations inside *ll_module*.
        zFunction passes on N)r   _data_layoutdata_layout_function_pass_manager	functionsr?   r   record
initializerunr   )rE   	ll_moduleZfpmfuncrb   r   r   r   _optimize_functions  s    


z"CPUCodeLibrary._optimize_functionsc              	   C   sn   d}| j | | jj| j W 5 Q R X tjs>t| j| _d}| j | | jj	| j W 5 Q R X dS )zA
        Internal: optimize this library's final module.
        z/Module passes (cheap optimization for refprune)z!Module passes (full optimization)N)
r   r  r   
_mpm_cheapr  r  r   LLVM_REFPRUNE_PASSr   	_mpm_full)rE   Z
cheap_nameZ	full_namer   r   r   _optimize_final_module  s    z%CPUCodeLibrary._optimize_final_modulec                 C   s   |    | jdk	r| jS | j}g }d}|jD ],}|d7 }|js,|jtjjkr,|	|j
 q,|dkrptd| f |r| }|D ]}d||_q|| _|S )a:  
        Internal: get a LLVM module suitable for linking multiple times
        into another library.  Exported functions are made "linkonce_odr"
        to allow for multiple definitions, inlining, and removal of
        unused exports.

        See discussion in https://github.com/numba/numba/pull/890
        Nr   rl   z7library unfit for linking: no available functions in %sZlinkonce_odr)r   r  r  r
  is_declarationlinkager   ZLinkageexternalr   r?   r   clonerA   )rE   modZto_fixZnfuncsrF   r?   r   r   r   _get_module_for_linking  s(    	

z&CPUCodeLibrary._get_module_for_linkingc                 C   s   |   | j| d S r=   )r   r  r   r   r   r   r   r     s    z"CPUCodeLibrary.add_linking_libraryc                 C   sN   |    t|tjsttt|}t	|}|j
|_
|  | | d S r=   )r   rW   llvmirModulerr   r   r  r   r   r  r?   verifyadd_llvm_module)rE   r   irr  r   r   r   r     s    
zCPUCodeLibrary.add_ir_modulec                 C   s(   |  | tjst|}| j| d S r=   )r  r   r  r   r  link_in)rE   r  r   r   r   r    s    
zCPUCodeLibrary.add_llvm_modulec                 C   s   t   | j  |   tjr4td| j |  d t	 }| j
D ]*}||kr@|| | jj| dd q@|   | j  |   d S )NzFUNCTION OPTIMIZED DUMP %sr*   T)preserve)r
   r   _check_llvm_bugsr   r   ZDUMP_FUNC_OPTr;   r?   r   r]   r  addr  r   r  r  r  _finalize_final_module)rE   seenr   r   r   r   r     s&    

 

 
zCPUCodeLibrary.finalizec                 C   s,   | j jD ]}|jdr| j|j qd S )Nznumba.dynamic.globals)r  global_variablesr?   
startswithr   r   )rE   r   r   r   r   _finalize_dynamic_globals  s    z(CPUCodeLibrary._finalize_dynamic_globalsc                 C   s8   | j jD ]*}|jr|jdrd}t||jqd S )NZ	_ZN5numbazSymbol {} not linked properly)r  r
  r  r?   r'  rr   r   )rE   rF   r:   r   r   r   _verify_declare_only_symbols  s    z+CPUCodeLibrary._verify_declare_only_symbolsc                 C   s   |    |   t| | j_| j| j}|r<t| | | 	  d| _
tjrftd| j |  d tjrtd| j |  d dS )z?
        Make the underlying LLVM module ready to use.
        TzOPTIMIZED DUMP %sr*   zASSEMBLY %sr+   N)r(  r)  weakrefproxyr  _CPUCodeLibrary__libraryr   _add_moduler   _finalize_specificr   r   ZDUMP_OPTIMIZEDr;   r?   r   ZDUMP_ASSEMBLYr   )rE   cleanupr   r   r   r$    s    z%CPUCodeLibrary._finalize_final_modulec                 c   s"   | j }|jD ]}|js|V  qdS )zj
        Get all functions defined in the library.  The library must have
        been finalized.
        N)r  r
  r  )rE   r  rF   r   r   r   get_defined_functions'  s    
z$CPUCodeLibrary.get_defined_functionsc                 C   s   | j |S r=   )r  rA   r   r   r   r   rA   1  s    zCPUCodeLibrary.get_functionc                 C   s   | j rtd d S )Nz@Inspection disabled for cached code. Invalid result is returned.)r   r   r    r   r   r   r    _sentry_cache_disable_inspection4  s    z/CPUCodeLibrary._sentry_cache_disable_inspectionc                 C   s   |    t| jS r=   )r1  r   r  r   r   r   r   r   9  s    zCPUCodeLibrary.get_llvm_strc                 C   s   |    t| jj| jS r=   )r1  r   r   _tmZemit_assemblyr  r   r   r   r   r   =  s    zCPUCodeLibrary.get_asm_strNc                 K   s   |    t| ||f|S )z=
        Get control-flow graph of the LLVM function
        )r1  r<   )rE   r?   r@   rD   r   r   r   rB   A  s    zCPUCodeLibrary.get_function_cfgc                 C   s   |   }t||S )aa  
        Get the CFG of the disassembly of the ELF object at symbol mangled_name.

        Requires python package: r2pipe
        Requires radare2 binary on $PATH.
        Notebook rendering requires python package: graphviz
        Optionally requires a compiler toolchain (via pycc) to link the ELF to
        get better disassembly results.
        )r   r   )rE   Zmangled_nameZelfr   r   r   get_disasm_cfgH  s    
zCPUCodeLibrary.get_disasm_cfgc           	      C   s   ddl m} ddlm} ddlm} |||}td | D ]~}|d dkr@t|	 dd	 d
}td |D ]L}|j
s|qptd|j
 |d |d ||d d ||d d f  qpq@t  dS )zw
        Dump the symbol table of an ELF file.
        Needs pyelftools (https://github.com/eliben/pyelftools)
        r   )ELFFile)descriptions)BytesIOz	ELF file:Zsh_typeZ
SHT_SYMTABc                 S   s   | j S r=   r?   )symr   r   r   rf   b  rg   z*CPUCodeLibrary._dump_elf.<locals>.<lambda>)keyz    symbols:z/    - %r: size=%d, value=0x%x, type=%s, bind=%sst_sizeZst_valueZst_infor^   bindN)Zelftools.elf.elffiler4  Zelftools.elfr5  ior6  r-   Ziter_sectionssortedZiter_symbolsr?   r   Zdescribe_symbol_typeZdescribe_symbol_bind)	clsbufr4  r5  r6  r   secsymbolsr8  r   r   r   	_dump_elfU  s*    
zCPUCodeLibrary._dump_elfc                 C   s8   z
|j }W n tk
r    Y dS X |jr4d|_||_dS )zB
        `ll_module` was compiled into object code `buf`.
        NT)r,  r   r   r   r   )r>  r  r?  rE   r   r   r   _object_compiled_hookp  s    
z$CPUCodeLibrary._object_compiled_hookc                 C   sB   z
|j }W n tk
r    Y dS X |jr>|jr>|j}d|_|S dS )z>
        Return a cached object code for `ll_module`.
        N)r,  r   r   r   )r>  r  rE   r?  r   r   r   _object_getbuffer_hook}  s    
z%CPUCodeLibrary._object_getbuffer_hookc                 C   s   |    | jd| j fS )zX
        Serialize this library using its bitcode as the cached representation.
        bitcode)r   r?   r  
as_bitcoder   r   r   r   serialize_using_bitcode  s    z&CPUCodeLibrary.serialize_using_bitcodec                 C   s(   |    |  |   f}| jd|fS )z
        Serialize this library using its object code as the cached
        representation.  We also include its bitcode for further inlining
        with other libraries.
        object)r   r   r  rF  r?   )rE   datar   r   r   serialize_using_object_code  s
    
z*CPUCodeLibrary.serialize_using_object_codec           	      C   s   |\}}}| |}t|| s"t|dkrBt||_|  |S |dkr|\}}|  || t||_	|  |j
j|j	 |S td|f d S )NrE  rH  z!unsupported serialization kind %r)create_libraryrW   rr   r   Zparse_bitcoder  r$  r   r   r  r   _engine_load_defined_symbolsr5   )	r>  r   stater?   kindrI  rE   Zobject_codeZshared_bitcoder   r   r   _unserialize  s     


zCPUCodeLibrary._unserialize)N)r   r   r   rG   r  r  r  r   r   r  r   r(  r)  r$  r0  rA   r1  r   r   rB   r3  classmethodrB  rC  rD  rG  rJ  rP  __classcell__r   r   r  r   r     s8   #	




r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )AOTCodeLibraryc                 C   s   |    | jj| jS )z
        Return this library as a native object (a bytestring) -- for example
        ELF under Linux.

        This function implicitly calls .finalize().
        )r   r   r2  Zemit_objectr  r   r   r   r   emit_native_object  s    z!AOTCodeLibrary.emit_native_objectc                 C   s   |    | j S )zz
        Return this library as LLVM bitcode (a bytestring).

        This function implicitly calls .finalize().
        )r   r  rF  r   r   r   r   emit_bitcode  s    zAOTCodeLibrary.emit_bitcodec                 C   s   d S r=   r   r   r   r   r   r.    s    z!AOTCodeLibrary._finalize_specificN)r   r   r   rT  rU  r.  r   r   r   r   rS    s   
	rS  c                   @   s   e Zd Zdd Zdd ZdS )JITCodeLibraryc                 C   s0   |    | jj}||sdS | jj|S dS )a  
        Generate native code for function named *name* and return a pointer
        to the start of the function (as an integer).

        This function implicitly calls .finalize().

        Returns
        -------
        pointer : int
            - zero (null) if no symbol of *name* is defined by this code
              library.
            - non-zero if the symbol is defined.
        r   N)r   r   rL  is_symbol_definedget_function_address)rE   r?   eer   r   r   get_pointer_to_function  s
    
z&JITCodeLibrary.get_pointer_to_functionc              	   C   s6   | j | j | jd | j j  W 5 Q R X d S )NzFinalize object)r   _scan_and_fix_unresolved_refsr  r   r  rL  finalize_objectr   r   r   r   r.    s    z!JITCodeLibrary._finalize_specificN)r   r   r   rZ  r.  r   r   r   r   rV    s   rV  c                   @   s4   e Zd ZdZdZdd Zdd Zdd Zd	d
 ZdS )RuntimeLinkerzP
    For tracking unresolved symbols generated at runtime due to recursion.
    z.numba.unresolved$c                 C   s   t  | _t | _g | _d S r=   )r   Z
UniqueDict_unresolvedr]   _defined	_resolvedr   r   r   r   rG     s    
zRuntimeLinker.__init__c                 C   st   | j }|jD ]b}|j|r|jt|d }||jr<qtjd}t	
|}||t	| || j|< qdS )zr
        Scan and track all unresolved external symbols in the module and
        allocate memory for it.
        NZnrt_unresolved_abort)PREFIXr&  r?   r'  rq   rW  r	   r   rZ  ctypesc_void_padd_global_mapping	addressofr^  )rE   moduleengineprefixr   r8  Zabortfnptrr   r   r   scan_unresolved_symbols  s    

z%RuntimeLinker.scan_unresolved_symbolsc                 C   s$   |j D ]}|js| j|j qdS )z5
        Scan and track all defined symbols.
        N)r
  r  r_  r#  r?   )rE   rf  rF   r   r   r   scan_defined_symbols  s    
z"RuntimeLinker.scan_defined_symbolsc                    sT    fdd j D }|D ]6}||} j | }||_ j||f  j |= qdS )z=
        Fix unresolved symbols if they are defined.
        c                    s   g | ]}| j kr|qS r   )r_  ).0r?   r   r   r   
<listcomp>  s     
 z)RuntimeLinker.resolve.<locals>.<listcomp>N)r^  rX  r   r`  r   )rE   rg  pendingr?   fnptrri  r   r   r   resolve  s    

zRuntimeLinker.resolveN)	r   r   r   r   ra  rG   rj  rk  rp  r   r   r   r   r]    s   r]  c                    s   t   fdd}|S )Nc                    s    | j f||S r=   )_ee)rE   argsrD   oldr   r   wrapper"  s    z_proxy.<locals>.wrapper)	functoolswraps)rt  ru  r   rs  r   _proxy!  s    rx  c                   @   sh   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Ze	e
jjZe	e
jjZe	e
jjZe	e
jjZdS )	JitEnginezWraps an ExecutionEngine to provide custom symbol tracking.
    Since the symbol tracking is incomplete  (doesn't consider
    loaded code object), we are not putting it in llvmlite.
    c                 C   s   || _ t | _d S r=   )rq  r]   _defined_symbols)rE   rY  r   r   r   rG   -  s    
zJitEngine.__init__c                 C   s
   || j kS )z/Is the symbol defined in this session?
        )rz  r   r   r   r   rW  :  s    zJitEngine.is_symbol_definedc                 C   s.   |j |jfD ]}|  jdd |D O  _qdS )z(Extract symbols from the module
        c                 S   s   h | ]}|j s|jqS r   )r  r?   )rl  r   r   r   r   	<setcomp>C  s    z2JitEngine._load_defined_symbols.<locals>.<setcomp>N)r
  r&  rz  )rE   r  Zgsetsr   r   r   rM  ?  s    zJitEngine._load_defined_symbolsc                 C   s   |  | | j|S )zXOverride ExecutionEngine.add_module
        to keep info about defined symbols.
        )rM  rq  
add_modulerE   rf  r   r   r   r|  F  s    
zJitEngine.add_modulec                 C   s   | j |j | j||S )z`Override ExecutionEngine.add_global_mapping
        to keep info about defined symbols.
        )rz  r#  r?   rq  rd  )rE   r   addrr   r   r   rd  M  s    zJitEngine.add_global_mappingN)r   r   r   r   rG   rW  rM  r|  rd  rx  r   ZExecutionEngineset_object_cacher\  rX  get_global_value_addressr   r   r   r   ry  (  s   
ry  c                   @   sD   e Zd ZdZedd Zedd Zedd Zdd	 Z	d
d Z
dS )CodegenaM  
    Base Codegen class. It is expected that subclasses set the class attribute
    ``_library_class``, indicating the CodeLibrary class for the target.

    Subclasses should also initialize:

    ``self._data_layout``: the data layout for the target.
    ``self._target_data``: the binding layer ``TargetData`` for the target.
    c                 C   s   dS )zD
        Create a new empty module suitable for the target.
        Nr   r   r   r   r   r   j  s    zCodegen._create_empty_modulec                 C   s   dS )zu
        Add a module to the execution engine. Ownership of the module is
        transferred to the engine.
        Nr   r}  r   r   r   r-  p  s    zCodegen._add_modulec                 C   s   | j S )zJ
        The LLVM "target data" object for this codegen instance.
        )_target_datar   r   r   r   target_dataw  s    zCodegen.target_datac                 K   s   | j | |f|S )zb
        Create a :class:`CodeLibrary` object for use with this codegen
        instance.
        )_library_class)rE   r?   rD   r   r   r   rK  ~  s    zCodegen.create_libraryc                 C   s   | j | |S r=   )r  rP  )rE   Z
serializedr   r   r   unserialize_library  s    zCodegen.unserialize_libraryN)r   r   r   r   r   r   r-  r   r  rK  r  r   r   r   r   r  _  s   



r  c                   @   sl   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )r   c                 C   sB   t   d | _tt| || _d| j_t | _	| 
| j d S )NZglobal_codegen_module)initialize_llvmr  r   r  r   r   _llvm_moduler?   r]  	_rtlinker_init)rE   module_namer   r   r   rG     s    zCPUCodegen.__init__c                 C   s   t |jg kstdtjt }ttj	d}| 
 | _| | |jf |}t||}tjrl|  || _t|| _|j| _t| j| _| jddddd| _|  | _| j| jj| jj d S )NzModule isn't empty)optFr   cheap)loop_vectorizeslp_vectorizer  cost)listr&  rr   r   TargetZfrom_tripleget_process_tripler[   r   OPT_customize_tm_features_tm_features_customize_tm_optionscreate_target_machineZcreate_mcjit_compilerZENABLE_PROFILINGZenable_jit_eventsr2  ry  rL  r  r  r   r  _module_pass_managerr  r  r  r  rC  rD  )rE   llvm_moduler   Z
tm_optionstmrg  r   r   r   r    s,    



zCPUCodegen._initc                 C   s,   t t|}t |_| jr(| j|_|S r=   )	r  r  r   r  r   r  r   r  r  r   r   r   r   r     s
    
zCPUCodegen._create_empty_modulec              	   K   s   t  }| j| |dd }| jf |}|| W 5 Q R X |d k	rt|dkrttjdkrt|	  |
  |  tjr|t  |S )Nr  r  r   )r   Zcreate_module_pass_managerr2  add_analysis_passespop_pass_manager_builderpopulater   r  Zadd_loop_rotate_passZadd_licm_passZadd_cfg_simplification_passr  add_refprune_passr$   )rE   rD   pmr  pmbr   r   r   r    s    zCPUCodegen._module_pass_managerc              	   K   sN   t |}| j| | jf |}|| W 5 Q R X tjrJ|t	  |S r=   )
r   Zcreate_function_pass_managerr2  r  r  r  r   r  r  r$   )rE   r  rD   r  r  r   r   r   r	    s    
z!CPUCodegen._function_pass_managerc                 K   sD   | dtj}| dtj}| dtj}tf |||d|}|S )a  
        Create a PassManagerBuilder.

        Note: a PassManagerBuilder seems good only for one use, so you
        should call this method each time you want to populate a module
        or function pass manager.  Otherwise some optimizations will be
        missed...
        r  r  r  )r  r  r  )r  r   r  ZLOOP_VECTORIZEZSLP_VECTORIZEr   )rE   rD   	opt_levelr  r  r  r   r   r   r    s    	z CPUCodegen._pass_manager_builderc                 C   sZ   d}t |}t|}d|ks&d|kr*dS d|krHt }td|f td|f dS )z<
        Guard against some well-known LLVM bug(s).
        zo
            define double @func()
            {
                ret double 1.23e+01
            }
            z12.3z1.23Nz1.0zLLVM will produce incorrect floating-point code in the current locale %s.
Please read https://numba.readthedocs.io/en/stable/user/faq.html#llvm-locale-bug for more information.zUnexpected IR:
%s
)r   r  r   locale	getlocaler   rr   )rE   r  r  Zir_outlocr   r   r   r"    s    	
zCPUCodegen._check_llvm_bugsc                 C   s   | j j|  | jfS )zP
        Return a tuple unambiguously describing the codegen behaviour.
        )r  r   _get_host_cpu_namer  r   r   r   r   magic_tuple	  s    zCPUCodegen.magic_tuplec                 C   s.   | j || j | j | | j | j d S r=   )r  rj  rL  rk  rp  r}  r   r   r   r[    s    z(CPUCodegen._scan_and_fix_unresolved_refsc                 C   sp   t d }| jj| }|j}z||}W n* tk
rX   t j|||d}d|_	Y nX |
||| S )N   r7  r  )r  ZIntTypeZ
as_pointerr  ra  rf  Z
get_globalKeyErrorZGlobalVariabler  Zbitcastload)rE   ZbuilderZfntyr?   ZvoidptrZptrnameZllvm_modro  r   r   r   insert_unresolved_ref  s    z CPUCodegen.insert_unresolved_refc                 C   s   t jd krt S t jS r=   )r   ZCPU_NAMEr   Zget_host_cpu_namer   r   r   r   r  !  s    
zCPUCodegen._get_host_cpu_namec                 C   s   t jd k	rt jS t S r=   )r   ZCPU_FEATURESget_host_cpu_featuresr   r   r   r   _get_host_cpu_features&  s    
z!CPUCodegen._get_host_cpu_featuresN)r   r   r   rG   r  r   r  r	  r  r"  r  r[  r  r  r  r   r   r   r   r     s   
	r   c                   @   s6   e Zd ZdZeZdddZdd Zdd Zd	d
 Z	dS )AOTCPUCodegenzp
    A codegen implementation suitable for Ahead-Of-Time compilation
    (e.g. generation of object files).
    Nc                 C   s   |pd| _ t| | d S Nr   )	_cpu_namer   rG   )rE   r  cpu_namer   r   r   rG   4  s    
zAOTCPUCodegen.__init__c                 C   s<   | j }|dkr|  }||d< d|d< d|d< | j|d< d S )Nhostcpupicrelocr   	codemodelfeatures)r  r  r  )rE   optionsr  r   r   r   r  9  s    z#AOTCPUCodegen._customize_tm_optionsc                 C   s   dS r  r   r   r   r   r   r  B  s    z$AOTCPUCodegen._customize_tm_featuresc                 C   s   d S r=   r   r}  r   r   r   r-  G  s    zAOTCPUCodegen._add_module)N)
r   r   r   r   rS  r  rG   r  r  r-  r   r   r   r   r  ,  s   
	r  c                   @   s4   e Zd ZdZeZdd Zdd Zdd Zdd	 Z	d
S )JITCPUCodegenzI
    A codegen implementation suitable for Just-In-Time compilation.
    c                 C   sz   |   |d< tj j}|dr(d}n|dr8d}nd}||d< d|d	< | j|d
< ttjj	}d|j
krvd|d< d S )Nr  r   Zstaticppcr  r   r  Z
jitdefaultr  r  ZjitT)r  r   r  Zfrom_default_tripler?   r'  r  r   Zpysignaturer  
parameters)rE   r  r   Zreloc_modelsigr   r   r   r  R  s    



z#JITCPUCodegen._customize_tm_optionsc                 C   s   |   S r=   )r  r   r   r   r   r  m  s    z$JITCPUCodegen._customize_tm_featuresc                 C   s   | j | d S r=   )rL  r|  r}  r   r   r   r-  q  s    zJITCPUCodegen._add_modulec                 C   s2   | j |}tjd |}tt||d< dS )zrSet the environment address.

        Update the GlobalVariable named *env_name* to the address of *env*.
        rl   r   N)rL  r  rb  rc  from_addressr   )rE   env_nameenvZgvaddrZenvptrr   r   r   set_envy  s    zJITCPUCodegen.set_envN)
r   r   r   r   rV  r  r  r  r-  r  r   r   r   r   r  K  s   r  c                   C   s   t   t   t   dS )z Safe to use multiple times.
    N)r   r  Zinitialize_native_targetZinitialize_native_asmprinterr   r   r   r   r    s    r  c                  C   sR   zt  } W n tk
r"   Y dS X tjsF| D ]}|dr.d| |< q.|  S dS )z~Get host CPU features using LLVM.

    The features may be modified due to user setting.
    See numba.config.ENABLE_AVX.
    r   ZavxFN)r   r  r   r   Z
ENABLE_AVXr'  flatten)r  rb   r   r   r   r    s    

r  )6r   rv  r  r*  rb  r   r   Zllvmlite.bindingrI   r   Zllvmlite.irr  r  abcr   r   Z
numba.corer   r   r   Znumba.core.llvm_bindingsr   Znumba.core.runtime.nrtoptr   Znumba.core.runtimer	   Znumba.core.compiler_lockr
   Znumba.core.errorsr   Znumba.misc.inspectionr   Znumba.misc.llvm_pass_timingsr   	frozensetr   r   r$   r;   rH  r<   r   r   rS  rV  r]  rx  ry  r  r   r  r  r  r  r   r   r   r   <module>   sX       6{  577* $8