Adding docstrings for some of llnumba.
This commit is contained in:
parent
99c9a1f204
commit
fe1ba06698
4 changed files with 68 additions and 0 deletions
|
|
@ -11,7 +11,17 @@ from control_flow import ControlFlowGraph
|
|||
# ______________________________________________________________________
|
||||
|
||||
class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
||||
'''Visitor responsible for traversing a bytecode flow object and
|
||||
building a control flow graph (CFG).
|
||||
|
||||
The primary purpose of this transformation is to create a CFG,
|
||||
which is used by later transformers for dataflow analysis.
|
||||
'''
|
||||
def visit (self, flow, nargs = 0, *args, **kws):
|
||||
'''Given a bytecode flow, and an optional number of arguments,
|
||||
return a :py:class:`numba.llnumba.control_flow.ControlFlowGraph`
|
||||
instance describing the full control flow of the bytecode
|
||||
flow.'''
|
||||
self.nargs = nargs
|
||||
ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws)
|
||||
del self.nargs
|
||||
|
|
@ -73,6 +83,8 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
|||
# ______________________________________________________________________
|
||||
|
||||
def build_cfg (func):
|
||||
'''Given a Python function, create a bytecode flow, visit the flow
|
||||
object, and return a control flow graph.'''
|
||||
import byte_flow
|
||||
return ControlFlowBuilder().visit(
|
||||
byte_flow.build_flow(func),
|
||||
|
|
|
|||
15
byte_flow.py
15
byte_flow.py
|
|
@ -10,6 +10,19 @@ import opcode_util
|
|||
# ______________________________________________________________________
|
||||
|
||||
class BytecodeFlowBuilder (BytecodeIterVisitor):
|
||||
'''Transforms a bytecode vector into a bytecode "flow tree".
|
||||
|
||||
The flow tree is a Python dictionary, described loosely by the
|
||||
following set of productions:
|
||||
|
||||
* `flow_tree` ``:=`` ``{`` `blocks` ``*`` ``}``
|
||||
* `blocks` ``:=`` `block_index` ``:`` ``[`` `bytecode_tree` ``*`` ``]``
|
||||
* `bytecode_tree` ``:=`` ``(`` `opcode_index` ``,`` `opcode` ``,``
|
||||
`opname` ``,`` `arg` ``,`` ``[`` `bytecode_tree` ``*`` ``]`` ``)``
|
||||
|
||||
The primary purpose of this transformation is to simulate the
|
||||
value stack, removing it and any stack-specific opcodes.'''
|
||||
|
||||
def __init__ (self, *args, **kws):
|
||||
super(BytecodeFlowBuilder, self).__init__(*args, **kws)
|
||||
om_items = opcode_util.OPCODE_MAP.items()
|
||||
|
|
@ -195,6 +208,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
|||
# ______________________________________________________________________
|
||||
|
||||
def build_flow (func):
|
||||
'''Given a Python function, return a bytecode flow tree for that
|
||||
function.'''
|
||||
return BytecodeFlowBuilder().visit(opcode_util.get_code_object(func))
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#! /usr/bin/env python
|
||||
# ______________________________________________________________________
|
||||
'''Defines a bytecode based LLVM translator for llnumba code.
|
||||
'''
|
||||
# ______________________________________________________________________
|
||||
# Module imports
|
||||
|
||||
import opcode
|
||||
|
|
@ -113,7 +116,17 @@ class LLVMCaster (object):
|
|||
# Class definitions
|
||||
|
||||
class LLVMTranslator (BytecodeFlowVisitor):
|
||||
'''Transformer responsible for visiting a set of bytecode flow
|
||||
trees, emitting LLVM code.
|
||||
|
||||
Unlike other translators in :py:mod:`numba.llnumba`, this
|
||||
incorporates the full transformation chain, starting with
|
||||
:py:class:`numba.llnumba.byte_flow.BytecodeFlowBuilder`, then
|
||||
:py:class:`numba.llnumba.byte_control.ControlFlowBuilder`, and
|
||||
then :py:class:`numba.llnumba.phi_injector.PhiInjector`.'''
|
||||
|
||||
def __init__ (self, llvm_module = None, *args, **kws):
|
||||
'''Constructor for LLVMTranslator.'''
|
||||
super(LLVMTranslator, self).__init__(*args, **kws)
|
||||
if llvm_module is None:
|
||||
llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),))
|
||||
|
|
@ -123,6 +136,13 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
self.phi_injector = PhiInjector()
|
||||
|
||||
def translate (self, function, llvm_type = None, env = None):
|
||||
'''Translate a function to the given LLVM function type.
|
||||
|
||||
If no type is given, then assume the function is of LLVM type
|
||||
"void ()".
|
||||
|
||||
The optional env parameter allows extension of the global
|
||||
environment.'''
|
||||
if llvm_type is None:
|
||||
llvm_type = lc.Type.function(lvoid, ())
|
||||
if env is None:
|
||||
|
|
@ -495,6 +515,8 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
# ______________________________________________________________________
|
||||
|
||||
def translate_function (func, lltype, llvm_module = None, **kws):
|
||||
'''Given a function and an LLVM function type, emit LLVM code for
|
||||
that function using a new LLVMTranslator instance.'''
|
||||
translator = LLVMTranslator(llvm_module)
|
||||
translator.translate(func, lltype, kws)
|
||||
return translator
|
||||
|
|
|
|||
|
|
@ -23,6 +23,23 @@ REF_DEF = def_synth_op('REF_DEF')
|
|||
# ______________________________________________________________________
|
||||
|
||||
class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
||||
'''Transformer responsible for modifying a bytecode flow, removing
|
||||
LOAD_FAST and STORE_FAST opcodes, and replacing them with a static
|
||||
single assignment (SSA) representation.
|
||||
|
||||
In order to support SSA, PhiInjector adds the following synthetic
|
||||
opcodes to transformed flows:
|
||||
|
||||
* REF_ARG: Specifically reference an incomming argument value.
|
||||
|
||||
* BUILD_PHI: Build a phi node to disambiguate between several
|
||||
possible definitions at a control flow join.
|
||||
|
||||
* DEFINITION: Unique value definition indexed by the "arg" field
|
||||
in the tuple.
|
||||
|
||||
* REF_DEF: Reference a specific value definition.'''
|
||||
|
||||
def visit_cfg (self, cfg, nargs = 0, *args, **kws):
|
||||
self.cfg = cfg
|
||||
ret_val = self.visit(cfg.blocks, nargs)
|
||||
|
|
@ -105,6 +122,8 @@ class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
|
|||
# ______________________________________________________________________
|
||||
|
||||
def inject_phis (func):
|
||||
'''Given a Python function, return a bytecode flow object that has
|
||||
been transformed by a fresh PhiInjector instance.'''
|
||||
import byte_control
|
||||
argcount = byte_control.opcode_util.get_code_object(func).co_argcount
|
||||
cfg = byte_control.build_cfg(func)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue