[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