[pypy-svn] r11491 - pypy/dist/pypy/documentation

arigo at codespeak.net arigo at codespeak.net
Tue Apr 26 21:22:16 CEST 2005


Author: arigo
Date: Tue Apr 26 21:22:16 2005
New Revision: 11491

Modified:
   pypy/dist/pypy/documentation/translation.txt
Log:
More on the C-level operations that we want to have.



Modified: pypy/dist/pypy/documentation/translation.txt
==============================================================================
--- pypy/dist/pypy/documentation/translation.txt	(original)
+++ pypy/dist/pypy/documentation/translation.txt	Tue Apr 26 21:22:16 2005
@@ -371,8 +371,8 @@
 The C typer considers each operation in turn and, based on its annotations, replaces it by C-level operations if possible.
 
 
-Integer operations
-------------------
+Example: Integer operations
+---------------------------
 
 Integer operations are the easiest.  Assume a graph containing the following operation::
 
@@ -395,20 +395,84 @@
 Memory model
 ------------
 
-For more complicated examples we need to choose a memory model.  We will assume the following model: Variables store primitive values only (integers, pointers); more complex structures are always stored in the heap.
+For more complicated examples we need to choose a memory model.  We will assume a simple model: local Variables store primitive values only (integers, pointers), and the heap stores structs.
 
 We support this model using the following new graph operations (the result Variable is omitted when meaningless)::
 
+    v2 = malloc()
     v2 = malloc(v1)
     incref(v3)
     decref(v3)
 
-v2=malloc(v1) allocates v1 bytes of heap memory and returns a pointer to it.  For now, there is always a reference counter in a hidden header.
+v2=malloc() allocates some bytes of heap memory, zero it, and returns a pointer to it.  The number of bytes is suitable for the type of v2.  For now, there is always a reference counter in a hidden header, initialized to 1.
+
+incref() and decref() allow each value to be tracked.  The decref(v3) operation is used when the content of the value ``v3`` is about to be deleted.  GenC inserts an operation decref(v3) whenever the value in a local variable v3 is about to be forgotten (it isn't passed to the next basic block).  In addition, incref(v3) is inserted when a local Variable is about to be duplicated (it is passed several times to the next basic block).
+
+The exact operations performed by incref(v3) and decref(v3) depend on the type of v3.  For pointer types, they increment and decrement the reference counter of whatever they point to.  For integers, they have no effect.
+
+When decref() is applied on a pointer and the reference counter drops to zero, the destructor of the appropriate type is called; its action depends on the type, but (as in CPython) what it typically does is call decref() on each member of the structure and then release the occupied memory.
+
+Note that for now malloc() returns memory initialized to zero.  This allows our destructors to cope with partially initialized data structures, should an error occur while they are constructed.
+
+In C, it is common to see a struct definition whose last member is a variable-sized array.  For this case, v2=malloc(v1) allocates an amount of memory which is enough to store the fixed part of the struct plus ``v1`` items in the variable-sized part.
+
+
+CType
+-----
+
+Each C type is represented by an instance of a concrete subclass of CType_.  Each instance has the following interface:
+
+* a ``typename`` attribute: the name given to this type in C.
+
+* nameof(obj): method returning a C expression representing the constant ``obj`` in this C type.
+
+* init_globals(): called the first time genc sees this particular CType instance.  It generates C code that declares the type.
+
+* collect_globals(): called from time to time -- more precisely, before each function body is written to the C file.  It can generate more C code related to this type, if needed (e.g. declaration of static variables of this type).
+
+
+.. _CType: http://codespeak.net/svn/pypy/dist/pypy/translator/genc/basetype.py
+
+
+C-level operations
+------------------
+
+Here are the new operations that the C typer introduces in flow graphs.  Ideally, a completely typed graph should only contain these operations, and no longer any of the original operations.
+
+Integer arithmetic operations (see complete list in `ctyper.py`_)::
+
+    v3 = int_add(v1, v2)              # v3 = v1+v2;   // int v1, v2, v3
+    v3 = int_sub(v1, v2)              # v3 = v1-v2;   // int v1, v2, v3
+    v3 = int_mul(v1, v2)              # v3 = v1*v2;   // int v1, v2, v3
+    v3 = int_is_true(v1)              # v3 = v1?1:0;  // int v1, v3
+    etc.
+
+Function call::
+
+    v3 = direct_call(v1, v2, ...)     # v3 = v1(v2, ...);
+
+Memory management (see `Memory model`_)::
+
+    v2 = malloc()                     # for T* v2, alloc and zero sizeof(T) bytes of memory
+    v2 = malloc(v1)                   # same, but allocates sizeof(T) + v1*sizeof(T_item)
+    incref(v3)                        # for T* v3, details depend on T
+    decref(v3)                        # for T* v3, details depend on T
+
+Pointer operations::
+
+    v3 = arrow(v1, 'fieldname')       # v3 = v1->fieldname;   // if fieldname is a primitive
+    v3 = substruct(v1, 'fieldname')   # v3 = &v1->fieldname;  // if fieldname is a struct
+    v3 = subarray(v1, 'fieldname')    # v3 = v1->fieldname;   // if fieldname is an array
+    arrow_set(v1, 'fieldname', v2)    # v1->fieldname = v2;
+    v3 = ptr_add(v1, v2)              # v3 = v1+v2;    // T* v1, int v2, T* v3
+    v3 = ptr_cast(v1)                 # v3 = (T*) v1;  // S* v1, T* v3
+
+For regularity, all pointers should point to struct types.  Casting should follow the C99 aliasing rules: in our case, we should only use it when we have got a pointer ``S* v1``, and we discover (by inspecting what v1 points to) that it is actually just the first field of a larger structure of type T.
 
-incref() and decref() allow each primitive value to be tracked: GenC inserts an operation decref(v3) whenever the value in v3 is about to be forgotten (it isn't passed to the next basic block), or incref(v3) when it is about to be duplicated (it is passed several times to the next basic block).  The exact operations performed by incref(v3) and decref(v3) depend on the type of v3, but they typically only have an effect for pointer types, for which they increase and decrease the reference counter of the memory they point to and call the appropriate destructor when it falls to zero.  The destructor of complex data structures will in turn call decref() on its members.
+If you are confused by the three variants of the ``->`` operator, note that only arrow() reads the content of a field.  The substruct() operation returns a pointer to a substructure of the parent structure.  The subarray() operation does the same for arrays in the parent structure -- which is essentially the same as substruct(), and not as arrow().  Blame C syntax.
 
 
-XXX work in progress.
+.. _`ctyper.py`: http://codespeak.net/svn/pypy/dist/pypy/translator/genc/ctyper.py
 
 
 



More information about the Pypy-commit mailing list