[pypy-svn] r33875 - pypy/dist/pypy/jit/codegen

mwh at codespeak.net mwh at codespeak.net
Mon Oct 30 13:45:14 CET 2006


Author: mwh
Date: Mon Oct 30 13:45:13 2006
New Revision: 33875

Modified:
   pypy/dist/pypy/jit/codegen/model.py
Log:
(arigo, mwh)
add a lot of docstrings and stub methods to pypy.jit.codegen.model.


Modified: pypy/dist/pypy/jit/codegen/model.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/model.py	(original)
+++ pypy/dist/pypy/jit/codegen/model.py	Mon Oct 30 13:45:13 2006
@@ -4,11 +4,18 @@
 class NotConstant(Exception):
     pass
 
+# all the following classes will be subclassed by each backend.
 
 class GenVarOrConst(object):
+    '''Instances of this "doubly abstract" class contains values,
+    either run-time values or compile time constants.'''
 
     @specialize.arg(1)
     def revealconst(self, T):
+        '''Return a value of low-level type T, or raise NotConstant.
+
+        Some simple conversion may be required, e.g. casting an address to a
+        pointer, but not converting a float to an integer.'''
         raise NotConstant(self)
 
 class GenVar(GenVarOrConst):
@@ -17,33 +24,149 @@
 class GenConst(GenVarOrConst):
     is_const = True
 
+# a word about "tokens":
+
+# several llops take Void arguments, for example the fieldname of a
+# getfield.  these need to be represented in some way during code
+# generation, in the getfield example it might be the offset and size
+# of the field in the structure.  but this is not enough in general,
+# because on the powerpc you need to know if the value should be
+# loaded into a general purpose or floating point register.
+
+# for this kind of possibly machine dependent information, we have the
+# concept of "token".  the tokens are created by specialize.memo()ed
+# staticmethods on the RGenOp class, in particular fieldToken,
+# allocToken, varsizeAllocToken, kindToken and sigToken.  See their
+# docstrings for more.
 
 class CodeGenerator(object):
-    pass
+
+    '''Instances of CodeGenerator are responsible for actually
+    generating machine code.  One instance is responsible for one
+    chunk of memory, and when it is filled or the generated code jumps
+    away the code generator is thrown away.'''
+
+    # the genop methods should emit the machine code for a single llop.
+    # for most llops, the genop1 and genop2 methods suffice, but some
+    # (generally those that take Void arguments, or depend on the
+    # types of the arguments) require special attention, and these are
+    # handled by the genop_OPNAME methods.
+
+    # the gv_* arguments are instances of GenVarOrConst
+
+##     @specialize.arg(1)
+##     def genop1(self, opname, gv_arg):
+
+##     @specialize.arg(1)
+##     def genop2(self, opname, gv_arg1, gv_arg2):
+
+##     def genop_getfield(self, fieldtoken, gv_ptr):
+##     def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
+##     def genop_getsubstruct(self, fieldtoken, gv_ptr):
+##     def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
+##     def genop_getarraysize(self, arraytoken, gv_ptr):
+##     def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value):
+##     def genop_malloc_fixedsize(self, alloctoken):
+##     def genop_malloc_varsize(self, varsizealloctoken, gv_size):
+##     def genop_call(self, sigtoken, gv_fnptr, args_gv):
+##     def genop_same_as(self, kindtoken, gv_x):
+##     def genop_debug_pdb(self):    # may take an args_gv later
+
+    # the other thing that happens for a given chunk is entering and
+    # leaving basic blocks inside it.
+
+    def enter_next_block(self, kinds, args_gv):
+        '''Called before generating the code for a basic block.
+
+        zip(kinds, args_gv) gives the kindtoken and GenVarOrConst for
+        each inputarg of the block.
+
+        The Obscure Bit: args_gv must be mutated in place to replace
+        GenConsts with GenVars and optionally GenVars can be replaced
+        with new GenVars, for example if the same value might live in
+        different locations (registers, places on the stack) in
+        different basic blocks.
+
+        Returns an instance of CodeGenBlock that serves as a label
+        that can later be jumped to.
+        '''
+
+    def jump_if_false(self, gv_condition):
+        '''Make a fresh CodeGenerator, insert in the current block a
+        check of gv_condition and a conditional jump to the new block
+        that is taken if gv_condition is false and return the new
+        CodeGenerator.'''
+
+    def jump_if_true(self, gv_condition):
+        '''See above, with the obvious difference :)'''
+
+    def finish_and_return(self, sigtoken, gv_returnvar):
+        '''Emit the epilogue code for the function, and the code to
+        return gv_returnvar.  This "closes" the current CodeGenerator.'''
+
+    def finish_and_goto(self, outputargs_gv, targetblock):
+        '''Insert an unconditional jump to targetblock.
+
+        outputargs_gv is a list of GenVarOrConsts which corresponds to Link.args
+        targetblock is an instance of CodeGenBlock.
+
+        This must insert code to make sure that the values in
+        outputargs_gv go where the targetblock expects them to be.
+
+        This "closes" the current CodeGenerator.
+        '''
+
+    def flexswitch(self, gv_exitswitch):
+        '''The Fun Stuff.
+
+        Generates a switch on the value of gv_exitswitch that can have
+        cases added to it later, i.e. even after it\'s been executed a
+        few times.
+
+        Returns an instance of CodeGenSwitch, see below.
+
+        This "closes" the current CodeGenerator.
+        '''
+
+    def show_incremental_progress(self):
+        '''Give some indication of the code that this instance has generated.
+
+        So far, the machine code backends don\'t actually do anything for this.
+        '''
 
 class CodeGenBlock(object):
-    pass
+    '''A "smart" label.  Represents an address of the start of a basic
+    block and the location of the inputargs on entry to that block.'''
 
 
 class AbstractRGenOp(object):
+    '''An RGenOp instance is responsible for coordinating the
+    generation of machine code for a given architecture.
 
-    # all commented out for the sake of the annotator
-    pass
+    Conceptually at least, instances do not have much state, although
+    pratically they have some state relating to management of buffers
+    being written to.
+    '''
+
+    def newgraph(self, sigtoken):
+        """Begin code generation for a new function, which signature
+        described by sigtoken.  Returns builder, entrypoint,
+        inputargs_gv where builder is an instance of CodeGenerator,
+        entrypoint is the address of the new function and inputargs_gv
+        is the location of each argument on entry to the function."""
 
-    #def newgraph(self, sigtoken):
-    #    """ """
-    #    raise NotImplementedError
+    # all staticmethods commented out for the sake of the annotator
 
-    #@staticmethod
+   #@staticmethod
     #@specialize.genconst(0)
     #def genconst(llvalue):
-    #    """ """
+    #    """Convert an llvalue to an instance of (a subclass of) GenConst."""
     #    raise NotImplementedError
 
     #constPrebuiltGlobal = genconst
 
     #def gencallableconst(self, sigtoken, name, entrypointaddr):
-    #    """ """
+    #    """"""
     #    raise NotImplementedError
 
     # the "token" methods render non-RPython data structures
@@ -56,39 +179,54 @@
     #@staticmethod
     #@specialize.memo()
     #def fieldToken(T, name):
-    #    """ """
+    #    """Return a token describing the location of the field 'name'
+    #    within the Struct T."""
     #    raise NotImplementedError
 
     #@staticmethod
     #@specialize.memo()
     #def allocToken(T):
-    #    """ """
+    #    """Return a token describing the size of the fixed-size type T."""
     #    raise NotImplementedError
 
     #@staticmethod
     #@specialize.memo()
     #def varsizeAllocToken(T):
-    #    """ """
+    #    """Return a token describing the size of the var-size type T,
+    #    i.e. enough information to, when given the item count,
+    #    compute how much memory to allocate."""
     #    raise NotImplementedError
 
     #@staticmethod
     #@specialize.memo()
     #def arrayToken(A):
-    #    """ """
+    #    """Return a token describing the Array A, enough information
+    #    to read and write the length, find the base of the items
+    #    array and find the size of each item."""
     #    raise NotImplementedError
 
     #@staticmethod
     #@specialize.memo()
     #def kindToken(T):
-    #    """ """
+    #    """Return a token that identifies (but no more?) the low-level type T."""
     #    raise NotImplementedError
 
     #@staticmethod
     #@specialize.memo()
     #def sigToken(FUNCTYPE):
-    #    """ """
+    #    """Return a token describing the signature of FUNCTYPE."""
     #    raise NotImplementedError
 
 
 class CodeGenSwitch(object):
-    pass
+    '''A CodeGenSwitch is a flexible switch on a given GenVar that can have cases added
+    to it "later", i.e. after it has been executed a few times.'''
+
+    def add_case(self, gv_case):
+        '''Make a new CodeGenerator that will be jumped to when the
+        switched-on GenVar takes the value of the GenConst gv_case.'''
+
+    def add_default(self):
+        '''Make a new CodeGenerator that will be jumped to when the
+        switched-on GenVar does not take the value of any case.'''
+



More information about the Pypy-commit mailing list