Adding docstrings for some of llnumba.

This commit is contained in:
Jon Riehl 2012-10-15 15:21:53 -05:00
commit fe1ba06698
4 changed files with 68 additions and 0 deletions

View file

@ -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),

View file

@ -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))
# ______________________________________________________________________

View file

@ -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

View file

@ -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)