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): 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): 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 self.nargs = nargs
ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws) ret_val = super(ControlFlowBuilder, self).visit(flow, *args, **kws)
del self.nargs del self.nargs
@ -73,6 +83,8 @@ class ControlFlowBuilder (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
# ______________________________________________________________________ # ______________________________________________________________________
def build_cfg (func): 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 import byte_flow
return ControlFlowBuilder().visit( return ControlFlowBuilder().visit(
byte_flow.build_flow(func), byte_flow.build_flow(func),

View file

@ -10,6 +10,19 @@ import opcode_util
# ______________________________________________________________________ # ______________________________________________________________________
class BytecodeFlowBuilder (BytecodeIterVisitor): 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): def __init__ (self, *args, **kws):
super(BytecodeFlowBuilder, self).__init__(*args, **kws) super(BytecodeFlowBuilder, self).__init__(*args, **kws)
om_items = opcode_util.OPCODE_MAP.items() om_items = opcode_util.OPCODE_MAP.items()
@ -195,6 +208,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
# ______________________________________________________________________ # ______________________________________________________________________
def build_flow (func): 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)) return BytecodeFlowBuilder().visit(opcode_util.get_code_object(func))
# ______________________________________________________________________ # ______________________________________________________________________

View file

@ -1,5 +1,8 @@
#! /usr/bin/env python #! /usr/bin/env python
# ______________________________________________________________________ # ______________________________________________________________________
'''Defines a bytecode based LLVM translator for llnumba code.
'''
# ______________________________________________________________________
# Module imports # Module imports
import opcode import opcode
@ -113,7 +116,17 @@ class LLVMCaster (object):
# Class definitions # Class definitions
class LLVMTranslator (BytecodeFlowVisitor): 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): def __init__ (self, llvm_module = None, *args, **kws):
'''Constructor for LLVMTranslator.'''
super(LLVMTranslator, self).__init__(*args, **kws) super(LLVMTranslator, self).__init__(*args, **kws)
if llvm_module is None: if llvm_module is None:
llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),)) llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),))
@ -123,6 +136,13 @@ class LLVMTranslator (BytecodeFlowVisitor):
self.phi_injector = PhiInjector() self.phi_injector = PhiInjector()
def translate (self, function, llvm_type = None, env = None): 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: if llvm_type is None:
llvm_type = lc.Type.function(lvoid, ()) llvm_type = lc.Type.function(lvoid, ())
if env is None: if env is None:
@ -495,6 +515,8 @@ class LLVMTranslator (BytecodeFlowVisitor):
# ______________________________________________________________________ # ______________________________________________________________________
def translate_function (func, lltype, llvm_module = None, **kws): 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 = LLVMTranslator(llvm_module)
translator.translate(func, lltype, kws) translator.translate(func, lltype, kws)
return translator return translator

View file

@ -23,6 +23,23 @@ REF_DEF = def_synth_op('REF_DEF')
# ______________________________________________________________________ # ______________________________________________________________________
class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor): 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): def visit_cfg (self, cfg, nargs = 0, *args, **kws):
self.cfg = cfg self.cfg = cfg
ret_val = self.visit(cfg.blocks, nargs) ret_val = self.visit(cfg.blocks, nargs)
@ -105,6 +122,8 @@ class PhiInjector (BenignBytecodeVisitorMixin, BytecodeFlowVisitor):
# ______________________________________________________________________ # ______________________________________________________________________
def inject_phis (func): 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 import byte_control
argcount = byte_control.opcode_util.get_code_object(func).co_argcount argcount = byte_control.opcode_util.get_code_object(func).co_argcount
cfg = byte_control.build_cfg(func) cfg = byte_control.build_cfg(func)