[pypy-svn] r18565 - in pypy/branch/hl-backend/pypy: doc doc/image interpreter/pyparser/test module/Numeric module/_socket module/_socket/test objspace/flow objspace/flow/test objspace/std objspace/std/test rpython rpython/l3interp rpython/memory rpython/memory/test rpython/module rpython/test translator translator/asm translator/asm/i386gen translator/asm/ppc translator/asm/ppcgen translator/asm/test translator/c translator/c/src translator/c/test translator/goal translator/js translator/js/test translator/llvm translator/llvm/module

boria at codespeak.net boria at codespeak.net
Fri Oct 14 17:44:59 CEST 2005


Author: boria
Date: Fri Oct 14 17:44:56 2005
New Revision: 18565

Added:
   pypy/branch/hl-backend/pypy/doc/image/JIT.dot
      - copied unchanged from r18564, pypy/dist/pypy/doc/image/JIT.dot
   pypy/branch/hl-backend/pypy/module/Numeric/   (props changed)
      - copied from r18564, pypy/dist/pypy/module/Numeric/
   pypy/branch/hl-backend/pypy/module/_socket/   (props changed)
      - copied from r18564, pypy/dist/pypy/module/_socket/
   pypy/branch/hl-backend/pypy/rpython/l3interp/
      - copied from r18564, pypy/dist/pypy/rpython/l3interp/
   pypy/branch/hl-backend/pypy/rpython/module/ll_stack.py
      - copied unchanged from r18564, pypy/dist/pypy/rpython/module/ll_stack.py
   pypy/branch/hl-backend/pypy/translator/asm/ppc/
      - copied from r18564, pypy/dist/pypy/translator/asm/ppc/
   pypy/branch/hl-backend/pypy/translator/asm/regalloc.py
      - copied unchanged from r18564, pypy/dist/pypy/translator/asm/regalloc.py
   pypy/branch/hl-backend/pypy/translator/asm/simulator.py
      - copied unchanged from r18564, pypy/dist/pypy/translator/asm/simulator.py
   pypy/branch/hl-backend/pypy/translator/asm/test/test_simulator.py
      - copied unchanged from r18564, pypy/dist/pypy/translator/asm/test/test_simulator.py
   pypy/branch/hl-backend/pypy/translator/c/src/stack.h
      - copied unchanged from r18564, pypy/dist/pypy/translator/c/src/stack.h
   pypy/branch/hl-backend/pypy/translator/goal/targetrpystonedalone.py
      - copied unchanged from r18564, pypy/dist/pypy/translator/goal/targetrpystonedalone.py
Modified:
   pypy/branch/hl-backend/pypy/doc/draft-dynamic-language-translation.txt
   pypy/branch/hl-backend/pypy/doc/image/lattice1.dot
   pypy/branch/hl-backend/pypy/doc/news.txt
   pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astbuilder.py
   pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astcompiler.py
   pypy/branch/hl-backend/pypy/module/_socket/test/   (props changed)
   pypy/branch/hl-backend/pypy/objspace/flow/model.py
   pypy/branch/hl-backend/pypy/objspace/flow/objspace.py
   pypy/branch/hl-backend/pypy/objspace/flow/test/test_objspace.py
   pypy/branch/hl-backend/pypy/objspace/std/longobject.py
   pypy/branch/hl-backend/pypy/objspace/std/test/test_longobject.py
   pypy/branch/hl-backend/pypy/rpython/extfunctable.py
   pypy/branch/hl-backend/pypy/rpython/llinterp.py
   pypy/branch/hl-backend/pypy/rpython/memory/gc.py
   pypy/branch/hl-backend/pypy/rpython/memory/lltypesimulation.py
   pypy/branch/hl-backend/pypy/rpython/memory/simulator.py
   pypy/branch/hl-backend/pypy/rpython/memory/test/test_gc.py
   pypy/branch/hl-backend/pypy/rpython/memory/test/test_lltypesimulation.py
   pypy/branch/hl-backend/pypy/rpython/module/ll_stackless.py
   pypy/branch/hl-backend/pypy/rpython/objectmodel.py
   pypy/branch/hl-backend/pypy/rpython/rint.py
   pypy/branch/hl-backend/pypy/rpython/rtyper.py
   pypy/branch/hl-backend/pypy/rpython/test/test_rint.py
   pypy/branch/hl-backend/pypy/rpython/test/test_rlist.py
   pypy/branch/hl-backend/pypy/rpython/test/test_rstr.py
   pypy/branch/hl-backend/pypy/translator/asm/genasm.py
   pypy/branch/hl-backend/pypy/translator/asm/i386gen/   (props changed)
   pypy/branch/hl-backend/pypy/translator/asm/infregmachine.py   (contents, props changed)
   pypy/branch/hl-backend/pypy/translator/asm/ppcgen/func_builder.py
   pypy/branch/hl-backend/pypy/translator/asm/test/test_asm.py
   pypy/branch/hl-backend/pypy/translator/c/extfunc.py
   pypy/branch/hl-backend/pypy/translator/c/funcgen.py
   pypy/branch/hl-backend/pypy/translator/c/gc.py
   pypy/branch/hl-backend/pypy/translator/c/genc.py
   pypy/branch/hl-backend/pypy/translator/c/src/address.h
   pypy/branch/hl-backend/pypy/translator/c/src/g_include.h
   pypy/branch/hl-backend/pypy/translator/c/src/ll_stackless.h
   pypy/branch/hl-backend/pypy/translator/c/src/mem.h
   pypy/branch/hl-backend/pypy/translator/c/src/support.h
   pypy/branch/hl-backend/pypy/translator/c/stackless.py
   pypy/branch/hl-backend/pypy/translator/c/test/test_annotated.py
   pypy/branch/hl-backend/pypy/translator/c/test/test_extfunc.py
   pypy/branch/hl-backend/pypy/translator/c/test/test_lladdresses.py
   pypy/branch/hl-backend/pypy/translator/c/test/test_standalone.py
   pypy/branch/hl-backend/pypy/translator/c/test/test_typed.py
   pypy/branch/hl-backend/pypy/translator/goal/bench-windows.py
   pypy/branch/hl-backend/pypy/translator/goal/driver.py
   pypy/branch/hl-backend/pypy/translator/goal/targetnopstandalone.py
   pypy/branch/hl-backend/pypy/translator/goal/targetrichards.py
   pypy/branch/hl-backend/pypy/translator/goal/translate_pypy.py
   pypy/branch/hl-backend/pypy/translator/js/arraynode.py
   pypy/branch/hl-backend/pypy/translator/js/codewriter.py
   pypy/branch/hl-backend/pypy/translator/js/database.py
   pypy/branch/hl-backend/pypy/translator/js/funcnode.py
   pypy/branch/hl-backend/pypy/translator/js/js.py
   pypy/branch/hl-backend/pypy/translator/js/node.py
   pypy/branch/hl-backend/pypy/translator/js/opaquenode.py
   pypy/branch/hl-backend/pypy/translator/js/opwriter.py
   pypy/branch/hl-backend/pypy/translator/js/structnode.py
   pypy/branch/hl-backend/pypy/translator/js/test/test_genllvm1.py
   pypy/branch/hl-backend/pypy/translator/llvm/build_llvm_module.py
   pypy/branch/hl-backend/pypy/translator/llvm/externs2ll.py
   pypy/branch/hl-backend/pypy/translator/llvm/gc.py
   pypy/branch/hl-backend/pypy/translator/llvm/module/genexterns.c
   pypy/branch/hl-backend/pypy/translator/transform.py
   pypy/branch/hl-backend/pypy/translator/translator.py
Log:
* Merged trunk (dist/pypy/) at revision 18564 into hl-backend branch.


Modified: pypy/branch/hl-backend/pypy/doc/draft-dynamic-language-translation.txt
==============================================================================
--- pypy/branch/hl-backend/pypy/doc/draft-dynamic-language-translation.txt	(original)
+++ pypy/branch/hl-backend/pypy/doc/draft-dynamic-language-translation.txt	Fri Oct 14 17:44:56 2005
@@ -783,8 +783,8 @@
 - *b*, *b'*, *b''*... are maps from *V* to *A*.
 
 We call *state* a pair *(b,E)*.  We say that a state *(b',E')* is more
-general than a state *(b,E)* if for all variables *v* we have *b'(v) >=
-b(v)* and *E'* includes at least all relations of *E*.  There is:
+general than a state *(b,E)* if for all variables *v* we have ``b'(v) >=
+b(v)`` and *E'* includes at least all relations of *E*.  There is:
 
 - a most general state, with *bmax(v) = Top* for all *v* and *Emax*
   identifying all variables with each other;
@@ -854,15 +854,15 @@
 .. _merge_into:
 
 In the sequel, a lot of rules will be based on the following
-``merge_into`` operator.  Given two variables *x* and *y*,
-``merge_into(x,y)`` modifies the state as follows::
+``merge_into`` operator.  Given an annotation *a* and a variable *x*,
+``merge_into(a,x)`` modifies the state as follows::
 
-         merge_into(x,y):
-             if b(x)=List(v) and b(y)=List(w):
+         merge_into(a,x):
+             if a=List(v) and b(x)=List(w):
                  b' = b
-                 E' = E union (v~w)
+                 E' = E union (v ~ w)
              else:
-                 b' = b with (y -> b(x) \/ b(y))
+                 b' = b with (x -> a \/ b(x))
                  E' = E
 
 where ``\/`` is the union in the lattice *A*.
@@ -875,7 +875,7 @@
 
          y = phi(x)
       ----------------------------------------
-               merge_into(x,y)
+               merge_into(b(x),y)
 
 The purpose of the equivalence relation *E* is to force two identified
 variables to keep the same binding.  The rationale for this is explained
@@ -884,13 +884,13 @@
 
          (x~y) in E
       ----------------------------------------
-               merge_into(x,y)
-               merge_into(y,x)
+               merge_into(b(x),y)
+               merge_into(b(y),x)
 
-Note that in theory, all rules should be tried repeatedly until none of
+Note that a priori, all rules should be tried repeatedly until none of
 them generalizes the state any more, at which point we have reached a
-fixpoint.  In practice, the rules are well suited to a simple metarule
-that tracks a small set of rules that can possibly apply.  Only these
+fixpoint.  However, the rules are well suited to a simple metarule that
+tracks a small set of rules that can possibly apply.  Only these
 "scheduled" rules are tried.  The metarule is as follows:
 
 - when an identification *x~y* is added to *E*, then the rule
@@ -966,7 +966,7 @@
 
          setitem(x,y,z), b(x)=List(v)
       --------------------------------------------
-               merge_into(z,v)
+               merge_into(b(z),v)
 
 Reading an item out a list requires care to ensure that the rule is
 rescheduled if the binding of the hidden variable is generalized.  We do
@@ -1019,9 +1019,9 @@
 instances".  By default, instances of some user-defined class that
 happens to pre-exist annotation have no constantness requirement on
 their own; after annotation and possibly compilation, these instances
-will continue to behave as regular mutable instances of that class.
-These prebuilt instances are decribed in another section (`Constant
-annotations`_).  However, the user program can give a hint that forces
+will continue to behave as regular mutable instances of that class,
+turned into mostly regular ``Inst(C)`` annotations when the annotator
+encounters them.  However, the user program can give a hint that forces
 the annotator to consider the object as a "frozen prebuilt constant".
 The object is then considered as a now-immutable container of
 attributes.  It looses its object-oriented aspects and its class becomes
@@ -1071,15 +1071,15 @@
 program that is static enough, it must reconstruct a static structure
 for each class in the hierarchy.  It does so by observing the usage
 patterns of the classes and their instances, by propagating annotations
-of the form ``SomeInstance(cls)`` -- which stands for "an instance of
-the class *cls* or any subclass".  Instance fields are attached to a
-class whenever we see that the field is being written to an instance of
-this class.  If the user program manipulates instances polymorphically,
-the variables holding the instances will be annotated
-``SomeInstance(cls)`` with some abstract base class *cls*; accessing
-attributes on such generalized instances lifts the inferred attribute
-declarations up to *cls*.  The same technique works for inferring the
-location of both fields and methods.
+of the form ``Inst(cls)`` -- which stands for "an instance of the class
+*cls* or any subclass".  Instance fields are attached to a class
+whenever we see that the field is being written to an instance of this
+class.  If the user program manipulates instances polymorphically, the
+variables holding the instances will be annotated ``Inst(cls)`` with
+some abstract base class *cls*; accessing attributes on such generalized
+instances lifts the inferred attribute declarations up to *cls*.  The
+same technique works for inferring the location of both fields and
+methods.
 
 ~~~~~~~~~~~~~~~~~~~~~~
 
@@ -1119,135 +1119,139 @@
          setattr(x,attr,z), b(x)=Inst(C)
       ---------------------------------------------------------------------
                E' = E union (v_C.attr ~ v_D.attr)  for all D subclass of C
-               merge_into(z, v_C.attr)
-
-The purpose of ``lookup_filter`` is to avoid loosing precision in method
-calls.  Indeed, as described more precisely in `Constant annotations`_
-below, if ``attr`` names a method of the class ``C`` then the binding
-``b(v_C.attr)`` is a ``Pbc`` that includes all the "potental bound
-method" objects ``D.f``, for each subclass ``D`` of ``C`` where a
-function ``f`` is present under the name ``attr``.
-
-XXX
-
-
-if ``attr`` is a method defined on XXX::
-
-    lookup_filter(Pbc(set), class) = Pbc(newset) where
-        we only keep in newset the non-methods, and the following methods:
-         * the ones bound to a strict subclass of 'class', and
-         * among the methods bound the 'class' or superclasses, only the
-             one from the most derived class.
-    lookup_filter(NonPbcAnnotation, class) = NonPbcAnnotation
+               merge_into(b(z), v_C.attr)
 
 Note the similarity with the ``getitem`` and ``setitem`` of lists, in
 particular the usage of the auxiliary variable *z'*.
 
-XXX
-
+The purpose of ``lookup_filter`` is to avoid loosing precision in method
+calls.  Indeed, if ``attr`` names a method of the class ``C`` then the
+binding ``b(v_C.attr)`` is initialized to ``Pbc(m)``, where *m* is the
+following set:
 
-Constant annotations
-~~~~~~~~~~~~~~~~~~~~
+* for each subclass ``D`` of ``C``, if the class ``D`` introduces a method
+  ``attr`` implemented as, say, the function ``f``, then the "potential
+  bound method" object ``D.f`` belongs to *m*.
 
-XXX constant arguments to operations
+However, because of the possible identification between the variable
+``v_C.attr`` and the corresponding variable ``v_B.attr`` of a
+superclass, the set *m* might end up containing potential bound methods
+of other unrelated subclasses of ``B``, even when performing a
+``getattr`` on what we know is an instance of ``C``.  The
+``lookup_filter`` reverses this effect as follows::
 
+    lookup_filter(Pbc(set), C) = Pbc(newset)
+    lookup_filter(NonPbcAnnotation, C) = NonPbcAnnotation
 
-Draft
-~~~~~
+where the *newset* only keeps the non-methods of *set* (if any) plus the
+following methods:
 
-::
+* the ones bound to a strict subclass of ``C``, plus
 
-    Char
-    
-    Inst(class)
-    
-    List(x)
-    
-    Dict(x, y)
-
-    Tup(ann_1, ..., ann_n)
-    
-    Pbc({... a finite set ...})
-    
-         with:   None
-                 f
-                 class
-                 class.f
-    
-    v_n = op(v_n1, ...) | v_n', v_n''
-    
-    v_class.attr
-    
-    v_n: Annotation
-
-    for each function f:
-        arg_f_1 ... arg_f_n
-        returnvar_f
-
-
-    E: eq rel on V
-    b: V->A
-    V: set of variables
-    A: fixed lattice of the above annotation terms
+* among the methods bound to ``C`` or superclasses of ``C``, only the
+  one from the most derived class.
 
 
-         z=getattr(x,attr) | z', b(x)=Inst(A)
-      ---------------------------------------------------------------------
-               E' = E union (A.attr ~ A'.attr)  for all A' subclass of A
-               E' = E union (z' ~ A.attr)
-               b' = b with (z->lookup_filter(b(z'), A))
-
-
-         setattr(x,attr,z), b(x)=Inst(A)
-      ---------------------------------------------------------------------
-               assert b(z) is not a Pbc containing methods
-               E' = E union (A.attr ~ A'.attr)  for all A' subclass of A
-               merge_into(z, A.attr)
+Calls
+~~~~~
 
+The ``Pbc`` annotations regroup (among others) all user-defined callable
+objects: functions, methods and classes.  A call in the user program
+turns into a ``simplecall`` operation whose first argument is the object
+to call.  Here is the corresponding rule -- regrouping all cases because
+the same ``Pbc(set)`` could mix several kinds of callables::
 
          z=simplecall(x,y1,...,yn), b(x)=Pbc(set)
       ---------------------------------------------------------------------
            for each c in set:
                if c is a function:
-                   E' = E union (z~returnvar_c)
-                   merge_into(y1, arg_c_1)
+                   E' = E union (z ~ returnvar_c)
+                   merge_into(b(y1), arg_c_1)
                    ...
-                   merge_into(yn, arg_c_n)
+                   merge_into(b(yn), arg_c_n)
                if c is a class:
                    let f = c.__init__
-                   b' = b with (z->b(z)\/Inst(c))
-                   b' = b with (arg_f_1->b(arg_f_1)\/Inst(c))
-                   merge_into(y1, arg_f_2)
+                   merge_into(Inst(c), z)
+                   merge_into(Inst(c), arg_f_1)
+                   merge_into(b(y1), arg_f_2)
                    ...
-                   merge_into(yn, arg_f_(n+1))
+                   merge_into(b(yn), arg_f_(n+1))
                if c is a method:
                    let class.f = c
-                   E' = E union (z~returnvar_f)
-                   b' = b with (arg_f_1->b(arg_f_1)\/Inst(class))
-                   merge_into(y1, arg_f_2)
+                   E' = E union (z ~ returnvar_f)
+                   merge_into(Inst(class), arg_f_1)
+                   merge_into(b(y1), arg_f_2)
                    ...
-                   merge_into(yn, arg_f_(n+1))
+                   merge_into(b(yn), arg_f_(n+1))
+
+Calling a class returns an instance and flows the annotations into the
+contructor ``__init__`` of the class.  Calling a method inserts the
+instance annotation as the first argument of the underlying function
+(the annotation is exactly ``Inst(C)`` for the class ``C`` in which the
+method is found).
 
 
-    lookup_filter(Pbc(set), class) = Pbc(newset) where
-        we only keep in newset the non-methods, and the following methods:
-         * the ones bound to a strict subclass of 'class', and
-         * among the methods bound the 'class' or superclasses, only the
-             one from the most derived class.
-    lookup_filter(NonPbcAnnotation, class) = NonPbcAnnotation
+Termination and soundness
+~~~~~~~~~~~~~~~~~~~~~~~~~
 
+As the annotation process is a fix-point search, it is necessary for
+completeness to prove more formally that it is well-behaved.  The
+following proofs are all rather easy given the approach we have taken.
 
 Termination
-~~~~~~~~~~~
+***********
+
+We first have to check that each rule can only turn a state *(b,E)* into
+a state *(b',E')* that is either identical or more general.  To do so,
+we first verify that they all have the following properties:
+
+* if *z* is the result variable of an operation, the binding ``b(z)`` is
+  only ever modified by the rule (or rules) about this operation: this
+  is true because *E* never identifies such a result variable with any
+  other variable.
+
+* the annotation ``b(z)`` of such a result variable can only become more
+  general: using the previous point, this can be checked on the rule (or
+  rules) of each operation independently.  Indeed, there are only two
+  ways in which ``b(z)`` is modified: by ``merge_into(..., z)``, which
+  trivially guarantees the property by being based on the union operator
+  ``\/`` of the lattice, or explicitely in a way that can easily be
+  checked to respect the property.
+
+...
+
+
+Each basic step (execution of one rule) can lead to the generalization
+of the state.  If it does, then other rules may be scheduled or
+re-scheduled for execution.  The state can only be generalized a finite
+number of times because both the lattice *A* and the set of variables
+*V* of which *E* is an equivalence relation are finite.  If a rule does
+not lead to any generalization, then it does not trigger re-scheduling
+of any other rule.  This ensures that the process eventually terminates.
+
+The extended lattice used in practice is a priori not finite.  As we did
+not describe this lattice formally here, we have to skip the (easy)
+proof that it still contains no infinite ascending chain.  An ascending
+chain is a sequence where each item is strictly larger than the previous
+one.
+
+Soundness
+*********
+
+We define an annotation state to be *sound* if none of the rules would
+lead to further Xxx.
+
 
 XXX termination + soundness + most-precise-fixpoint-ness + complexity 
 
 
+Complexity
+**********
+
 The lattice is finite, although its size depends on the size of the
 program.  The List part has the same size as *V*, and the Pbc part is
 exponential on the number of prebuilt constants.  However, in this model
-a chain of annotations (where each one is larger than the previous)
-cannot be longer than::
+a chain of annotations cannot be longer than::
 
     max(5, number-of-pbcs + 3, depth-of-class-hierarchy + 3).
 
@@ -1258,6 +1262,9 @@
 to prove that there is no infinite ascending chain, which is enough to
 guarantee termination.
 
+Additionally, an important property of ``lookup_filter`` is to be
+monotonic: XXX
+
 
 Non-static aspects
 ~~~~~~~~~~~~~~~~~~

Modified: pypy/branch/hl-backend/pypy/doc/image/lattice1.dot
==============================================================================
--- pypy/branch/hl-backend/pypy/doc/image/lattice1.dot	(original)
+++ pypy/branch/hl-backend/pypy/doc/image/lattice1.dot	Fri Oct 14 17:44:56 2005
@@ -4,11 +4,11 @@
     Top -> "*instances*" -> Bottom;
     "*instances*" -> None;
     NullableStr -> None;
-    Top -> "*callables*" -> Bottom;
-    "*callables*" -> None;
+    Top -> "*PBCs*" -> Bottom;
+    "*PBCs*" -> None;
     Top -> "*lists*" -> None -> Bottom;
 
     "*lists*" [shape=box];
     "*instances*" [shape=box];
-    "*callables*" [shape=box];
+    "*PBCs*" [shape=box];
 }

Modified: pypy/branch/hl-backend/pypy/doc/news.txt
==============================================================================
--- pypy/branch/hl-backend/pypy/doc/news.txt	(original)
+++ pypy/branch/hl-backend/pypy/doc/news.txt	Fri Oct 14 17:44:56 2005
@@ -18,12 +18,13 @@
 `continuation-passing`_ style (stackless), making the translation process
 work for target languages with more powerful object systems and some tiny
 steps into the JIT_ direction. Michael and Carl have written
-a `report about day one`_. *(10/11/2005)*
+a `report about day one`_ and `one about day two and three`_. *(10/14/2005)*
 
 .. _`Logilabs offices in Paris`: http://codespeak.net/pypy/extradoc/sprintinfo/paris-2005-sprint.html 
 .. _JIT: http://en.wikipedia.org/wiki/Just-in-time_compilation
 .. _`continuation-passing`: http://en.wikipedia.org/wiki/Continuation_passing_style
 .. _`report about day one`: http://codespeak.net/pipermail/pypy-dev/2005q4/002510.html
+.. _`one about day two and three`: http://codespeak.net/pipermail/pypy-dev/2005q4/002512.html
 
 PyPy release 0.7.0
 =================== 

Modified: pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astbuilder.py	(original)
+++ pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astbuilder.py	Fri Oct 14 17:44:56 2005
@@ -715,10 +715,8 @@
         filepath = os.path.join(STDLIB_PATH, basename)
         size = os.stat(filepath)[6]
         # filter on size
-        if size <= 10000:
-            print "TESTING", filepath
-            source = file(filepath).read()
-            yield check_expression, source, 'exec'
+        source = file(filepath).read()
+        yield check_expression, source, 'exec'
 
 
 def test_eval_string():

Modified: pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astcompiler.py
==============================================================================
--- pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astcompiler.py	(original)
+++ pypy/branch/hl-backend/pypy/interpreter/pyparser/test/test_astcompiler.py	Fri Oct 14 17:44:56 2005
@@ -204,6 +204,19 @@
         source = file(filepath).read()
         yield check_compile, source, 'exec'
 
+STDLIB_PATH = os.path.dirname(os.__file__)
+def test_on_stdlib():
+    py.test.skip('too ambitious for now (and time consuming)')
+    for basename in os.listdir(STDLIB_PATH):
+        if not basename.endswith('.py'):
+            continue
+        filepath = os.path.join(STDLIB_PATH, basename)
+        # size = os.stat(filepath)[6]
+        # filter on size
+        # if size <= 10000:
+        source = file(filepath).read()
+        yield check_compile, source, 'exec'
+
 def test_libstuff():
     for snippet_name in LIBSTUFF:
         filepath = os.path.join(os.path.dirname(__file__), '../../../lib', snippet_name)

Modified: pypy/branch/hl-backend/pypy/objspace/flow/model.py
==============================================================================
--- pypy/branch/hl-backend/pypy/objspace/flow/model.py	(original)
+++ pypy/branch/hl-backend/pypy/objspace/flow/model.py	Fri Oct 14 17:44:56 2005
@@ -256,6 +256,7 @@
                 name = '_' + name
             name = self.namesdict.setdefault(name, (name, 0))[0]
         self._name = name
+        self._nr = -1
 
     def set_name_from(self, v):
         # this is for SSI_to_SSA only which should not know about internals

Modified: pypy/branch/hl-backend/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/branch/hl-backend/pypy/objspace/flow/objspace.py	(original)
+++ pypy/branch/hl-backend/pypy/objspace/flow/objspace.py	Fri Oct 14 17:44:56 2005
@@ -395,7 +395,7 @@
                                    types.ClassType,
                                    types.TypeType)) and
                       c.__module__ in ['__builtin__', 'exceptions']):
-                    exceptions = None
+                    exceptions = implicit_exceptions.get(c, None)
         self.handle_implicit_exceptions(exceptions)
         return w_res
 
@@ -434,7 +434,9 @@
     op_appendices[_exc] = _name
 del _name, _exc
 
-implicit_exceptions = {}
+implicit_exceptions = {
+    int: [ValueError],      # built-ins that can always raise exceptions
+    }
 
 def _add_exceptions(names, exc):
     for name in names.split():

Modified: pypy/branch/hl-backend/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/branch/hl-backend/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/branch/hl-backend/pypy/objspace/flow/test/test_objspace.py	Fri Oct 14 17:44:56 2005
@@ -267,7 +267,7 @@
     def implicitException_int_and_id(x):
         try:
             return int(x) + id(x)
-        except ValueError:   # not captured by the flow graph!
+        except TypeError:   # not captured by the flow graph!
             return 0
 
     def test_implicitException_int_and_id(self):

Modified: pypy/branch/hl-backend/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/hl-backend/pypy/objspace/std/longobject.py	(original)
+++ pypy/branch/hl-backend/pypy/objspace/std/longobject.py	Fri Oct 14 17:44:56 2005
@@ -99,10 +99,10 @@
     def fromint(space, intval):
         if intval < 0:
             sign = -1
-            ival = -intval
+            ival = r_uint(-intval)
         elif intval > 0:
             sign = 1
-            ival = intval
+            ival = r_uint(intval)
         else:
             return W_LongObject(space, [0], 0)
         # Count the number of Python digits.
@@ -118,7 +118,7 @@
         t = ival
         p = 0
         while t:
-            v.digits[p] = t & MASK
+            v.digits[p] = intmask(t & MASK)
             t >>= SHIFT
             p += 1
         return v

Modified: pypy/branch/hl-backend/pypy/objspace/std/test/test_longobject.py
==============================================================================
--- pypy/branch/hl-backend/pypy/objspace/std/test/test_longobject.py	(original)
+++ pypy/branch/hl-backend/pypy/objspace/std/test/test_longobject.py	Fri Oct 14 17:44:56 2005
@@ -409,3 +409,9 @@
         raises(ValueError, math.log, 0) 
         raises(ValueError, math.log, -1) 
         raises(ValueError, math.log, -2) 
+
+    def test_long(self):
+        import sys
+        n = -sys.maxint-1
+        assert long(n) == n
+        assert str(long(n)) == str(n)

Modified: pypy/branch/hl-backend/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/extfunctable.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/extfunctable.py	Fri Oct 14 17:44:56 2005
@@ -209,6 +209,9 @@
 # stackless
 from pypy.rpython import objectmodel
 declare(objectmodel.stack_frames_depth, int, 'll_stackless/stack_frames_depth')
+declare(objectmodel.stack_too_big, bool, 'll_stack/too_big')
+declare(objectmodel.stack_check, noneannotation, 'll_stack/check')
+declare(objectmodel.stack_unwind, noneannotation, 'll_stack/unwind')
 
 # ___________________________________________________________
 # the exceptions that can be implicitely raised by some operations
@@ -224,4 +227,5 @@
     KeyError         : True,
     IndexError       : True,
     AssertionError   : True,
+    RuntimeError     : True,
     }

Modified: pypy/branch/hl-backend/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/llinterp.py	Fri Oct 14 17:44:56 2005
@@ -324,7 +324,10 @@
             result = self.op_direct_call(malloc, *args)
             return self.llinterpreter.gc.adjust_result_malloc(result, obj, size)
         else:
-            return self.llt.malloc(obj, size)
+            try:
+                return self.llt.malloc(obj, size)
+            except MemoryError, e:
+                self.make_llexception(e)
 
     def op_flavored_malloc(self, flavor, obj):
         assert isinstance(flavor, str)

Modified: pypy/branch/hl-backend/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/memory/gc.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/memory/gc.py	Fri Oct 14 17:44:56 2005
@@ -34,12 +34,14 @@
     ll = AddressLinkedList()
     ll.append(NULL)
     ll.append(raw_malloc(10))
+    ll.pop() #make the annotator see pop
     return ll
 
 def dummy_get_roots2():
     ll = AddressLinkedList()
     ll.append(raw_malloc(10))
     ll.append(NULL)
+    ll.pop() #make the annotator see pop
     return ll
 
 
@@ -67,6 +69,30 @@
         "NOT_RPYTHON"
         pass
 
+class DummyGC(GCBase):
+    _alloc_flavor_ = "raw"
+
+    def __init__(self, dummy=None, get_roots=None):
+        self.get_roots = get_roots
+        self.set_query_functions(None, None, None, None, None, None, None)
+   
+    def malloc(self, typeid, length=0):
+        size = self.fixed_size(typeid)
+        if self.is_varsize(typeid):
+            size += length * self.varsize_item_sizes(typeid)
+        return raw_malloc(size)
+         
+    def collect(self):
+        self.get_roots() #this is there so that the annotator thinks get_roots is a function
+
+    def size_gc_header(self, typeid=0):
+        return 0
+
+    def init_gc_object(self, addr, typeid):
+        return
+    init_gc_object_immortal = init_gc_object
+   
+
 class MarkSweepGC(GCBase):
     _alloc_flavor_ = "raw"
 

Modified: pypy/branch/hl-backend/pypy/rpython/memory/lltypesimulation.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/memory/lltypesimulation.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/memory/lltypesimulation.py	Fri Oct 14 17:44:56 2005
@@ -48,7 +48,7 @@
         if isinstance(self._T, lltype.Array):
             self._address.signed[0] = size
         elif isinstance(self._T, lltype.Struct):
-            if isinstance(self._T._flds[self._T._names[-1]], lltype.Array):
+            if self._T._arrayfld is not None:
                 addr = self._address + self._layout[self._T._arrayfld]
                 addr.signed[0] = size
         else:

Modified: pypy/branch/hl-backend/pypy/rpython/memory/simulator.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/memory/simulator.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/memory/simulator.py	Fri Oct 14 17:44:56 2005
@@ -113,7 +113,8 @@
         return self.blocks[mid]
 
     def malloc(self, size):
-        assert size > 0
+        if size == 0:
+            size = 1
         result = self.freememoryaddress
         self.blocks.append(MemoryBlock(result, size))
         self.freememoryaddress += size

Modified: pypy/branch/hl-backend/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/memory/test/test_gc.py	Fri Oct 14 17:44:56 2005
@@ -5,7 +5,7 @@
 from pypy.translator.annrpython import RPythonAnnotator
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.memory.gc import GCError, MarkSweepGC, SemiSpaceGC
-from pypy.rpython.memory.gc import DeferredRefcountingGC
+from pypy.rpython.memory.gc import DeferredRefcountingGC, DummyGC
 from pypy.rpython.memory.support import AddressLinkedList, INT_SIZE
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
 from pypy.rpython.memory.simulator import MemorySimulatorError
@@ -138,3 +138,22 @@
     def teardown_class(cls):
         gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
         gclltype.use_gc = cls.old
+
+class TestDummyGC(TestMarkSweepGC):
+    def setup_class(cls):
+        gclltype.use_gc = DummyGC
+        cls.old = gclltype.use_gc
+    def teardown_class(cls):
+        gclltype.use_gc = cls.old
+
+class TestDummyGCRunningOnLLinterp(TestMarkSweepGC):
+    def setup_class(cls):
+        cls.prep_old = gclltype.prepare_graphs_and_create_gc
+        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
+        gclltype.use_gc = DummyGC
+        cls.old = gclltype.use_gc
+
+    def teardown_class(cls):
+        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
+        gclltype.use_gc = cls.old
+

Modified: pypy/branch/hl-backend/pypy/rpython/memory/test/test_lltypesimulation.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/memory/test/test_lltypesimulation.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/memory/test/test_lltypesimulation.py	Fri Oct 14 17:44:56 2005
@@ -121,6 +121,11 @@
     assert s1.a == 17
     assert s1.rest[3].v == 5
 
+def test_empty_struct():
+    S1 = lltype.GcStruct("s1")
+    s1 = malloc(S1)
+    assert s1 == s1
+
 def test_substructure_ptr():
     S3 = lltype.Struct("s3", ('a', lltype.Signed))
     S2 = lltype.Struct("s2", ('s3', S3), ('char', lltype.Char))

Modified: pypy/branch/hl-backend/pypy/rpython/module/ll_stackless.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/module/ll_stackless.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/module/ll_stackless.py	Fri Oct 14 17:44:56 2005
@@ -1,6 +1,5 @@
 from pypy.rpython import objectmodel
 
-
 def ll_stackless_stack_frames_depth():
     return objectmodel.stack_frames_depth()
 ll_stackless_stack_frames_depth.suggested_primitive = True

Modified: pypy/branch/hl-backend/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/objectmodel.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/objectmodel.py	Fri Oct 14 17:44:56 2005
@@ -38,9 +38,22 @@
 def hlinvoke(repr, llcallable, *args):
     raise TypeError, "hlinvoke is meant to be rtyped and not called direclty"
 
+def stack_unwind():
+    pass
+
 def stack_frames_depth():
     return len(inspect.stack())
 
+def stack_too_big():
+    return False
+
+def stack_check():
+    if stack_too_big():
+        # stack_unwind implementation is different depending on if stackless
+        # is enabled. If it is it unwinds the stack, otherwise it simply
+        # raises a RuntimeError.
+        stack_unwind()
+
 # ____________________________________________________________
 
 

Modified: pypy/branch/hl-backend/pypy/rpython/rint.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rint.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/rint.py	Fri Oct 14 17:44:56 2005
@@ -295,7 +295,9 @@
         sign = 0
         if i < 0:
             sign = 1
-            i = -i
+            i = r_uint(-i)
+        else:
+            i = r_uint(i)
         if i == 0:
             len = 1
             temp[0] = '0'

Modified: pypy/branch/hl-backend/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/rtyper.py	Fri Oct 14 17:44:56 2005
@@ -25,6 +25,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.tool.sourcetools import func_with_new_name, valid_identifier
 from pypy.translator.unsimplify import insert_empty_block
+from pypy.translator.transform import insert_stackcheck
 from pypy.rpython.rmodel import Repr, inputconst
 from pypy.rpython.rmodel import TyperError, BrokenReprTyperError
 from pypy.rpython.rmodel import warning
@@ -139,8 +140,10 @@
         """Main entry point: specialize all annotated blocks of the program."""
         self.crash_on_first_typeerror = crash_on_first_typeerror
         # specialize depends on annotator simplifications
+        insert_stackcheck(self.annotator)
         if not dont_simplify_again:
             self.annotator.simplify()
+            
         # first make sure that all functions called in a group have exactly
         # the same signature, by hacking their flow graphs if needed
         perform_normalizations(self)

Modified: pypy/branch/hl-backend/pypy/rpython/test/test_rint.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/test/test_rint.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/test/test_rint.py	Fri Oct 14 17:44:56 2005
@@ -1,3 +1,4 @@
+import sys
 from pypy.translator.translator import Translator
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.annotation import model as annmodel
@@ -62,7 +63,10 @@
 
     res = interpret(dummy, [-123])
     assert ''.join(res.chars) == '-123'
-    
+
+    res = interpret(dummy, [-sys.maxint-1])
+    assert ''.join(res.chars) == str(-sys.maxint-1)
+
 def test_hex_of_int():
     def dummy(i):
         return hex(i)

Modified: pypy/branch/hl-backend/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/test/test_rlist.py	Fri Oct 14 17:44:56 2005
@@ -1,3 +1,4 @@
+import sys
 from pypy.translator.translator import Translator
 from pypy.rpython.lltype import *
 from pypy.rpython.rtyper import RPythonTyper
@@ -500,3 +501,14 @@
     assert res == 2
     res = interpret(fn, [6])
     assert res == 100
+
+def test_memoryerror():
+    def fn(i):
+        lst = [0] * i
+        lst[i-1] = 5
+        return lst[0]
+    res = interpret(fn, [1])
+    assert res == 5
+    res = interpret(fn, [2])
+    assert res == 0
+    interpret_raises(MemoryError, fn, [sys.maxint])

Modified: pypy/branch/hl-backend/pypy/rpython/test/test_rstr.py
==============================================================================
--- pypy/branch/hl-backend/pypy/rpython/test/test_rstr.py	(original)
+++ pypy/branch/hl-backend/pypy/rpython/test/test_rstr.py	Fri Oct 14 17:44:56 2005
@@ -472,6 +472,17 @@
                 res = interpret(fn, [i, j])
                 assert res == expected
 
+def test_int_valueerror():
+    s1 = ['42g', '?']
+    def fn(i):
+        try:
+            return int(s1[i])
+        except ValueError:
+            return -654
+    res = interpret(fn, [0])
+    assert res == -654
+    res = interpret(fn, [1])
+    assert res == -654
 
 def test_char_mul_n():
     def f(c, n):

Modified: pypy/branch/hl-backend/pypy/translator/asm/genasm.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/asm/genasm.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/asm/genasm.py	Fri Oct 14 17:44:56 2005
@@ -2,6 +2,7 @@
 from pypy.objspace.flow.model import traverse, Block, Variable, Constant
 from pypy.translator.asm import infregmachine
 from pypy.rpython.lltype import Signed
+from pypy.translator.asm.simulator import Machine, TranslateProgram
 
 #Available Machine code targets (processor+operating system)
 TARGET_UNKNOWN=0
@@ -33,7 +34,7 @@
     from pypy.translator.asm.i386gen.i386_assembler import make_func
 
 
-def genasm(translator):
+def genasm(translator, processor):
 
     f = translator.entrypoint
 
@@ -48,10 +49,27 @@
 
     g = FuncGenerator(graph)
     g.gencode()
-#    g.assembler.dump()
-    finreg = g.assembler.allocate_registers(30)
 
-    return make_func(finreg.assemble(), 'i', 'i'*len(graph.startblock.inputargs))
+    if processor == 'virt':
+        def r(*args):
+            return Machine.RunProgram(g.assembler.instructions,
+                                      args,
+                                      tracing=True)
+
+        return r
+    elif processor == 'virtfinite':
+        insns = TranslateProgram(g.assembler.instructions, 50)
+        for i in insns:
+            print i
+        def r(*args):
+            return Machine.RunProgram(insns,
+                                      args,
+                                      tracing=True)
+
+        return r
+    elif processor == 'ppc':
+        from pypy.translator.asm.ppc import codegen
+        return codegen.make_native_code(graph, g.assembler.instructions)
 
 class FuncGenerator(object):
 
@@ -71,7 +89,7 @@
         self.assembler = infregmachine.Assembler()
 
         for i, var in enumerate(graph.startblock.inputargs):
-            self.emit('LIA', self.reg(var), i)
+            self.emit('LIA', self.reg(var), Constant(i))
 
     def assign_register(self, var):
         assert var not in self._var2reg
@@ -85,7 +103,7 @@
         if isinstance(var, Constant):
             r = self.next_register
             assert isinstance(var.value, int)
-            self.assembler.emit("LOAD", r, var.value)
+            self.assembler.emit("LOAD", r, var)
             self.next_register += 1
             return r
         elif isinstance(var, Variable):
@@ -128,7 +146,8 @@
             assert block.exitswitch is not None
             falselink, truelink = block.exits
             lastop = block.operations[-1]
-            assert lastop.opname in ['int_gt', 'int_lt', 'int_ge']
+            assert lastop.opname in ['int_gt', 'int_lt', 'int_ge',
+                                     'int_eq', 'int_le', 'int_ne']
             A.emit(lastop.opname, *map(self.reg, lastop.args))
             b = self.blockname()
             A.emit('JT', b)

Modified: pypy/branch/hl-backend/pypy/translator/asm/infregmachine.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/asm/infregmachine.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/asm/infregmachine.py	Fri Oct 14 17:44:56 2005
@@ -6,12 +6,15 @@
         self.arguments = arguments
 
     def registers_used(self):
-        if self.name == 'LIA' or self.name == 'LOAD':
-            return [self.arguments[0]]
-        elif self.name in ('JT', 'JF', 'J'):
-            return []
-        else:
-            return list(self.arguments)
+        return [a for a in self.arguments if isinstance(a, int)]
+
+    def renumber(self, regmap):
+        def _(a):
+            if isinstance(a, int) and a in regmap:
+                return regmap[a]
+            else:
+                return a
+        return Instruction(self.name, map(_, self.arguments))
 
     def __repr__(self):
         if self.name == 'LIA':
@@ -20,10 +23,28 @@
         elif self.name in ('JT', 'JF', 'J'):
             args = self.arguments[0]
         elif self.name == 'LOAD':
-            args = 'r%s, %s'%tuple(self.arguments)
+            args = 'r%s, #%s'%tuple(self.arguments)
         else:
-            args = ', '.join(['r%s'%a for a in self.arguments])
-        return '    %-10s %s'%(self.name, args)
+            def c(x):
+                if isinstance(x, int):
+                    return 'r%s'%x
+                else:
+                    return str(x)
+            args = ', '.join(map(c, self.arguments))
+        return '%-30s'%('    %-10s %s'%(self.name, args),)
+
+class Program(object):
+    # approximately a list of Instructions, but with sprinkles
+    # not used yet.
+
+    def __init__(self, insns):
+        self.insns = insns
+
+    def iterinsns(self):
+        for insn in self.insns:
+            if isinstance(ins, str):
+                continue
+            yield insn
 
 class Assembler(object):
     def __init__(self):
@@ -40,67 +61,3 @@
             if isinstance(i, str):
                 i += ':'
             print i
-
-    def allocate_registers(self, nregisters):
-        r = FiniteRegisterAssembler(nregisters)
-        for i in self.instructions:
-            if not isinstance(i, str): # labels
-                assert max(i.registers_used() + [0]) < nregisters
-            r.instructions.append(i)
-        return r
-
-class FiniteRegisterAssembler(Assembler):
-    def __init__(self, nregisters):
-        Assembler.__init__(self)
-        self.nregisters = nregisters
-
-    def assemble(self):
-        from pypy.translator.asm.ppcgen import ppc_assembler
-        A = ppc_assembler.PPCAssembler()
-
-        for i in self.instructions:
-            if isinstance(i, str):
-                A.label(i)
-                continue
-
-            getattr(self, i.name)(A, *i.arguments)
-
-        return A
-
-    def LIA(self, A, dest, argindex):
-        assert dest + 2 == argindex + 3
-
-    def LOAD(self, A, dest, value):
-        assert isinstance(value, int)
-        assert -30000 < value < 30000
-        A.li(dest + 2, value)
-
-    def int_add(self, A, dest, a, b):
-        A.add(dest + 2, a + 2, b + 2)
-
-    def int_sub(self, A, dest, a, b):
-        A.sub(dest + 2, a + 2, b + 2)
-
-    def int_mul(self, A, dest, a, b):
-        A.mullw(dest + 2, a + 2, b + 2)
-
-    def int_gt(self, A, a, b):
-        A.cmpw(a + 2, b + 2)
-        A.crmove(0, 1)
-
-    def int_lt(self, A, a, b):
-        A.cmpw(a + 2, b + 2)
-
-    def JT(self, A, branch):
-        # should be "A.bt(BI=0, BD=branch)" but this crashes.
-        A.blt(branch)
-
-    def J(self, A, branch):
-        A.b(branch)
-
-    def RETPYTHON(self, A, reg):
-        A.mr(3, reg + 2)
-        A.blr()
-
-    def MOV(self, A, dest, src):
-        A.mr(dest + 2, src + 2)

Modified: pypy/branch/hl-backend/pypy/translator/asm/ppcgen/func_builder.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/asm/ppcgen/func_builder.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/asm/ppcgen/func_builder.py	Fri Oct 14 17:44:56 2005
@@ -7,14 +7,14 @@
     code.lwz(rD, r4, 12 + 4*argi)
     if typecode == 'i':
         code.load_word(r0, lookup("PyInt_Type"))
-        code.lwz(r15, rD, 4) # XXX ick!
-        code.cmpw(r0, r15)
+        code.lwz(r31, rD, 4) # XXX ick!
+        code.cmpw(r0, r31)
         code.bne("argserror")
         code.lwz(rD, rD, 8)
     elif typecode == 'f':
         code.load_word(r0, lookup("PyFloat_Type"))
-        code.lwz(r15, rD, 4)
-        code.cmpw(r0, r15)
+        code.lwz(r31, rD, 4)
+        code.cmpw(r0, r31)
         code.bne("argserror")
         code.lfd(rD-2, rD, 8)
     elif typecode != "O":
@@ -22,16 +22,18 @@
 
 FAST_ENTRY_LABEL = "FAST-ENTRY-LABEL"
 
-def make_func(code, retcode, signature):
+def make_func(code, retcode, signature, localwords=0):
     """code shouldn't contain prologue/epilogue (or touch r31)"""
 
+    stacksize = 80 + 4*localwords
+
     argcount = len(signature)
 
     ourcode = MyPPCAssembler()
     ourcode.mflr(r0)
     ourcode.stmw(r31, r1, -4)
     ourcode.stw(r0, r1, 8)
-    ourcode.stwu(r1, r1, -80)
+    ourcode.stwu(r1, r1, -stacksize)
 
     ourcode.lwz(r3, r4, 8)
     ourcode.cmpwi(r3, argcount)
@@ -47,7 +49,7 @@
         load_arg(ourcode, 1, signature[1])
 
     ourcode.bl(FAST_ENTRY_LABEL)
-    
+
     if retcode == 'i':
         s = lookup("PyInt_FromLong")
         ourcode.load_word(r0, s)
@@ -60,8 +62,8 @@
         ourcode.bctrl()
 
     ourcode.label("epilogue")
-    ourcode.lwz(r0, r1, 88)
-    ourcode.addi(r1, r1, 80)
+    ourcode.lwz(r0, r1, stacksize + 8)
+    ourcode.addi(r1, r1, stacksize)
     ourcode.mtlr(r0)
     ourcode.lmw(r31, r1, -4)
     ourcode.blr()
@@ -96,7 +98,7 @@
     return r
 
 def wrap(funcname, retcode, signature):
-    
+
     argcount = len(signature)
 
     ourcode = MyPPCAssembler()
@@ -118,11 +120,11 @@
     if argcount > 1:
         load_arg(ourcode, 1, signature[1])
 
-    
+
     ourcode.load_word(r0, lookup(funcname))
     ourcode.mtctr(r0)
     ourcode.bctrl()
-    
+
     if retcode == 'i':
         s = lookup("PyInt_FromLong")
         ourcode.load_word(r0, s)

Modified: pypy/branch/hl-backend/pypy/translator/asm/test/test_asm.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/asm/test/test_asm.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/asm/test/test_asm.py	Fri Oct 14 17:44:56 2005
@@ -1,14 +1,11 @@
 from pypy.translator.translator import Translator
+from pypy.rpython.rarithmetic import ovfcheck
 import py
 import os
 
 class TestAsm(object):
 
-    def setup_class(cls):
-        if not hasattr(os, "uname") or os.uname()[-1] != 'Power Macintosh':
-            py.test.skip('asm generation only on PPC')
-        
-        cls.processor = 'ppc'
+    processor = 'virt'
 
     def getcompiled(self, func, view=False):
         t = Translator(func, simplifying=True)
@@ -44,8 +41,8 @@
                 return x + y - 42
         f = self.getcompiled(testfn)#, view=True)
 
-        assert f(2, 3) == testfn(2, 3)
         assert f(-2, 3) == testfn(-2, 3)
+        assert f(2, 5) == testfn(2, 5)
 
     def test_loop(self):
         def testfn(lim=int):
@@ -61,4 +58,80 @@
         assert f(10) == testfn(10)
         assert f(100) == testfn(100)
         assert f(1000) == testfn(1000)
-            
+
+    def test_factor(self):
+        def factor(n=int):
+            i = 2
+            while i < n:
+                if n % i == 0:
+                    return i
+                i += 1
+            return i
+        f = self.getcompiled(factor)
+
+        assert f(25) == 5
+        assert f(27) == 3
+        assert f(17*13) == 13
+        assert f(29) == 29
+
+    def test_from_psyco(self):
+        def f1(n=int):
+            "Arbitrary test function."
+            i = 0
+            x = 1
+            while i<n:
+                j = 0
+                while j<=i:
+                    j = j + 1
+                    x = x + (i&j)
+                i = i + 1
+            return x
+
+        f = self.getcompiled(f1)
+        assert f(10) == f1(10)
+
+    def test_comparisons(self):
+        def f(x=int):
+            if x == 0:
+                return 0
+            elif x > 10:
+                return 10
+            elif x >= 5:
+                return 5
+            elif x < -10:
+                return -10
+            elif x <= -5:
+                return -5
+            elif x != 1:
+                return 1
+            else:
+                return x
+        g = self.getcompiled(f)
+        for i in range(-20, 20):
+            assert g(i) == f(i)
+
+    def dont_test_overflow(self):
+        def f(x=int, y=int):
+            try:
+                return ovfcheck(x*y)
+            except OverflowError:
+                return 0
+        g = self.getcompiled(f, view=True)
+        assert f(3, 4) == g(3, 4)
+        big = 1000000000
+        assert f(big, big) == g(big, big)
+        
+class TestAsmAfterAllocation(TestAsm):
+
+    processor = 'virtfinite'
+
+
+class TestAsmPPC(TestAsm):
+
+    processor = 'ppc'
+
+    def setup_class(cls):
+        if not hasattr(os, "uname") or os.uname()[-1] != 'Power Macintosh':
+            py.test.skip('asm generation only on PPC')
+
+

Modified: pypy/branch/hl-backend/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/extfunc.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/extfunc.py	Fri Oct 14 17:44:56 2005
@@ -4,7 +4,8 @@
 from pypy.rpython.rmodel import getfunctionptr
 from pypy.rpython.rstr import STR
 from pypy.rpython import rlist
-from pypy.rpython.module import ll_os, ll_time, ll_math, ll_strtod, ll_stackless
+from pypy.rpython.module import ll_os, ll_time, ll_math, ll_strtod
+from pypy.rpython.module import ll_stackless, ll_stack
 from pypy.module.thread.rpython import ll_thread
 
 
@@ -50,6 +51,8 @@
     ll_thread.ll_thread_start:     'LL_thread_start',
     ll_thread.ll_thread_get_ident: 'LL_thread_get_ident',
     ll_stackless.ll_stackless_stack_frames_depth: 'LL_stackless_stack_frames_depth',
+    ll_stack.ll_stack_unwind: 'LL_stack_unwind',
+    ll_stack.ll_stack_too_big: 'LL_stack_too_big',
     }
 
 #______________________________________________________

Modified: pypy/branch/hl-backend/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/funcgen.py	Fri Oct 14 17:44:56 2005
@@ -234,7 +234,11 @@
                     lst.append(self.expr(op.result))
                     lst.append(err)
                     line = '%s(%s);' % (macro, ', '.join(lst))
-                yield line
+                if '\n' in line:
+                    for subline in line.split('\n'):
+                        yield subline
+                else:
+                    yield line
                 if line.find(err) >= 0:
                     reachable_err = len(to_release)
                 to_release.append(op.result)
@@ -404,11 +408,11 @@
             # skip assignment of 'void' return value
             r = self.expr(op.result)
             line = '%s = %s' % (r, line)
-        line = '%s %s' % (line, self.check_directcall_result(op, err))
+        line = '%s\n%s' % (line, self.check_directcall_result(op, err))
         return line
 
     def check_directcall_result(self, op, err):
-        return 'if (RPyExceptionOccurred()) FAIL(%s);' % err
+        return 'if (RPyExceptionOccurred())\n\tFAIL(%s);' % err
 
     # low-level operations
     def generic_get(self, op, sourceexpr):
@@ -418,7 +422,7 @@
         # need to adjust the refcount of the result only for PyObjects
         if T == PyObjPtr:
             result.append(self.pyobj_incref_expr(newvalue, T))
-        result = '\t'.join(result)
+        result = '\n'.join(result)
         if T is Void:
             result = '/* %s */' % result
         return result
@@ -429,7 +433,7 @@
         # insert write barrier
         T = self.lltypemap(op.args[2])
         self.gcpolicy.write_barrier(result, newvalue, T, targetexpr)
-        result = '\t'.join(result)
+        result = '\n'.join(result)
         if T is Void:
             result = '/* %s */' % result
         return result
@@ -513,12 +517,20 @@
         eresult = self.expr(op.result)
         if VARPART.OF is Void:    # strange
             esize = 'sizeof(%s)' % (cdecl(typename, ''),)
+            result = ''
         else:
-            esize = 'sizeof(%s)+((%s-1)*sizeof(%s))' % (cdecl(typename, ''),
-                                                       elength,
-                                                       cdecl(itemtypename, ''))
-        result = self.gcpolicy.zero_malloc(TYPE, esize, eresult, err)
-        result += '\t%s->%s = %s;' % (eresult, lenfld, elength)
+            itemtype = cdecl(itemtypename, '')
+            result = 'OP_MAX_VARSIZE(%s, %s, %s);\n' % (
+                elength,
+                itemtype,
+                err)
+            esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % (
+                cdecl(typename, ''),
+                itemtype,
+                elength,
+                itemtype)
+        result += self.gcpolicy.zero_malloc(TYPE, esize, eresult, err)
+        result += '\n%s->%s = %s;' % (eresult, lenfld, elength)
         return result
 
     def OP_CAST_POINTER(self, op, err):

Modified: pypy/branch/hl-backend/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/gc.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/gc.py	Fri Oct 14 17:44:56 2005
@@ -107,10 +107,12 @@
         if increfstmt:
             result.append(increfstmt)
         if decrefstmt:
-            result.insert(0, '{ %s = %s;' % (
+            result.insert(0, '%s = %s;' % (
                 cdecl(self.db.gettype(T), 'prev'),
                 targetexpr))
             result.append(decrefstmt)
+            result[:] = ['\t%s' % line for line in result]
+            result[0] = '{' + result[0]
             result.append('}')
 
     def generic_dealloc(self, expr, T):
@@ -348,7 +350,7 @@
                                                                 is_varsize,
                                                                 err)
         if gcinfo and gcinfo.finalizer:
-            result += ('\tGC_REGISTER_FINALIZER(%s, %s, NULL, NULL, NULL);'
+            result += ('\nGC_REGISTER_FINALIZER(%s, %s, NULL, NULL, NULL);'
                        % (eresult, gcinfo.finalizer))
         return result
 

Modified: pypy/branch/hl-backend/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/genc.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/genc.py	Fri Oct 14 17:44:56 2005
@@ -11,7 +11,7 @@
 from pypy.rpython import lltype
 from pypy.tool.udir import udir
 
-class CBuilder: 
+class CBuilder(object):
     c_source_filename = None
     _compiled = False
     symboltable = None
@@ -23,7 +23,7 @@
 
         if libraries is None:
             libraries = []
-        self.libraries = libraries        
+        self.libraries = libraries
 
     def generate_source(self):
         assert self.c_source_filename is None
@@ -132,7 +132,8 @@
 
 # ____________________________________________________________
 
-SPLIT_CRITERIA = 170
+#SPLIT_CRITERIA = 32767 # enable to support VC++ 6.0
+SPLIT_CRITERIA = 65535 # support VC++ 7.2
 
 MARKER = '/*/*/' # provide an easy way to split after generating
 
@@ -148,9 +149,7 @@
 
     def set_strategy(self, path):
         all_nodes = list(self.database.globalcontainers())
-        # split off non-function nodes
-        # win32 has a problem: compiles but infinite recursion etc.
-        # trytocicumvent this by placing all non-func nodes into one file.
+        # split off non-function nodes. We don't try to optimize these, yet.
         funcnodes = []
         othernodes = []
         for node in all_nodes:
@@ -158,7 +157,8 @@
                 funcnodes.append(node)
             else:
                 othernodes.append(node)
-        if 1 or len(funcnodes) >= SPLIT_CRITERIA:##!!
+        # for now, only split for stand-alone programs.
+        if self.database.standalone:
             self.one_source_file = False
         self.funcnodes = funcnodes
         self.othernodes = othernodes
@@ -180,15 +180,26 @@
     def getothernodes(self):
         return self.othernodes[:]
 
-    def splitfuncnodes(self):
-        # silly first split, just by node count
-        # XXX filter constant stuff off and put it elsewhere
-        nodes = self.funcnodes[:]
-        nchunks = len(nodes) // SPLIT_CRITERIA or 1
-        chunksize = (len(nodes) + nchunks - 1) // nchunks
-        while nodes:
-            yield self.uniquecname('implement.c'), nodes[:chunksize]
-            del nodes[:chunksize]
+    def splitnodesimpl(self, basecname, nodes, nextra, nbetween):
+        # produce a sequence of nodes, grouped into files
+        # which have no more than SPLIT_CRITERIA lines
+        used = nextra
+        part = []
+        for node in nodes:
+            impl = list(node.implementation())
+            if not impl:
+                continue
+            cost = len(impl) + nbetween
+            if used + cost > SPLIT_CRITERIA and part:
+                # split if criteria met, unless we would produce nothing.
+                yield self.uniquecname(basecname), part
+                part = []
+                used = nextra
+            part.append( (node, impl) )
+            used += cost
+        # generate left pieces
+        if part:
+            yield self.uniquecname(basecname), part
 
     def gen_readable_parts_of_source(self, f):
         if self.one_source_file:
@@ -266,26 +277,33 @@
         print >> fc, '/***********************************************************/'
         fc.close()
 
-        name = self.uniquecname('nonfuncnodes.c')
-        print >> f, '/* %s */' % name
-        fc = self.makefile(name)
-        print >> fc, '/***********************************************************/'
-        print >> fc, '/***  Non-function Implementations                       ***/'
-        print >> fc
-        print >> fc, '#define PYPY_NOT_MAIN_FILE'
-        print >> fc, '#include "common_header.h"'
-        print >> fc, '#include "structdef.h"'
-        print >> fc, '#include "forwarddecl.h"'
-        print >> fc
-        print >> fc, '#include "src/g_include.h"'
-        print >> fc
-        print >> fc, MARKER
-        for node in self.getothernodes():
-            render_nonempty(node.implementation())
-        print >> fc, '/***********************************************************/'
-        fc.close()
+        nextralines = 11 + 1
+        for name, nodesimpl in self.splitnodesimpl('nonfuncnodes.c',
+                                                   self.othernodes,
+                                                   nextralines, 1):
+            print >> f, '/* %s */' % name
+            fc = self.makefile(name)
+            print >> fc, '/***********************************************************/'
+            print >> fc, '/***  Non-function Implementations                       ***/'
+            print >> fc
+            print >> fc, '#define PYPY_NOT_MAIN_FILE'
+            print >> fc, '#include "common_header.h"'
+            print >> fc, '#include "structdef.h"'
+            print >> fc, '#include "forwarddecl.h"'
+            print >> fc
+            print >> fc, '#include "src/g_include.h"'
+            print >> fc
+            print >> fc, MARKER
+            for node, impl in nodesimpl:
+                print >> fc, '\n'.join(impl)
+                print >> fc, MARKER
+            print >> fc, '/***********************************************************/'
+            fc.close()
 
-        for name, nodes in self.splitfuncnodes():
+        nextralines = 8 + len(self.preimpl) + 4 + 1
+        for name, nodesimpl in self.splitnodesimpl('implement.c',
+                                                   self.funcnodes,
+                                                   nextralines, 1):
             print >> f, '/* %s */' % name
             fc = self.makefile(name)
             print >> fc, '/***********************************************************/'
@@ -302,9 +320,9 @@
             print >> fc, '#include "src/g_include.h"'
             print >> fc
             print >> fc, MARKER
-            linecount = 12 + len(self.preimpl)
-            for node in nodes:
-                linecount += render_nonempty(node.implementation())
+            for node, impl in nodesimpl:
+                print >> fc, '\n'.join(impl)
+                print >> fc, MARKER
             print >> fc, '/***********************************************************/'
             fc.close()
         print >> f

Modified: pypy/branch/hl-backend/pypy/translator/c/src/address.h
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/src/address.h	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/src/address.h	Fri Oct 14 17:44:56 2005
@@ -5,9 +5,9 @@
 
 /***  binary operations ***/
 
-#define OP_ADR_DELTA(x,y,r,err) r = ((x) - (y))
-#define OP_ADR_SUB(x,y,r,err)   r = ((x) - (y))
-#define OP_ADR_ADD(x,y,r,err)   r = ((x) + (y))
+#define OP_ADR_DELTA(x,y,r,err) r = ((char *)(x) - (char *)(y))
+#define OP_ADR_SUB(x,y,r,err)   r = ((char *)(x) - (y))
+#define OP_ADR_ADD(x,y,r,err)   r = ((char *)(x) + (y))
 
 #define OP_ADR_EQ(x,y,r,err)	  r = ((x) == (y))
 #define OP_ADR_NE(x,y,r,err)	  r = ((x) != (y))

Modified: pypy/branch/hl-backend/pypy/translator/c/src/g_include.h
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/src/g_include.h	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/src/g_include.h	Fri Oct 14 17:44:56 2005
@@ -41,6 +41,8 @@
 #  include "src/ll_stackless.h"
 #endif
 
+#include "src/stack.h"
+
 #ifdef PYPY_STANDALONE
 #  include "src/main.h"
 #endif

Modified: pypy/branch/hl-backend/pypy/translator/c/src/ll_stackless.h
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/src/ll_stackless.h	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/src/ll_stackless.h	Fri Oct 14 17:44:56 2005
@@ -32,6 +32,7 @@
 slp_frame_t* slp_new_frame(int size, int state);
 long LL_stackless_stack_frames_depth(void);
 void slp_main_loop(void);
+char LL_stackless_stack_too_big(void);
 
 #ifndef PYPY_NOT_MAIN_FILE
 
@@ -53,6 +54,19 @@
   return f;
 }
 
+void LL_stackless_stack_unwind(void)
+{
+    if (slp_frame_stack_top)
+        goto resume;
+
+    slp_frame_stack_top = slp_frame_stack_bottom =
+        slp_new_frame(sizeof(slp_frame_t), 0);
+    return ;
+
+ resume:
+    slp_frame_stack_top = NULL;
+}
+
 
 /* example function for testing */
 
@@ -62,7 +76,7 @@
 	    goto resume;
 
 	slp_frame_stack_top = slp_frame_stack_bottom =
-		slp_new_frame(sizeof(slp_frame_t), 0);
+		slp_new_frame(sizeof(slp_frame_t), 1);
 	return -1;
 
  resume:
@@ -82,7 +96,6 @@
 
 #include "slp_state_decoding.h"
 
-
 void slp_main_loop(void)
 {
   int state, signature;
@@ -132,7 +145,8 @@
 
 int slp_standalone_entry_point(RPyListOfString *argv)
 {
-	int result = PYPY_STANDALONE(argv);
+	int result;
+	result = PYPY_STANDALONE(argv);
 	if (slp_frame_stack_bottom) {
 		slp_main_loop();
 		result = (int) slp_retval_long;
@@ -142,4 +156,5 @@
 
 #endif /* PYPY_NOT_MAIN_FILE */
 
-#endif USE_STACKLESS
+#endif /* USE_STACKLESS */
+

Modified: pypy/branch/hl-backend/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/src/mem.h	Fri Oct 14 17:44:56 2005
@@ -3,6 +3,17 @@
  /***  C header subsection: operations on LowLevelTypes    ***/
 
 
+/* a reasonably safe bound on the largest allowed argument value
+   that we can pass to malloc.  This is used for var-sized mallocs
+   to compute the largest allowed number of items in the array. */
+#define MAXIMUM_MALLOCABLE_SIZE   (LONG_MAX-4096)
+
+#define OP_MAX_VARSIZE(numitems, itemtype, err)  {			\
+    if ((numitems) > (MAXIMUM_MALLOCABLE_SIZE / sizeof(itemtype)))	\
+        FAIL_EXCEPTION(err, PyExc_MemoryError, "addr space overflow");	\
+  } 
+
+
 /* XXX hack to initialize the refcount of global structures: officially,
    we need a value equal to the number of references to this global from
    other globals, plus one.  This upper bound "approximation" will do... */

Modified: pypy/branch/hl-backend/pypy/translator/c/src/support.h
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/src/support.h	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/src/support.h	Fri Oct 14 17:44:56 2005
@@ -34,8 +34,13 @@
 PyObject* PyList_Pack(int n, ...);
 PyObject* PyDict_Pack(int n, ...);
 PyObject* PyTuple_Pack(int n, ...);
+#if PY_VERSION_HEX >= 0x02030000   /* 2.3 */
+# define PyObject_GetItem1  PyObject_GetItem
+# define PyObject_SetItem1  PyObject_SetItem
+#else
 PyObject* PyObject_GetItem1(PyObject* obj, PyObject* index);
 PyObject* PyObject_SetItem1(PyObject* obj, PyObject* index, PyObject* v);
+#endif
 PyObject* CallWithShape(PyObject* callable, PyObject* shape, ...);
 PyObject* decode_arg(PyObject* fname, int position, PyObject* name,
 			    PyObject* vargs, PyObject* vkwds, PyObject* def);
@@ -168,10 +173,7 @@
 }
 #endif
 
-#if PY_VERSION_HEX >= 0x02030000   /* 2.3 */
-# define PyObject_GetItem1  PyObject_GetItem
-# define PyObject_SetItem1  PyObject_SetItem
-#else
+#if PY_VERSION_HEX < 0x02030000   /* 2.3 */
 /* for Python 2.2 only */
 PyObject* PyObject_GetItem1(PyObject* obj, PyObject* index)
 {

Modified: pypy/branch/hl-backend/pypy/translator/c/stackless.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/stackless.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/stackless.py	Fri Oct 14 17:44:56 2005
@@ -11,16 +11,18 @@
 from pypy.translator.c.support import cdecl
 from pypy.translator.c.funcgen import FunctionCodeGenerator
 
-
 class StacklessData:
 
     def __init__(self):
         self.frame_types = {}
-        self.globalstatecounter = 1
         self.allsignatures = {}
         self.decode_table = []
+
         # start the decoding table with entries for the functions that
         # are written manually in ll_stackless.h
+        self.registerunwindable('LL_stackless_stack_unwind',
+                                lltype.FuncType([], lltype.Void),
+                                resume_points=1)
         self.registerunwindable('LL_stackless_stack_frames_depth',
                                 lltype.FuncType([], lltype.Signed),
                                 resume_points=1)
@@ -36,12 +38,17 @@
             for n in range(1, resume_points):
                 self.decode_table.append(('NULL', n))
 
-    def get_frame_type(self, n_integers, n_floats, n_pointers):
-        key = n_integers, n_floats, n_pointers
+    def get_frame_type(self, counts):
+        """Return the frame struct name,
+        named after the number of saved variables of each kind.
+        counts is a sequence of numbers, ordered like STATE_TYPES
+        """
+        key = tuple(counts)
         try:
             return self.frame_types[key]
         except KeyError:
-            name = 'slp_frame_%d_%d_%d_s' % key
+            nums = "_".join([str(c) for c in key])
+            name = 'slp_frame_%s_s' % nums
             self.frame_types[key] = name
             return name
 
@@ -56,37 +63,38 @@
         for line in sg.preimpl:
             print >> fc, line
         print >> fc, '#include "src/g_include.h"'
+
         items = self.frame_types.items()
         items.sort()
-        for (n_integers, n_floats, n_pointers), structname in items:
-            types = (['long']*n_integers +
-                     ['double']*n_floats +
-                     ['void *']*n_pointers)
-            varnames = (['l%d' % i for i in range(n_integers)] +
-                        ['d%d' % i for i in range(n_floats)] +
-                        ['v%d' % i for i in range(n_pointers)])
+        for counts, structname in items:
+            varnames = []
+            for count, vartype in zip(counts, STATE_TYPES):
+                varnames.extend([(vartype.ctype, '%s%d' % (vartype.prefix, i))
+                                 for i in range(count)])
+
+            # generate the struct definition
             fields = []
-            for type, varname in zip(types, varnames):
+            for type, varname in varnames:
                 fields.append('%s %s;' % (type, varname))
             print >> fi, 'struct %s { slp_frame_t header; %s };' % (
                 structname, ' '.join(fields))
 
+            # generate the 'save_' function
             arguments = ['int state']
             saving_lines = []
-            for type, varname in zip(types, varnames):
+            for type, varname in varnames:
                 arguments.append('%s %s' % (type, varname))
                 saving_lines.append('((struct %s*) f)->%s = %s;' % (
                     structname, varname, varname))
 
-            head = 'void *save_%(name)s(%(arguments)s);'
+            head = 'void save_%(name)s(%(arguments)s);'
             code = str(py.code.Source('''
-             void *save_%(name)s(%(arguments)s)
+             void save_%(name)s(%(arguments)s)
              {
                  slp_frame_t* f = slp_new_frame(sizeof(struct %(name)s), state);
                  slp_frame_stack_bottom->f_back = f;
                  slp_frame_stack_bottom = f;
                  %(saving_lines)s
-                 return NULL;
              }
             '''))
             argdict = {'name': structname,
@@ -110,11 +118,10 @@
             functiontype = sg.database.gettype(lltype.Ptr(FUNC))
             callexpr = '((%s) fn) (%s);' % (cdecl(functiontype, ''),
                                             ', '.join(dummyargs))
-            globalretvalvartype = simplified_type(FUNC.RESULT)
+            globalretvalvartype = storage_type(FUNC.RESULT)
             if globalretvalvartype is not None:
-                globalretvalvarname = RETVALVARS[globalretvalvartype]
-                callexpr = '%s = (%s) %s' % (globalretvalvarname,
-                                             globalretvalvartype,
+                callexpr = '%s = (%s) %s' % (globalretvalvartype.global_name,
+                                             globalretvalvartype.ctype,
                                              callexpr)
             print >> fi, '\t' + callexpr
             print >> fi, '\tbreak;'
@@ -163,11 +170,10 @@
             # record extra data needed to generate the slp_*.h tables:
             # find the signatures of all functions
             slpdata = self.db.stacklessdata
-            argtypes = [erase_ptr_type(v.concretetype)
+            argtypes = [signature_type(self.lltypemap(v))
                         for v in self.graph.getargs()]
             argtypes = [T for T in argtypes if T is not lltype.Void]
-            import sys
-            rettype = erase_ptr_type(self.graph.getreturnvar().concretetype)
+            rettype = signature_type(self.lltypemap(self.graph.getreturnvar()))
             FUNC = lltype.FuncType(argtypes, rettype)
             slpdata.registerunwindable(self.functionname, FUNC,
                                        resume_points = len(self.resumeblocks))
@@ -179,49 +185,38 @@
         stacklessdata = self.db.stacklessdata
         block = self.currentblock
         curpos = block.operations.index(op)
-
-        # XXX obscure: find all variables that are produced before 'op'
-        vars = []
-        for v in block.inputargs:
-            vars.append(v)
-        for op1 in block.operations[:curpos]:
-            vars.append(op1.result)
+        vars = list(variables_to_save_across_op(block, curpos))
 
         # get the simplified frame struct that can store these vars
-        counts = {"long":   [],
-                  "double": [],
-                  "void*":  []}
+        counts = dict([(type, []) for type in STATE_TYPES])
         variables_to_restore = []
         for v in vars:
-            st = simplified_type(erase_ptr_type(v.concretetype))
+            st = storage_type(self.lltypemap(v))
             if st is not None:   # ignore the Voids
                 varname = self.expr(v)
-                # XXX hackish: the name of the field in the structure is
-                # computed from the 1st letter of the 'st' type, counting
-                # from 0 for each of the 'st' types independently
+                # The name of the field in the structure is computed from
+                # the prefix of the 'st' type, counting from 0 for each
+                # of the 'st' types independently
                 variables_to_restore.append((v, '%s%d' % (
-                    st[0], len(counts[st]))))
-                counts[st].append('(%s)%s' % (st, varname))
-        structname = stacklessdata.get_frame_type(len(counts["long"]),
-                                                  len(counts["double"]),
-                                                  len(counts["void*"]))
+                    st.prefix, len(counts[st]))))
+                counts[st].append('(%s)%s' % (st.ctype, varname))
+        structname = stacklessdata.get_frame_type([len(counts[st]) for st in STATE_TYPES])
 
         # reorder the vars according to their type
-        vars = counts["long"] + counts["double"] + counts["void*"]
+        vars = sum([counts[st] for st in STATE_TYPES],[])
 
         # generate the 'save:' line, e.g.
         #      save_0: return (int) save_frame_1(0, (long) n);
         savelabel = 'save_%d' % len(self.savelines)
-        arguments = ['%d' % stacklessdata.globalstatecounter] + vars
-        stacklessdata.globalstatecounter += 1
+
+        # The globally unique number for our state
+        # is the total number of saved states so far
+        globalstatecounter = len(stacklessdata.decode_table) + len(self.savelines)
+        
+        arguments = ['%d' % globalstatecounter] + vars
+
         savecall = 'save_%s(%s);' % (structname, ', '.join(arguments))
-        retvar = self.graph.getreturnvar()
-        if retvar.concretetype is lltype.Void:
-            savecall += ' return;'
-        else:
-            retvartype = self.lltypename(retvar)
-            savecall = 'return (%s) %s' % (cdecl(retvartype, ''),
-                                           savecall)
+        savecall += ' return %s;' % self.error_return_value()
         self.savelines.append('%s: %s' % (savelabel, savecall))
 
         # generate the resume block, e.g.
@@ -238,9 +233,9 @@
                 varname, cdecl(vartype, ''), structname, fieldname))
         retvarname = self.expr(op.result)
         retvartype = self.lltypename(op.result)
-        retvarst = simplified_type(erase_ptr_type(op.result.concretetype))
+        retvarst = storage_type(self.lltypemap(op.result))
         if retvarst is not None:
-            globalretvalvarname = RETVALVARS[retvarst]
+            globalretvalvarname = retvarst.global_name
             lines.append('%s = (%s) %s;' % (
                 retvarname, cdecl(retvartype, ''), globalretvalvarname))
         lines.append('goto %s;' % (resumelabel,))
@@ -248,17 +243,18 @@
 
         # add the checks for the unwinding case just after the directcall
         # in the source
-        unwind_check = "if (slp_frame_stack_bottom) goto %s;" % (savelabel,)
+        unwind_check = "if (slp_frame_stack_bottom)\n\tgoto %s;" % (savelabel,)
         exception_check = (super(SlpFunctionCodeGenerator, self)
                            .check_directcall_result(op, err))
-        return '%s\n     %s:\n\t%s' % (unwind_check,
-                                       resumelabel,
-                                       exception_check)
+        return '%s\n  %s:\n%s' % (unwind_check,
+                                    resumelabel,
+                                    exception_check)
 
 
-def erase_ptr_type(T):
+def signature_type(T):
     """Return T unless it's a pointer type, in which case we return a general
     basic pointer type.
+    The returned type must have the same behaviour when put on the C stack.
     """
     if isinstance(T, lltype.Ptr):
         return Address
@@ -266,20 +262,55 @@
         return T
 
 
-def simplified_type(T):
+class StateVariableType:
+    def __init__(self, ctype, prefix, global_name):
+        self.ctype = ctype
+        self.prefix = prefix
+        self.global_name = global_name
+
+STATE_TYPES = [
+    StateVariableType('long',   'l', 'slp_retval_long'),
+    StateVariableType('void*',  'p', 'slp_retval_voidptr'),
+    StateVariableType('double', 'd', 'slp_retval_double'),
+    ]
+
+def storage_type(T):
+    """Return the type used to save values of this type
+    """
     if T is lltype.Void:
         return None
     elif T is lltype.Float:
-        return "double"
-    elif T is Address:
-        return "void*"
+        return STATE_TYPES[ 2 ]
+    elif T is Address or isinstance(T, lltype.Ptr):
+        return STATE_TYPES[ 1 ]
     elif isinstance(T, lltype.Primitive):
-        return "long"   # large enough for all other primitives
+        return STATE_TYPES[ 0 ] # long is large enough for all other primitives
     else:
         raise Exception("don't know about %r" % (T,))
 
-RETVALVARS = {
-    "double": "slp_retval_double",
-    "long"  : "slp_retval_long",
-    "void*" : "slp_retval_voidptr",
-    }
+def variables_to_save_across_op(block, opindex):
+    # variable lifetime detection:
+    # 1) find all variables that are produced before the operation
+    produced = {}
+    for v in block.inputargs:
+        produced[v] = True
+    for op1 in block.operations[:opindex]:
+        produced[op1.result] = True
+    # 2) find all variables that are used by or after the operation
+    consumed = {}
+    for op1 in block.operations[opindex:]:
+        for v in op1.args:
+            if isinstance(v, Variable):
+                consumed[v] = True
+    if isinstance(block.exitswitch, Variable):
+        consumed[block.exitswitch] = True
+    for link in block.exits:
+        for v in link.args:
+            if isinstance(v, Variable):
+                consumed[v] = True
+    # 3) variables that are atomic and not consumed after the operation
+    #    don't have to have their lifetime extended; that leaves only
+    #    the ones that are not atomic or consumed.
+    for v in produced:
+        if v in consumed or not v.concretetype._is_atomic():
+            yield v

Modified: pypy/branch/hl-backend/pypy/translator/c/test/test_annotated.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/test/test_annotated.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/test/test_annotated.py	Fri Oct 14 17:44:56 2005
@@ -1,5 +1,5 @@
 import autopath
-import py
+import py, sys
 from pypy.translator.tool.cbuild import skip_missing_compiler
 from pypy.translator.translator import Translator
 
@@ -167,13 +167,13 @@
         assert fn(-4.5) == 92.125
         assert fn(4.5) == 90.125
 
-    def test_recursion_detection(self):
-        def f(n=int, accum=int):
-            if n == 0:
-                return accum
-            else:
-                return f(n-1, accum*n)
+    def test_memoryerror(self):
+        def f(i=int):
+            lst = [0]*i
+            lst[-1] = 5
+            return lst[0]
         fn = self.getcompiled(f)
-        assert fn(7, 1) == 5040
-        py.test.skip("recursion detection: in-progress")
-        py.test.raises(RuntimeError, fn, -1, 0)
+        assert fn(1) == 5
+        assert fn(2) == 0
+        py.test.raises(MemoryError, fn, sys.maxint//2+1)
+        py.test.raises(MemoryError, fn, sys.maxint)

Modified: pypy/branch/hl-backend/pypy/translator/c/test/test_extfunc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/test/test_extfunc.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/test/test_extfunc.py	Fri Oct 14 17:44:56 2005
@@ -23,14 +23,18 @@
     f1 = compile(does_stuff, [])
     t0 = time.clock()
     t1 = f1()
-    t0 = (t0 + time.clock()) / 2.0
-    correct = t0 - t1
-    # now we can compare!
-    t0 = time.clock()
-    t1 = f1() + correct
-    assert type(t1) is float
     t2 = time.clock()
-    assert t0 <= t1 <= t2
+    t3 = f1()
+    t4 = time.clock()
+    t5 = f1()
+    t6 = time.clock()
+    # time.clock() and t1() might have a different notion of zero, so
+    # we can only subtract two numbers returned by the same function.
+    assert 0 <= t2-t0
+    assert 0 <= t3-t1 <= t4-t0
+    assert 0 <= t4-t2 <= t5-t1 <= t6-t0
+    assert 0 <= t5-t3 <= t6-t2
+    assert 0 <= t6-t4
 
 def test_time_sleep():
     def does_nothing():

Modified: pypy/branch/hl-backend/pypy/translator/c/test/test_lladdresses.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/test/test_lladdresses.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/test/test_lladdresses.py	Fri Oct 14 17:44:56 2005
@@ -71,4 +71,18 @@
     res = fc()
     assert res
 
-
+def test_pointer_comparison():
+    def f():
+        result = 0
+        for addr1 in [raw_malloc(1), NULL]:
+            addr2 = addr1 + 1
+            result = result * 2 + int(addr1 == addr2)
+            result = result * 2 + int(addr1 != addr2)
+            result = result * 2 + int(addr1 <  addr2)
+            result = result * 2 + int(addr1 <= addr2)
+            result = result * 2 + int(addr1 >  addr2)
+            result = result * 2 + int(addr1 >= addr2)
+        return result
+    fc = compile(f, [])
+    res = fc()
+    assert res == int('011100' * 2, 2)

Modified: pypy/branch/hl-backend/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/test/test_standalone.py	Fri Oct 14 17:44:56 2005
@@ -1,8 +1,8 @@
 from pypy.translator.translator import Translator
-from pypy.translator.tool.cbuild import build_executable 
+from pypy.translator.tool.cbuild import build_executable
 from pypy.annotation.model import SomeList, SomeString
 from pypy.annotation.listdef import ListDef
-from pypy.rpython.objectmodel import stack_frames_depth
+from pypy.rpython.objectmodel import stack_unwind, stack_frames_depth, stack_too_big
 import os
 
 
@@ -14,19 +14,19 @@
         for s in argv:
             os.write(1, "   '" + str(s) + "'\n")
         return 0
-    
+
     t = Translator(entry_point)
     s_list_of_strings = SomeList(ListDef(None, SomeString()))
     t.annotate([s_list_of_strings])
     t.specialize()
     cbuilder = t.cbuilder(standalone=True)
     cbuilder.generate_source()
-    cbuilder.compile() 
+    cbuilder.compile()
     data = cbuilder.cmdexec('hi there')
     assert data.startswith('''hello world\nargument count: 2\n   'hi'\n   'there'\n''')
 
 
-def test_stack_unwind():
+def test_stack_depth():
     def g1():
         "just to check Void special cases around the code"
     def g2(ignored):
@@ -64,6 +64,64 @@
     data = wrap_stackless_function(fn)
     assert data.strip() == '10'
 
+def test_stackless_manytimes():
+    def f(n):
+        if n > 0:
+            stack_frames_depth()
+            res = f(n-1)
+        else:
+            res = stack_frames_depth(), 1
+        return res
+
+    def fn():
+        count0, _ = f(0)
+        count10, _ = f(100)
+        return count10 - count0
+
+    data = wrap_stackless_function(fn)
+    assert data.strip() == '100'
+
+def test_stackless_arguments():
+    def f(n, d, t):
+        if n > 0:
+            res = f(n-1, d, t)
+        else:
+            res = stack_frames_depth(), d, t
+        return res
+
+    def fn():
+        count0, d, t = f(0, 5.5, (1, 2))
+        count10, d, t = f(10, 5.5, (1, 2))
+        return "[" + str(count10 - count0) + ", " + str(d) + ", " + str(t[0]) + ", " + str(t[1]) + "]"
+
+    data = wrap_stackless_function(fn)
+    assert eval(data) == [10, 5.5, 1, 2]
+
+
+def test_stack_too_big():
+    def f1():
+        return stack_too_big()
+    def f2():
+        return lst[1]()
+    def f3():
+        return lst[2]()
+    def f4():
+        return lst[3]()
+    def f5():
+        return lst[4]()
+    lst = [None,f1,f2,f3,f4,f5]
+
+    def f(n):
+        if lst[5]():
+            return n
+        return f(n)+1
+
+    def fn():
+        return f(0)
+    data = wrap_stackless_function(fn)
+    assert int(data.strip()) > 500
+
+
 
 def wrap_stackless_function(fn):
     def entry_point(argv):
@@ -72,10 +130,29 @@
 
     t = Translator(entry_point)
     s_list_of_strings = SomeList(ListDef(None, SomeString()))
-    t.annotate([s_list_of_strings])
+    ann = t.annotate([s_list_of_strings])
     t.specialize()
     cbuilder = t.cbuilder(standalone=True)
     cbuilder.stackless = True
     cbuilder.generate_source()
-    cbuilder.compile() 
+    cbuilder.compile()
     return cbuilder.cmdexec('')
+
+def test_stack_unwind():
+    def f():
+        stack_unwind()
+        return 42
+
+    data = wrap_stackless_function(f)
+    assert int(data.strip()) == 42
+
+def test_auto_stack_unwind():
+    def f(n):
+        if n == 1:
+            return 1
+        return (n+f(n-1)) % 1291
+
+    def fn():
+        return f(10**6)
+    data = wrap_stackless_function(fn)
+    assert int(data.strip()) == 704

Modified: pypy/branch/hl-backend/pypy/translator/c/test/test_typed.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/c/test/test_typed.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/c/test/test_typed.py	Fri Oct 14 17:44:56 2005
@@ -1,5 +1,6 @@
 import autopath
 import sys
+import py
 from py.test import raises
 from pypy.translator.translator import Translator
 from pypy.translator.test import snippet 
@@ -398,3 +399,13 @@
         f = self.getcompiled(fn)
         for args in [2, 7, 0], [7, 2, 0], [10, 50, 7], [50, -10, -3]:
             assert f(*args) == intmask(fn(*args))
+
+    def test_recursion_detection(self):
+        def f(n=int, accum=int):
+            if n == 0:
+                return accum
+            else:
+                return f(n-1, accum*n)
+        fn = self.getcompiled(f)
+        assert fn(7, 1) == 5040
+        py.test.raises(RuntimeError, fn, -1, 0)

Modified: pypy/branch/hl-backend/pypy/translator/goal/bench-windows.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/goal/bench-windows.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/goal/bench-windows.py	Fri Oct 14 17:44:56 2005
@@ -78,7 +78,7 @@
             CREATIONFLAGS = win32con.HIGH_PRIORITY_CLASS
             print "configured to run under high priority"
 
-BENCH_EXECONFIG = 'bench_windows_exe.txt'
+BENCH_EXECONFIG = '_bench_windows_exe.txt'
 bench_exe = None
 
 def reference(progname):
@@ -103,16 +103,22 @@
         size += os.path.getsize(win32api.GetModuleFileName(int(dll)))
     return ver, size
 
-def run_pystone(executable=reference('python'), n=0):
-    argstr = PYSTONE_CMD % (str(n) and n or '')
-    txt = run_cmd('%s -c "%s"' % (executable, argstr))
+def run_pystone(executable=reference('python'), n=0, rpy=False):
+    if rpy:
+        txt = run_cmd('%s pystone' % executable)
+    else:
+        argstr = PYSTONE_CMD % (str(n) and n or '')
+        txt = run_cmd('%s -c "%s"' % (executable, argstr))
     res = get_result(txt, PYSTONE_PATTERN)
     print res
     return res
 
-def run_richards(executable=reference('python'), n=20):
-    argstr = RICHARDS_CMD % n
-    txt = run_cmd('%s -c "%s"' % (executable, argstr))
+def run_richards(executable=reference('python'), n=20, rpy=False):
+    if rpy:
+        txt = run_cmd('%s richards' % executable)
+    else:
+        argstr = RICHARDS_CMD % n
+        txt = run_cmd('%s -c "%s"' % (executable, argstr))
     res = get_result(txt, RICHARDS_PATTERN)
     print res
     return res
@@ -122,7 +128,7 @@
     exes.sort()
     return exes
 
-STAT_FILE = 'bench_windows.dump'
+STAT_FILE = '_bench_windows.dump'
 def load_stats(statfile=STAT_FILE):
     try:
         dic = pickle.load(file(statfile, 'rb'))
@@ -134,9 +140,11 @@
     pickle.dump(dic, file(statfile, 'wb'))
 
 HEADLINE = '''\
-executable                  richards         pystone            size (MB)'''
+executable                  richards           pystone            size (MB)'''
 FMT = '''\
-%-27s'''                +    '%5d  %5.1fx    %7.1f  %5.1fx      %5.2f'
+%-27s'''             +    '%5d  %5.1fx' +  '  %9.1f  %5.1fx       %5.3f'
+FMT2 = '''\
+%-27s'''             +  '%5.3f  %5.1f/' +  '  %9.1f  %5.1f/       %5.3f'
 
 def main():
     print 'getting the richards reference'
@@ -149,25 +157,30 @@
         exename = os.path.splitext(exe)[0]
         mtime = os.path.getmtime(exe)
         size = os.path.getsize(exe)
+        rpy = size < 500000
         key = md5.new(file(exe,'rb').read()).digest()
         if key in prior:
             print 'skipped', exename
             resdic[key] = prior[key][:2] + (exename, mtime, size)
         else:
-            resdic[key] = (run_richards(exe, 2), run_pystone(exe, 20000),
+            resdic[key] = (run_richards(exe, 2,rpy), run_pystone(exe, 20000, rpy),
                            exename, mtime, size)
             prior[key] = resdic[key] # save result, temporarily
             save_stats(prior)
     save_stats(resdic) # save cleaned result
-    res = [ (mtime, exe, size, rich, stone)
+    res = [ (stone / rich, exe, size, rich, stone)
             for rich, stone, exe, mtime, size in resdic.values()]
     version, size = run_version_size()
-    res.append( (9e9, 'python %s' % version, size, ref_rich, ref_stone) )
+    res.append( (1.0, 'python %s' % version, size, ref_rich, ref_stone) )
     res.sort()
     print HEADLINE
-    for mtime, exe, size, rich, stone in res:
-        print FMT % (exe, rich, rich / ref_rich, stone, ref_stone / stone,
-                     size / float(1024 * 1024))
+    for speed2, exe, size, rich, stone in res:
+        if speed2 <= 1.0:
+            print FMT % (exe, rich, rich / ref_rich, stone, ref_stone / stone,
+                         size / float(1024 * 1024))
+        else:
+            print FMT2 % (exe, rich, ref_rich / rich, stone, stone / ref_stone,
+                          size / float(1024 * 1024))
 
 if __name__ == '__main__':
     main()

Modified: pypy/branch/hl-backend/pypy/translator/goal/driver.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/goal/driver.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/goal/driver.py	Fri Oct 14 17:44:56 2005
@@ -16,6 +16,7 @@
 
 DEFAULT_OPTIONS = optparse.Values(defaults={
   'gc': 'ref',
+  'stackless': False,
   'debug': True,
   'insist': False,
   'backend': 'c',
@@ -189,6 +190,7 @@
             gcpolicy = gc.NoneGcPolicy
 
         cbuilder = translator.cbuilder(standalone=standalone, gcpolicy=gcpolicy)
+        cbuilder.stackless = opt.stackless
         c_source_filename = cbuilder.generate_source()
         self.log.info("written: %s" % (c_source_filename,))
         self.cbuilder = cbuilder

Modified: pypy/branch/hl-backend/pypy/translator/goal/targetnopstandalone.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/goal/targetnopstandalone.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/goal/targetnopstandalone.py	Fri Oct 14 17:44:56 2005
@@ -1,3 +1,12 @@
+"""
+A simple standalone target.
+
+The target below specifies None as the argument types list.
+This is a case treated specially in driver.py . If the list
+of input types is empty, it is meant to be a list of strings,
+actually implementing argv of the executable.
+"""
+
 import os, sys
 
 def debug(msg): 
@@ -6,11 +15,10 @@
 # __________  Entry point  __________
 
 def entry_point(argv):
-    debug("done!")
+    debug("hello world")
     return 0
 
 # _____ Define and setup target ___
 
 def target(*args):
     return entry_point, None
-

Modified: pypy/branch/hl-backend/pypy/translator/goal/targetrichards.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/goal/targetrichards.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/goal/targetrichards.py	Fri Oct 14 17:44:56 2005
@@ -1,7 +1,9 @@
 from pypy.translator.goal import richards
+from pypy.translator.tool.taskengine import SimpleTaskEngine
 
 entry_point = richards.entry_point
 
+
 # _____ Define and setup target ___
 
 def target(*args):
@@ -18,3 +20,34 @@
     richards.main(iterations=5)
 
     
+class Tasks(SimpleTaskEngine):
+
+    def task_annotate(self):
+        pass
+    task_annotate.task_deps = []
+
+    def task
+
+
+""" sketch of tasks for translation:
+
+annotate:  # includes annotation and annotatation simplifications
+
+rtype: annotate
+
+backendoptimisations: rtype # make little sense otherwise
+
+source_llvm: backendoptimisations, rtype, annotate
+
+source_c: ?backendoptimisations, ?rtype, ?annotate
+
+compile_c : source_c
+
+compile_llvm: source_llvm
+
+run_c: compile_c
+
+run_llvm: compile_llvm
+
+"""
+ 

Modified: pypy/branch/hl-backend/pypy/translator/goal/translate_pypy.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/goal/translate_pypy.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/goal/translate_pypy.py	Fri Oct 14 17:44:56 2005
@@ -49,6 +49,7 @@
     '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm'])],
 
     '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'none'])],
+    '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)],
     },
 
 
@@ -97,6 +98,7 @@
 
     'gc': 'boehm',
     'backend': 'c',
+    'stackless': False,
     
     'batch': False,
     'text': False,

Modified: pypy/branch/hl-backend/pypy/translator/js/arraynode.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/arraynode.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/arraynode.py	Fri Oct 14 17:44:56 2005
@@ -39,14 +39,14 @@
     # ______________________________________________________________________
     # entry points from genllvm
     #
-    def writedatatypedecl(self, codewriter):
-        codewriter.arraydef(self.ref,
-                            'int',
-                            self.db.repr_type(self.arraytype))
-
-    def writedecl(self, codewriter): 
-        # declaration for constructor
-        codewriter.declare(self.constructor_decl)
+    #def writedatatypedecl(self, codewriter):
+    #    codewriter.arraydef(self.ref,
+    #                        'int',
+    #                        self.db.repr_type(self.arraytype))
+
+    #def writedecl(self, codewriter): 
+    #    # declaration for constructor
+    #    codewriter.declare(self.constructor_decl)
 
 
 class VoidArrayTypeNode(LLVMNode):
@@ -58,9 +58,9 @@
         self.array = array
         self.ref = "arraytype_Void"
 
-    def writedatatypedecl(self, codewriter):
-        td = "%s = type { int }" % self.ref
-        codewriter.append(td)
+    #def writedatatypedecl(self, codewriter):
+    #    td = "%s = type { int }" % self.ref
+    #    codewriter.append(td)
         
 class ArrayNode(ConstantLLVMNode):
     """ An arraynode.  Elements can be
@@ -91,6 +91,12 @@
         if p is not None:
             self.db.prepare_constant(lltype.typeOf(p), p)
 
+    def writedecl(self, codewriter):
+        if self.arraytype is lltype.Char:  #or use seperate nodetype
+            codewriter.declare(self.ref + ' = new String()')
+        else:
+            codewriter.declare(self.ref + ' = new Array()')
+
     def get_length(self):
         """ returns logical length of array """
         items = self.value.items
@@ -109,21 +115,22 @@
         return "{ int, [%s x %s] }" % (arraylen, typeval)
 
     def get_ref(self):
+        return self.ref
         #typeval = self.db.repr_type(lltype.typeOf(self.value))
         #ref = "cast (%s* %s to %s*)" % (self.get_typerepr(), self.ref, typeval)
-        p, c = lltype.parentlink(self.value)
-        assert p is None, "child arrays are NOT needed by rtyper"
+        #p, c = lltype.parentlink(self.value)
+        #assert p is None, "child arrays are NOT needed by rtyper"
         #return ref
-        return self.ref
 
     def get_pbcref(self, toptr):
-        ref = self.ref
-        p, c = lltype.parentlink(self.value)
-        assert p is None, "child arrays are NOT needed by rtyper"
-
-        fromptr = "%s*" % self.get_typerepr()
-        ref = "cast(%s %s to %s)" % (fromptr, ref, toptr)
-        return ref
+        return self.ref
+        #ref = self.ref
+        #p, c = lltype.parentlink(self.value)
+        #assert p is None, "child arrays are NOT needed by rtyper"
+        #
+        #fromptr = "%s*" % self.get_typerepr()
+        #ref = "cast(%s %s to %s)" % (fromptr, ref, toptr)
+        #return ref
 
     def get_childref(self, index):
         return "getelementptr(%s* %s, int 0, uint 1, int %s)" %(
@@ -156,9 +163,6 @@
     def get_arrayvalue(self):
         items = self.value.items
         item_length = len(items)
-        if item_length == 0 or items[-1] != chr(0):
-            items = items + [chr(0)]
-            item_length += 1
         s = []
         for c in items:
             if ord(c) in StrArrayNode.printables:
@@ -166,7 +170,7 @@
             else:
                 s.append("\\%02x" % ord(c))
                 
-        r = 'c"%s"' % "".join(s)
+        r = '"%s"' % "".join(s)
         return item_length, r
 
 class VoidArrayNode(ConstantLLVMNode):

Modified: pypy/branch/hl-backend/pypy/translator/js/codewriter.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/codewriter.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/codewriter.py	Fri Oct 14 17:44:56 2005
@@ -11,13 +11,18 @@
     def __init__(self, f, js): 
         self.f = f
         self.js = js
+        self._skip_closeblock = False
 
     def append(self, line, indentation_level=4): 
         if indentation_level:
             s = self.tabstring * indentation_level
         else:
             s = ''
-        self.f.write(s + line + '\n')
+        if not line or line[-1] in '{:};' or line.lstrip()[:2] == '//':
+            eol = '\n'
+        else:
+            eol = ';\n'
+        self.f.write(s + line + eol)
 
     def comment(self, line, indentation_level=4):
         self.append("// " + line, indentation_level)
@@ -30,10 +35,15 @@
 
     def label(self, name):
         self.append("case %d:" % name, 3)
-    openblock = label
+
+    def openblock(self, name):
+        self.append("case %d:" % name, 3)
+        self._currentblock = name
 
     def closeblock(self):
-        self.append('continue')
+        if not self._skip_closeblock:
+            self.append('break')
+        self._skip_closeblock = False
 
     def globalinstance(self, name, typeanddata):
         #self.append('%s = %s' % (name, typeanddata[1:].split('{')[1][:-1]), 0)
@@ -44,32 +54,61 @@
             self.llvm(line, 0)
 
     def structdef(self, name, typereprs):
-        self.llvm("%s = type { %s }" %(name, ", ".join(typereprs)), 0)
+        #self.llvm("%s = type { %s }" %(name, ", ".join(typereprs)), 0)
+        pass
 
     def arraydef(self, name, lentype, typerepr):
-        self.llvm("%s = type { %s, [0 x %s] }" % (name, lentype, typerepr), 0)
+        #self.llvm("%s = type { %s, [0 x %s] }" % (name, lentype, typerepr), 0)
+        pass
 
     def funcdef(self, name, rettyperepr, argtypereprs):
-        self.llvm("%s = type %s (%s)" % (name, rettyperepr,
-                                           ", ".join(argtypereprs)), 0)
+        #self.llvm("%s = type %s (%s)" % (name, rettyperepr,
+        #                                   ", ".join(argtypereprs)), 0)
+        pass
 
     def declare(self, decl):
-        #self.llvm("declare %s" % decl, 0)
-        pass
+        self.append(decl, 0)
 
     def startimpl(self):
         #self.llvm("implementation", 0)
         pass
 
-    def br_uncond(self, blockname): 
-        self.append('prevblock = block')
-        self.append('block = %d' % blockname)
-        #self.llvm("br label %s" %(blockname,))
-
-    def br(self, cond, blockname_false, blockname_true):
-        self.append('prevblock = block')
-        self.append('block = %s ? %d : %d' % (cond, blockname_true, blockname_false))
-        #self.llvm("br bool %s, label %s, label %s" % (cond, blockname_true, blockname_false))
+    def _goto_block(self, block, indentation_level=4):
+        if block == self._currentblock + 1:
+            self._skip_closeblock = True
+        else:
+            self.append('block = ' + str(block), indentation_level)
+            self.append('break', indentation_level)
+
+    def _phi(self, targetblock, exit, indentation_level=4):
+        #self.comment('target.inputargs=%s, args=%s, targetblock=%d' % (exit.target.inputargs, exit.args, targetblock), indentation_level)
+        for i, exitarg in enumerate(exit.args):
+            dest = str(exit.target.inputargs[i])
+            #src = str(exitarg)
+            src = str(self.js.db.repr_arg(exitarg))
+            if src == 'False':
+                src = 'false'
+            elif src == 'True':
+                src = 'true'
+            elif src == 'None':
+                src = 'undefined'
+            if dest != src:
+                self.append('%s = %s' % (dest, src), indentation_level)
+
+    def br_uncond(self, block, exit): 
+        self._phi(block, exit)
+        self._goto_block(block)
+        self._skip_closeblock = True
+
+    def br(self, cond, block_false, exit_false, block_true, exit_true):
+        self.append('if (%s) {' % cond)
+        self._phi(block_true, exit_true, 5)
+        self._goto_block(block_true, 5)
+        self.append('} else {')
+        self._phi(block_false, exit_false, 5)
+        self._goto_block(block_false, 5)
+        self.append('}')
+        self._skip_closeblock = True
 
     def switch(self, intty, cond, defaultdest, value_label):
         labels = ''
@@ -84,6 +123,10 @@
         self.blocks   = blocks
         usedvars      = {}  #XXX could probably be limited to inputvars
         for block in blocks:
+            if block != blocks[0]:  #don't double startblock inputargs
+                for inputarg in block.inputargs:
+                    targetvar = self.js.db.repr_arg(inputarg)
+                    usedvars[targetvar] = True
             for op in block.operations:
                 targetvar = self.js.db.repr_arg(op.result)
                 usedvars[targetvar] = True
@@ -91,49 +134,20 @@
         self.append("function %s {" % self.decl, 0)
         if usedvars:
             self.append("var %s" % ', '.join(usedvars.keys()), 1)
-        self.append("var block = 0", 1)
-        self.append("while (block != undefined) {", 1)
+        self.append("for (var block = 0;;) {", 1)
         self.append("switch (block) {", 2)
 
     def closefunc(self): 
-        self.append("} // end of switch (block)", 2)
-        self.append("} // end of while (block != undefined)", 1)
-        self.append("} // end of function %s" % self.decl, 0)
+        self.append("}", 2)
+        self.append("}", 1)
+        self.append("};", 0)
 
     def ret(self, type_, ref): 
         if type_ == 'void':
             self.append("return")
         else:
             self.append("return " + ref)
-
-    def phi(self, targetvar, type_, refs, blocknames): 
-        assert refs and len(refs) == len(blocknames), "phi node requires blocks" 
-        #mergelist = ", ".join(
-        #    ["[%s, %s]" % item 
-        #        for item in zip(refs, blocknames)])
-        #s = "%s = phi %s %s" % (targetvar, type_, mergelist)
-        #self.llvm(s)
-        all_refs_identical = True
-        for ref in refs:
-            if ref != refs[0]:
-                all_refs_identical = False
-                break
-        if all_refs_identical:
-            if targetvar != refs[0]:
-                self.append('%s = %s' % (targetvar, refs[0]))
-        else:
-            if len(blocknames) == 1:
-                self.append('%s = %s' % (targetvar, refs[i]))
-            else:
-                n = 0
-                for i, blockname in enumerate(blocknames):
-                    if targetvar != refs[i]:
-                        if n > 0:
-                            s = 'else '
-                        else:
-                            s = ''
-                        self.append('%sif (prevblock == %d) %s = %s' % (s, blockname, targetvar, refs[i]))
-                        n += 1
+        self._skip_closeblock = True
 
     def binaryop(self, name, targetvar, type_, ref1, ref2):
         self.append("%(targetvar)s = %(ref1)s %(name)s %(ref2)s" % locals())
@@ -155,10 +169,10 @@
                 self.append('%s = %s(%s)' % (targetvar, functionref, args))
 
     def cast(self, targetvar, fromtype, fromvar, targettype):
-        self.comment('codewriter cast 1 targettype=%(targettype)s, targetvar=%(targetvar)s, fromtype=%(fromtype)s, fromvar=%(fromvar)s' % locals())
+        #self.comment('codewriter cast 1 targettype=%(targettype)s, targetvar=%(targetvar)s, fromtype=%(fromtype)s, fromvar=%(fromvar)s' % locals())
     	if fromtype == 'void' and targettype == 'void':
 		return
-        self.comment('codewriter cast 2')
+        #self.comment('codewriter cast 2')
         if targettype == fromtype:
             self.append("%(targetvar)s = %(fromvar)s" % locals())
         elif targettype in ('int','uint',):

Modified: pypy/branch/hl-backend/pypy/translator/js/database.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/database.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/database.py	Fri Oct 14 17:44:56 2005
@@ -213,7 +213,7 @@
         return self.obj2node.itervalues()
         
     # __________________________________________________________
-    # Representing variables and constants in LLVM source code 
+    # Representing variables and constants in Javascript source code 
 
     def repr_arg(self, arg):
         if isinstance(arg, Constant):
@@ -242,7 +242,7 @@
             if isinstance(type_, lltype.Primitive):
                 return self.primitives[type_]
             elif isinstance(type_, lltype.Ptr):
-                return self.repr_type(type_.TO) + '*'
+                return '' #self.repr_type(type_.TO) + 'XXX*'
             else: 
                 raise TypeError("cannot represent %r" %(type_,))
             
@@ -260,7 +260,8 @@
         type_ = lltype.typeOf(value)
         if isinstance(type_, lltype.Primitive):
             repr = self.primitive_to_str(type_, value)
-            return None, "%s %s" % (self.repr_type(type_), repr)
+            return None, repr
+            #return None, "%s %s" % (self.repr_type(type_), repr)
 
         elif isinstance(type_, lltype.Ptr):
             toptr = self.repr_type(type_)
@@ -333,13 +334,13 @@
     # __________________________________________________________
     # Other helpers
 
-    def is_function_ptr(self, arg):
-        if isinstance(arg, (Constant, Variable)): 
-            arg = arg.concretetype 
-            if isinstance(arg, lltype.Ptr):
-                if isinstance(arg.TO, lltype.FuncType):
-                    return True
-        return False
+    #def is_function_ptr(self, arg):
+    #    if isinstance(arg, (Constant, Variable)): 
+    #        arg = arg.concretetype 
+    #        if isinstance(arg, lltype.Ptr):
+    #            if isinstance(arg.TO, lltype.FuncType):
+    #                return True
+    #    return False
 
     def get_childref(self, parent, child):
         node = self.obj2node[parent]

Modified: pypy/branch/hl-backend/pypy/translator/js/funcnode.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/funcnode.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/funcnode.py	Fri Oct 14 17:44:56 2005
@@ -22,7 +22,7 @@
         self.db = db
         assert isinstance(type_, lltype.FuncType)
         self.type_ = type_
-        self.ref = self.make_ref('%functiontype', '')
+        self.ref = self.make_ref('functiontype', '')
  
     def __str__(self):
         return "<FuncTypeNode %r>" % self.ref
@@ -31,10 +31,10 @@
         self.db.prepare_type(self.type_.RESULT)
         self.db.prepare_type_multi(self.type_._trueargs())
  
-    def writedatatypedecl(self, codewriter):
-        returntype = self.db.repr_type(self.type_.RESULT)
-        inputargtypes = [self.db.repr_type(a) for a in self.type_._trueargs()]
-        codewriter.funcdef(self.ref, returntype, inputargtypes)
+    #def writedatatypedecl(self, codewriter):
+    #    returntype = self.db.repr_type(self.type_.RESULT)
+    #    inputargtypes = [self.db.repr_type(a) for a in self.type_._trueargs()]
+    #    codewriter.funcdef(self.ref, returntype, inputargtypes)
 
 class FuncNode(ConstantLLVMNode):
     __slots__ = "db value ref graph blockindex".split()
@@ -42,14 +42,15 @@
     def __init__(self, db, value):
         self.db = db
         self.value = value
-        self.ref   = self.make_ref('pypy_', value.graph.name)
+        pypy_prefix     = '' #pypy_
+        self.ref   = self.make_ref(pypy_prefix, value.graph.name)
         self.graph = value.graph
 
         self.db.genllvm.exceptionpolicy.transform(self.db.translator, self.graph)
         #remove_exception_mallocs(self.db.translator, self.graph, self.ref)
         #merge_mallocs(self.db.translator, self.graph, self.ref)
 
-        remove_double_links(self.db.translator, self.graph)
+        #remove_double_links(self.db.translator, self.graph)
 
     def __str__(self):
         return "<FuncNode %r>" %(self.ref,)
@@ -76,8 +77,8 @@
 
     # ______________________________________________________________________
     # main entry points from genllvm 
-    def writedecl(self, codewriter): 
-        codewriter.declare(self.getdecl())
+    #def writedecl(self, codewriter): 
+    #    codewriter.declare(self.getdecl())
 
     def writeimpl(self, codewriter):
         graph = self.graph
@@ -145,30 +146,30 @@
         return self.ref + "(%s)" % ", ".join(inputargs)
 
     def write_block(self, codewriter, block):
-        self.write_block_phi_nodes(codewriter, block)
+        #self.write_block_phi_nodes(codewriter, block)
         self.write_block_operations(codewriter, block)
         self.write_block_branches(codewriter, block)
 
-    def get_phi_data(self, block):
-        data = []
-        entrylinks = mkentrymap(self.graph)[block]
-        entrylinks = [x for x in entrylinks if x.prevblock is not None]
-        inputargs = self.db.repr_arg_multi(block.inputargs)
-        inputargtypes = self.db.repr_arg_type_multi(block.inputargs)
-        for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)):
-            names = self.db.repr_arg_multi([link.args[i] for link in entrylinks])
-            blocknames = [self.blockindex[link.prevblock] for link in entrylinks]
-            for i, link in enumerate(entrylinks):   #XXX refactor into a transformation
-                if link.prevblock.exitswitch == Constant(last_exception) and \
-                   link.prevblock.exits[0].target != block:
-                    blocknames[i] += '_exception_found_branchto_' + self.blockindex[block]
-            data.append( (arg, type_, names, blocknames) )
-        return data
-
-    def write_block_phi_nodes(self, codewriter, block):
-        for arg, type_, names, blocknames in self.get_phi_data(block):
-            if type_ != "void":
-                codewriter.phi(arg, type_, names, blocknames)
+    #def get_phi_data(self, block):
+    #    data = []
+    #    entrylinks = mkentrymap(self.graph)[block]
+    #    entrylinks = [x for x in entrylinks if x.prevblock is not None]
+    #    inputargs = self.db.repr_arg_multi(block.inputargs)
+    #    inputargtypes = self.db.repr_arg_type_multi(block.inputargs)
+    #    for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)):
+    #        names = self.db.repr_arg_multi([link.args[i] for link in entrylinks])
+    #        blocknames = [self.blockindex[link.prevblock] for link in entrylinks]
+    #        for i, link in enumerate(entrylinks):   #XXX refactor into a transformation
+    #            if link.prevblock.exitswitch == Constant(last_exception) and \
+    #               link.prevblock.exits[0].target != block:
+    #                blocknames[i] += '_exception_found_branchto_' + self.blockindex[block]
+    #        data.append( (arg, type_, names, blocknames) )
+    #    return data
+    #
+    #def write_block_phi_nodes(self, codewriter, block):
+    #    for arg, type_, names, blocknames in self.get_phi_data(block):
+    #        if type_ != "void":
+    #            codewriter.phi(arg, type_, names, blocknames)
 
     def write_block_branches(self, codewriter, block):
         #assert len(block.exits) <= 2    #more exits are possible (esp. in combination with exceptions)
@@ -176,11 +177,12 @@
             #codewriter.comment('FuncNode(ConstantLLVMNode) *last_exception* write_block_branches @%s@' % str(block.exits))
             return
         if len(block.exits) == 1:
-            codewriter.br_uncond(self.blockindex[block.exits[0].target])
+            codewriter.br_uncond(self.blockindex[block.exits[0].target], block.exits[0])
         elif len(block.exits) == 2:
             cond = self.db.repr_arg(block.exitswitch)
-            codewriter.br(cond, self.blockindex[block.exits[0].target],
-                          self.blockindex[block.exits[1].target])
+            codewriter.br(cond,
+                          self.blockindex[block.exits[0].target], block.exits[0],
+                          self.blockindex[block.exits[1].target], block.exits[1])
 
     def write_block_operations(self, codewriter, block):
         opwriter = OpWriter(self.db, codewriter, self, block)
@@ -212,7 +214,7 @@
 
     def write_returnblock(self, codewriter, block):
         assert len(block.inputargs) == 1
-        self.write_block_phi_nodes(codewriter, block)
+        #self.write_block_phi_nodes(codewriter, block)
         inputargtype = self.db.repr_arg_type(block.inputargs[0])
         inputarg = self.db.repr_arg(block.inputargs[0])
         codewriter.ret(inputargtype, inputarg)

Modified: pypy/branch/hl-backend/pypy/translator/js/js.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/js.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/js.py	Fri Oct 14 17:44:56 2005
@@ -4,6 +4,7 @@
     http://webreference.com/programming/javascript/
     http://mochikit.com/
     http://www.mozilla.org/js/spidermonkey/
+    svn co http://codespeak.net/svn/kupu/trunk/ecmaunit 
 '''
 
 #import os
@@ -77,7 +78,7 @@
         #    codewriter.comment("External Function Declarations")
         #    codewriter.append(llexterns_header)
 
-        codewriter.comment("Type Declarations", 0)
+        #codewriter.comment("Type Declarations", 0)
         #for c_name, obj in extern_decls:
         #    if isinstance(obj, lltype.LowLevelType):
         #        if isinstance(obj, lltype.Ptr):
@@ -85,33 +86,33 @@
         #        l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
         #        codewriter.append(l)
 
+        codewriter.comment("Function Implementation", 0)
+        for typ_decl in self.db.getnodes():
+            typ_decl.writeimpl(codewriter)
+
+        codewriter.comment("Forward Declarations", 0)
+        #for typ_decl in self.db.getnodes():
+        #    typ_decl.writedatatypedecl(codewriter)
         for typ_decl in self.db.getnodes():
-            typ_decl.writedatatypedecl(codewriter)
+            typ_decl.writedecl(codewriter)
 
         codewriter.comment("Global Data", 0)
         for typ_decl in self.db.getnodes():
             typ_decl.writeglobalconstants(codewriter)
 
-        codewriter.comment("Function Prototypes", 0)
+        #codewriter.comment("Function Prototypes", 0)
         #codewriter.append(extdeclarations)
         #codewriter.append(self.gcpolicy.declarations())
 
-        for typ_decl in self.db.getnodes():
-            typ_decl.writedecl(codewriter)
-
-        codewriter.comment("Function Implementation", 0)
-        codewriter.startimpl()
-        
-        for typ_decl in self.db.getnodes():
-            typ_decl.writeimpl(codewriter)
+        pypy_prefix = '' #pypy_
 
         #codewriter.append(self.exceptionpolicy.llvmcode(self.entrynode))
         #
         ## XXX we need to create our own main() that calls the actual entry_point function
-        #if entryfunc_name == 'pypy_entry_point': #XXX just to get on with translate_pypy
+        #if entryfunc_name == pypy_prefix + 'entry_point': #XXX just to get on with translate_pypy
         #    extfuncnode.ExternalFuncNode.used_external_functions['%main'] = True
         #
-        #elif entryfunc_name == 'pypy_main_noargs': #XXX just to get on with bpnn & richards
+        #elif entryfunc_name == pypy_prefix + 'main_noargs': #XXX just to get on with bpnn & richards
         #    extfuncnode.ExternalFuncNode.used_external_functions['%main_noargs'] = True
         #
         #for f in support_functions:
@@ -134,7 +135,7 @@
         graph      = self.db.obj2node[entry_point].graph
         startblock = graph.startblock
         args       = ','.join(['arguments[%d]' % i for i,v in enumerate(startblock.inputargs)])
-        self.wrappertemplate = "load('%s'); print(pypy_%s(%%s))" % (self.filename, graph.name)
+        self.wrappertemplate = "load('%s'); print(%s%s(%%s))" % (self.filename, pypy_prefix, graph.name)
 
         #codewriter.newline()
         #codewriter.comment("Wrapper code for the Javascript CLI", 0)

Modified: pypy/branch/hl-backend/pypy/translator/js/node.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/node.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/node.py	Fri Oct 14 17:44:56 2005
@@ -32,10 +32,10 @@
         pass
 
     # __________________ before "implementation" ____________________
-    def writedatatypedecl(self, codewriter):
-        """ write out declare names of data types 
-            (structs/arrays/function pointers)
-        """
+    #def writedatatypedecl(self, codewriter):
+    #    """ write out declare names of data types 
+    #        (structs/arrays/function pointers)
+    #    """
 
     def writeglobalconstants(self, codewriter):
         """ write out global values.  """

Modified: pypy/branch/hl-backend/pypy/translator/js/opaquenode.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/opaquenode.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/opaquenode.py	Fri Oct 14 17:44:56 2005
@@ -7,7 +7,7 @@
         assert isinstance(opaquetype, lltype.OpaqueType)
         self.db = db
         self.opaquetype = opaquetype
-        self.ref = "%%opaquetype.%s" % (opaquetype.tag)
+        self.ref = "opaquetype." + opaquetype.tag
         
     def __str__(self):
         return "<OpaqueNode %r>" %(self.ref,)
@@ -15,9 +15,9 @@
     # ______________________________________________________________________
     # main entry points from genllvm 
 
-    def writedatatypedecl(self, codewriter):
-        # XXX Dummy - not sure what what we want
-        codewriter.funcdef(self.ref, 'sbyte*', ['sbyte *'])
+    #def writedatatypedecl(self, codewriter):
+    #    # XXX Dummy - not sure what what we want
+    #    codewriter.funcdef(self.ref, 'sbyte*', ['sbyte *'])
 
 
 class OpaqueNode(ConstantLLVMNode):

Modified: pypy/branch/hl-backend/pypy/translator/js/opwriter.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/opwriter.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/opwriter.py	Fri Oct 14 17:44:56 2005
@@ -212,7 +212,7 @@
         targettype = self.db.repr_arg_type(op.result)
         fromvar = self.db.repr_arg(op.args[0])
         fromtype = self.db.repr_arg_type(op.args[0])
-        self.codewriter.comment(op.opname)
+        self.codewriter.comment('next line='+op.opname)
         self.codewriter.cast(targetvar, fromtype, fromvar, targettype)
     same_as = cast_primitive
 
@@ -254,8 +254,8 @@
         functionref = self.db.repr_arg(op_args[0])
         argrefs = self.db.repr_arg_multi(op_args[1:])
         argtypes = self.db.repr_arg_type_multi(op_args[1:])
-        if self.db.is_function_ptr(op.result):
-            returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
+        #if self.db.is_function_ptr(op.result):
+        #    returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
         self.codewriter.call(targetvar,returntype,functionref,argrefs,argtypes)
 
     def last_exception_type_ptr(self, op):
@@ -297,8 +297,8 @@
         block_label = self.node.blockindex[self.block]
         exc_label   = block_label + '_exception_handling'
 
-        if self.db.is_function_ptr(op.result):  #use longhand form
-            returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
+        #if self.db.is_function_ptr(op.result):  #use longhand form
+        #    returntype = "%s (%s)*" % (returntype, ", ".join(argtypes))
         self.codewriter.call(targetvar, returntype, functionref, argrefs,
                              argtypes, none_label, exc_label)
 
@@ -407,35 +407,27 @@
     def getfield(self, op): 
         tmpvar = self.db.repr_tmpvar()
         struct, structtype = self.db.repr_argwithtype(op.args[0])
-        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
         targetvar = self.db.repr_arg(op.result)
         targettype = self.db.repr_arg_type(op.result)
         if targettype != "void":
-            assert index != -1
-            self.codewriter.getelementptr(tmpvar, structtype, struct,
-                                          ("uint", index))        
-            self.codewriter.load(targetvar, targettype, tmpvar)
+            self.codewriter.append('%s = %s.%s' % (targetvar, struct, op.args[1].value)) #XXX move to codewriter
         else:
             self._skipped(op)
  
     def getsubstruct(self, op): 
         struct, structtype = self.db.repr_argwithtype(op.args[0])
-        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
+        #index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
         targetvar = self.db.repr_arg(op.result)
-        targettype = self.db.repr_arg_type(op.result)
-        assert targettype != "void"
-        self.codewriter.getelementptr(targetvar, structtype, 
-                                      struct, ("uint", index))        
+        #targettype = self.db.repr_arg_type(op.result)
+        #assert targettype != "void"
+        self.codewriter.append('%s = %s.%s' % (targetvar, struct, op.args[1].value)) #XXX move to codewriter
+        #self.codewriter.getelementptr(targetvar, structtype, struct, ("uint", index))        
          
     def setfield(self, op): 
-        tmpvar = self.db.repr_tmpvar()
         struct, structtype = self.db.repr_argwithtype(op.args[0])
-        index = self._getindexhelper(op.args[1].value, op.args[0].concretetype.TO)
         valuevar, valuetype = self.db.repr_argwithtype(op.args[2])
         if valuetype != "void": 
-            self.codewriter.getelementptr(tmpvar, structtype, struct,
-                                          ("uint", index))
-            self.codewriter.store(valuetype, valuevar, tmpvar) 
+            self.codewriter.append('%s.%s = %s' % (struct, op.args[1].value, valuevar)) #XXX move to codewriter
         else:
             self._skipped(op)
             
@@ -479,8 +471,9 @@
 
     def getarraysize(self, op):
         array, arraytype = self.db.repr_argwithtype(op.args[0])
-        tmpvar = self.db.repr_tmpvar()
-        self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0))
+        #tmpvar = self.db.repr_tmpvar()
+        #self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0))
         targetvar = self.db.repr_arg(op.result)
-        targettype = self.db.repr_arg_type(op.result)
-        self.codewriter.load(targetvar, targettype, tmpvar)
+        #targettype = self.db.repr_arg_type(op.result)
+        #self.codewriter.load(targetvar, targettype, tmpvar)
+        self.codewriter.append('%s = %s.length' % (targetvar, array)) #XXX move to codewriter

Modified: pypy/branch/hl-backend/pypy/translator/js/structnode.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/structnode.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/structnode.py	Fri Oct 14 17:44:56 2005
@@ -5,6 +5,11 @@
 
 log = log.structnode 
 
+def _rename_reserved_keyword(name):
+    if name in 'if then else function for while witch continue break super int bool Array String Struct Number'.split():
+        name += '_'
+    return name
+
 class StructTypeNode(LLVMNode):
     __slots__ = "db struct ref name".split()
 
@@ -32,9 +37,9 @@
     # ______________________________________________________________________
     # main entry points from genllvm 
 
-    def writedatatypedecl(self, codewriter):
-        fields_types = [self.db.repr_type(f) for f in self._fields()]
-        codewriter.structdef(self.ref, fields_types)
+    #def writedatatypedecl(self, codewriter):
+    #    fields_types = [self.db.repr_type(f) for f in self._fields()]
+    #    codewriter.structdef(self.ref, fields_types)
 
 class StructVarsizeTypeNode(StructTypeNode):
     __slots__ = "constructor_ref constructor_decl".split()
@@ -53,9 +58,9 @@
     # ______________________________________________________________________
     # main entry points from genllvm 
 
-    def writedecl(self, codewriter): 
-        # declaration for constructor
-        codewriter.declare(self.constructor_decl)
+    #def writedecl(self, codewriter): 
+    #    # declaration for constructor
+    #    codewriter.declare(self.constructor_decl)
 
     def writeimpl(self, codewriter):
         log.writeimpl(self.ref)
@@ -83,7 +88,7 @@
         self.db = db
         self.value = value
         self.structtype = self.value._TYPE
-        prefix = '%structinstance.'
+        prefix = 'structinstance_'
         name = str(value).split()[1]
         self.ref = self.make_ref(prefix, name)
         self._get_ref_cache = None
@@ -112,24 +117,26 @@
         p, c = lltype.parentlink(self.value)
         if p is not None:
             self.db.prepare_constant(lltype.typeOf(p), p)
-            
+
+    def writedecl(self, codewriter):
+        codewriter.declare(self.ref + ' = new Object()')
+        
     def get_typerepr(self):
         return self.db.repr_type(self.structtype)
 
     def get_childref(self, index):
-        pos = 0
-        found = False
-        for name in self.structtype._names_without_voids():
-            if name == index:
-                found = True
-                break
-            pos += 1
-        #Structure types require uint constants!
-        #see: http://llvm.cs.uiuc.edu/docs/LangRef.html#i_getelementptr
-        return "getelementptr(%s* %s, int 0, uint %s)" %(
-            self.get_typerepr(),
-            self.get_ref(),
-            pos)
+        return self.get_ref() #XXX what to do with index?
+        #pos = 0
+        #found = False
+        #for name in self.structtype._names_without_voids():
+        #    if name == index:
+        #        found = True
+        #        break
+        #    pos += 1
+        #return "getelementptr(%s* %s, int 0, uint %s)" %(
+        #    self.get_typerepr(),
+        #    self.get_ref(),
+        #    pos)
 
     def get_ref(self):
         """ Returns a reference as used for operations in blocks. """        
@@ -146,12 +153,20 @@
     def get_pbcref(self, toptr):
         """ Returns a reference as used per pbc. """        
         return self.get_ref()
-    
+
     def constantvalue(self):
         """ Returns the constant representation for this node. """
-        values = self._getvalues()
-        all_values = ",\n  ".join(values)
-        return "%s {\n  %s\n  }\n" % (self.get_typerepr(), all_values)
+        vars = []
+        for i, value in enumerate(self._getvalues()):
+            name = self._get_types[i][0]
+            name = _rename_reserved_keyword(name)
+            var  = (name, str(value))
+            vars.append(var)
+        return "({%s})" % ", ".join(["%s:%s" % var for var in vars])
+
+        #values = self._getvalues()
+        #all_values = ",\n  ".join(values)
+        #return "%s {\n  %s\n  }\n" % (self.get_typerepr(), all_values)
                 
                 
 class StructVarsizeNode(StructNode):
@@ -206,22 +221,24 @@
                 return result
          
     def get_ref(self):
-        if self._get_ref_cache:
-            return self._get_ref_cache
-        ref = super(StructVarsizeNode, self).get_ref()
-        typeval = self.db.repr_type(lltype.typeOf(self.value))
-        ref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
-                                        ref,
-                                        typeval)
-        self._get_ref_cache = ref
-        return ref
+        return self.ref
+        #if self._get_ref_cache:
+        #    return self._get_ref_cache
+        #ref = super(StructVarsizeNode, self).get_ref()
+        #typeval = self.db.repr_type(lltype.typeOf(self.value))
+        #ref = "cast (%s* %s to %s*)" % (self.get_typerepr(),
+        #                                ref,
+        #                                typeval)
+        #self._get_ref_cache = ref
+        #return ref
     
     def get_pbcref(self, toptr):
         """ Returns a reference as used per pbc. """        
-        ref = self.ref
-        p, c = lltype.parentlink(self.value)
-        assert p is None, "child arrays are NOT needed by rtyper"
-        fromptr = "%s*" % self.get_typerepr()
-        refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref)
-        ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr)
-        return ref
+        return self.ref
+        #ref = self.ref
+        #p, c = lltype.parentlink(self.value)
+        #assert p is None, "child arrays are NOT needed by rtyper"
+        #fromptr = "%s*" % self.get_typerepr()
+        #refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref)
+        #ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr)
+        #return ref

Modified: pypy/branch/hl-backend/pypy/translator/js/test/test_genllvm1.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/js/test/test_genllvm1.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/js/test/test_genllvm1.py	Fri Oct 14 17:44:56 2005
@@ -28,7 +28,7 @@
 
     def test_ackermann(self):
         f = compile_function(llvmsnippet.ackermann, [int, int])
-        for i in range(10):
+        for i in range(7):  #>7 js error: too much recursion?!?
             assert f(0, i) == i + 1
             assert f(1, i) == i + 2
             assert f(2, i) == 2 * i + 3

Modified: pypy/branch/hl-backend/pypy/translator/llvm/build_llvm_module.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/llvm/build_llvm_module.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/llvm/build_llvm_module.py	Fri Oct 14 17:44:56 2005
@@ -82,13 +82,19 @@
 
     use_gcc = True
     profile = False
+    cleanup = False
+
+    if sys.platform == 'darwin':
+        gc_libs_path = '-L/sw/lib -ldl'
+    else:
+        gc_libs_path = '-static'
 
     cmds = ["llvm-as < %s.ll | opt %s -f -o %s.bc" % (b, OPTIMIZATION_SWITCHES, b)]
     if not use_gcc:
         cmds.append("llc %s %s.bc -f -o %s.s" % (genllvm.exceptionpolicy.llc_options(), b, b))
         cmds.append("as %s.s -o %s.o" % (b, b))
         if exe_name:
-            cmd = "gcc %s.o %s -lm -ldl -pipe -o %s" % (b, gc_libs, exe_name)
+            cmd = "gcc %s.o %s %s -lm -pipe -o %s" % (b, gc_libs_path, gc_libs, exe_name)
             cmds.append(cmd)
         object_files.append("%s.o" % b)
     else:
@@ -100,13 +106,13 @@
             else:
                 cmd += ' -fomit-frame-pointer'
             cmds.append(cmd)
-            cmd = "gcc %s.o %s -lm -ldl -pipe -o %s" % (b, gc_libs, exe_name)
+            cmd = "gcc %s.o %s %s -lm -pipe -o %s" % (b, gc_libs_path, gc_libs, exe_name)
             if profile:
                 cmd += ' -pg'
             cmds.append(cmd)
         source_files.append("%s.c" % b)
 
-    if exe_name and not profile:
+    if cleanup and exe_name and not profile:
         cmds.append('strip ' + exe_name)
         upx = os.popen('which upx').read()
         if upx: #compress file even further

Modified: pypy/branch/hl-backend/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/llvm/externs2ll.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/llvm/externs2ll.py	Fri Oct 14 17:44:56 2005
@@ -1,4 +1,5 @@
 import os
+import sys
 import types
 import urllib
 
@@ -11,10 +12,20 @@
 
 
 def get_ll(ccode, function_names):
+    filename = str(udir.join("ccode.c"))
+    f = open(filename, "w")
+    f.write(ccode)
+    f.close()
     
-    # goto codespeak and compile our c code
-    request = urllib.urlencode({'ccode':ccode})
-    llcode = urllib.urlopen('http://codespeak.net/pypy/llvm-gcc.cgi', request).read()
+    if os.popen('which llvm-gcc').read():   #local llvm CFE available
+        #log('using local llvm-gcc')
+        plain = filename[:-2]
+        os.system("llvm-gcc -S %s.c -o %s.ll 2>&1" % (plain, plain))
+        llcode = open(plain + '.ll').read()
+    else:   #as fallback use remove CFE. XXX local and remote should be similar machines!
+        #log('falling back on remote llvm-gcc')
+        request = urllib.urlencode({'ccode':ccode}) # goto codespeak and compile our c code
+        llcode = urllib.urlopen('http://codespeak.net/pypy/llvm-gcc.cgi', request).read()
 
     # strip lines
     ll_lines = []
@@ -134,13 +145,14 @@
         include_files.append(j(j(os.path.dirname(extfunc.__file__), "src"), f + ".h"))
 
     for f in include_files:
-        ccode.append(open(f).read())
+        s = open(f).read()
+        if f.find('genexterns.c'):
+            if sys.platform == 'darwin':
+                python_h = '"/System/Library/Frameworks/Python.framework/Versions/2.3/include/python2.3/Python.h"'
+            else:
+                python_h = '<python2.3/Python.h>'
+            s = s.replace('__PYTHON_H__', python_h)
+        ccode.append(s)
     ccode = "".join(ccode)
 
-    if debug:
-        filename = udir.join("ccode.c")
-        f = open(str(filename), "w")
-        f.write(ccode)
-        f.close()
-    
     return get_ll(ccode, function_names + support_functions)

Modified: pypy/branch/hl-backend/pypy/translator/llvm/gc.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/llvm/gc.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/llvm/gc.py	Fri Oct 14 17:44:56 2005
@@ -25,7 +25,8 @@
         gcpolicy = gcpolicy or 'boehm'
         
         from os.path import exists
-        boehm_on_path = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a')
+        boehm_on_path = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') or \
+                        exists('/sw/lib/libgc.so') or exists('/sw/lib/libgc.a')
         if gcpolicy == 'boehm' and not boehm_on_path:
             log.gc.WARNING('warning: Boehm GC libary not found in /usr/lib, falling back on no gc')
             gcpolicy = 'none'

Modified: pypy/branch/hl-backend/pypy/translator/llvm/module/genexterns.c
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/llvm/module/genexterns.c	(original)
+++ pypy/branch/hl-backend/pypy/translator/llvm/module/genexterns.c	Fri Oct 14 17:44:56 2005
@@ -19,7 +19,9 @@
 #include <errno.h>
 #include <locale.h>
 #include <ctype.h>
-#include <python2.3/Python.h>
+
+//the placeholder in the next line gets replaced by the actual python.h path
+#include __PYTHON_H__
 
 // Do this manually from python :-(
 //#include "ll_os.h"

Modified: pypy/branch/hl-backend/pypy/translator/transform.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/transform.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/transform.py	Fri Oct 14 17:44:56 2005
@@ -14,7 +14,7 @@
 from pypy.translator.annrpython import CannotSimplify
 from pypy.annotation import model as annmodel
 from pypy.annotation.specialize import MemoTable
-
+from pypy.rpython.objectmodel import stack_check
 
 def checkgraphs(self, blocks):
     seen = {}
@@ -187,6 +187,30 @@
                                 else:
                                     op.opname = intern('call_specialcase')
 
+def insert_stackcheck(ann):
+    from pypy.tool.algo.graphlib import Edge, make_edge_dict, break_cycles
+    edges = []
+    for callposition, (caller, callee) in ann.translator.callgraph.items():
+        edge = Edge(caller, callee)
+        edge.callposition = callposition
+        edges.append(edge)
+    edgedict = make_edge_dict(edges)
+    for edge in break_cycles(edgedict, edgedict):
+        caller = edge.source
+        _, _, call_tag = edge.callposition
+        if call_tag:
+            _, caller_block, _ = call_tag
+        else:
+            ann.warning("cycle detected but no information on where to insert "
+                        "stack_check()")
+            continue
+        # caller block found, insert stack_check()
+        v = Variable()
+        # push annotation on v
+        ann.setbinding(v, annmodel.SomeImpossibleValue())
+        unwind_op = SpaceOperation('simple_call', [Constant(stack_check)], v)
+        caller_block.operations.insert(0, unwind_op)
+
 default_extra_passes = [
     transform_specialization,
     transform_allocate,

Modified: pypy/branch/hl-backend/pypy/translator/translator.py
==============================================================================
--- pypy/branch/hl-backend/pypy/translator/translator.py	(original)
+++ pypy/branch/hl-backend/pypy/translator/translator.py	Fri Oct 14 17:44:56 2005
@@ -329,11 +329,11 @@
         self.frozen = True
         return genllvm.genllvm(self, really_compile=really_compile, standalone=standalone, optimize=optimize, exe_name=exe_name, gcpolicy=gcpolicy)
 
-    def asmcompile(self, processor='ppc'):
+    def asmcompile(self, processor='virt'):
         from pypy.translator.asm import genasm
-        assert processor == 'ppc', 'only ppc asm-generation supported for now'
+        assert processor in ['ppc', 'virt', 'virtfinite']
         assert self.rtyper is not None, 'must specialize'
-        return genasm.genasm(self)
+        return genasm.genasm(self, processor)
 
     def call(self, *args):
         """Calls underlying Python function."""



More information about the Pypy-commit mailing list