From fe1ba066983fce48c5242f9e9578b9dd388d35f7 Mon Sep 17 00:00:00 2001 From: Jon Riehl Date: Mon, 15 Oct 2012 15:21:53 -0500 Subject: [PATCH] Adding docstrings for some of llnumba. --- byte_control.py | 12 ++++++++++++ byte_flow.py | 15 +++++++++++++++ byte_translator.py | 22 ++++++++++++++++++++++ phi_injector.py | 19 +++++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/byte_control.py b/byte_control.py index 8180cf2..0ee4b67 100644 --- a/byte_control.py +++ b/byte_control.py @@ -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), diff --git a/byte_flow.py b/byte_flow.py index 6951b26..f0df934 100644 --- a/byte_flow.py +++ b/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)) # ______________________________________________________________________ diff --git a/byte_translator.py b/byte_translator.py index 7954970..62f3e21 100644 --- a/byte_translator.py +++ b/byte_translator.py @@ -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 diff --git a/phi_injector.py b/phi_injector.py index c40abe3..b45be20 100644 --- a/phi_injector.py +++ b/phi_injector.py @@ -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)