[pypy-svn] r30238 - in pypy/dist/pypy/translator: c llvm llvm/module llvm/test

rxe at codespeak.net rxe at codespeak.net
Wed Jul 19 18:10:50 CEST 2006


Author: rxe
Date: Wed Jul 19 18:10:41 2006
New Revision: 30238

Added:
   pypy/dist/pypy/translator/llvm/test/test_stackless.py   (contents, props changed)
Removed:
   pypy/dist/pypy/translator/llvm/extfunchelper.py
   pypy/dist/pypy/translator/llvm/module/raisingop.h
Modified:
   pypy/dist/pypy/translator/c/exceptiontransform.py
   pypy/dist/pypy/translator/c/extfunc.py
   pypy/dist/pypy/translator/llvm/buildllvm.py
   pypy/dist/pypy/translator/llvm/database.py
   pypy/dist/pypy/translator/llvm/exception.py
   pypy/dist/pypy/translator/llvm/externs2ll.py
   pypy/dist/pypy/translator/llvm/funcnode.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/llvm/module/excsupport.py
   pypy/dist/pypy/translator/llvm/module/genexterns.c
   pypy/dist/pypy/translator/llvm/module/protos.h
   pypy/dist/pypy/translator/llvm/opwriter.py
Log:
use genc to transform our graphs (thanks to cfbolz for the idea)

* purge all exception related code out of genllvm
* introduced hacked version of _RPyExceptionOccurred() which is hopefully very
  temporary
* remove dead module/raisingop.h and other mess

all the tests pass - not sure if we can translate



Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Wed Jul 19 18:10:41 2006
@@ -54,7 +54,15 @@
         def rpyexc_occured():
             exc_type = exc_data.exc_type
             lloperation.llop.debug_log_exc(lltype.Void, exc_type)
-            return  exc_type is not null_type
+            return exc_type is not null_type
+
+        # XXX tmp HACK for genllvm
+        # llvm is strongly typed between bools and ints, which means we have no way of
+        # calling rpyexc_occured() from c code with lltype.Bool
+        def _rpyexc_occured():
+            exc_type = exc_data.exc_type
+            lloperation.llop.debug_log_exc(lltype.Void, exc_type)
+            return exc_type is not null_type
 
         def rpyexc_fetch_type():
             return exc_data.exc_type
@@ -78,6 +86,15 @@
             RPYEXC_OCCURED_TYPE, "RPyExceptionOccurred",
             graph=rpyexc_occured_graph),
             lltype.Ptr(RPYEXC_OCCURED_TYPE))
+
+        # XXX tmp HACK for genllvm
+        _RPYEXC_OCCURED_TYPE = lltype.FuncType([], lltype.Signed)
+        _rpyexc_occured_graph = mixlevelannotator.getgraph(
+            _rpyexc_occured, [], l2a(lltype.Signed))
+        self._rpyexc_occured_ptr = Constant(lltype.functionptr(
+            _RPYEXC_OCCURED_TYPE, "_RPyExceptionOccurred",
+            graph=_rpyexc_occured_graph),
+            lltype.Ptr(_RPYEXC_OCCURED_TYPE))
         
         RPYEXC_FETCH_TYPE_TYPE = lltype.FuncType([], self.lltype_of_exception_type)
         rpyexc_fetch_type_graph = mixlevelannotator.getgraph(

Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/extfunc.py	Wed Jul 19 18:10:41 2006
@@ -85,7 +85,7 @@
             return r.lowleveltype.TO
     return None
 
-def predeclare_common_types(db, rtyper, optimize=True):
+def predeclare_common_types(db, rtyper):
     # Common types
     yield ('RPyString', STR)
     LIST_OF_STR = find_list_of_str(rtyper)
@@ -95,7 +95,7 @@
     yield ('RPyMODF_RESULT', ll_math2.MODF_RESULT)
     yield ('RPySTAT_RESULT', STAT_RESULT)
 
-def predeclare_utility_functions(db, rtyper, optimize=True):
+def predeclare_utility_functions(db, rtyper):
     # Common utility functions
     def RPyString_New(length=lltype.Signed):
         return lltype.malloc(STR, length)
@@ -131,7 +131,7 @@
                 yield (fname, graph)
 
 
-def get_extfunc_helper_ptrs(db, rtyper, optimize=True):
+def get_extfunc_helper_ptrs(db, rtyper):
 
     def annotate(func, args):
         fptr = rtyper.annotate_helper(func, args)
@@ -141,7 +141,7 @@
     for func, args, symb in db.translator._implicitly_called_by_externals:
         yield annotate(func, args)
 
-def predeclare_extfunc_helpers(db, rtyper, optimize=True):
+def predeclare_extfunc_helpers(db, rtyper):
     def decl(func):
         return (func.__name__, db.helper2ptr[func])
 
@@ -149,7 +149,7 @@
         yield decl(func)
         yield ('LL_NEED_' + symb, 1)
 
-def predeclare_extfuncs(db, rtyper, optimize=True):
+def predeclare_extfuncs(db, rtyper):
     modules = {}
     def module_name(c_name):
         frags = c_name[3:].split('_')
@@ -168,7 +168,7 @@
         funcptr = funcobj._as_ptr()
         yield c_name, funcptr
 
-def predeclare_exception_data(db, rtyper, optimize=True):
+def predeclare_exception_data(db, rtyper):
     # Exception-related types and constants
     exceptiondata = rtyper.getexceptiondata()
     exctransformer = db.exctransformer
@@ -182,6 +182,7 @@
     if not db.standalone:
         yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.fn_pyexcclass2exc)
 
+    yield ('_RPyExceptionOccurred',    exctransformer._rpyexc_occured_ptr.value)
     yield ('RPyExceptionOccurred',     exctransformer.rpyexc_occured_ptr.value)
     yield ('RPyFetchExceptionType',    exctransformer.rpyexc_fetch_type_ptr.value)
     yield ('RPyFetchExceptionValue',   exctransformer.rpyexc_fetch_value_ptr.value)
@@ -199,25 +200,25 @@
         yield ('RPyExc_%s' % name, exc_llvalue)
 
 
-def predeclare_all(db, rtyper, optimize=True):
+def predeclare_all(db, rtyper):
     for fn in [predeclare_common_types,
                predeclare_utility_functions,
                predeclare_exception_data,
                predeclare_extfunc_helpers,
                predeclare_extfuncs,
                ]:
-        for t in fn(db, rtyper, optimize):
+        for t in fn(db, rtyper):
             yield t
 
 
-def get_all(db, rtyper, optimize=True):
+def get_all(db, rtyper):
     for fn in [predeclare_common_types,
                predeclare_utility_functions,
                predeclare_exception_data,
                get_extfunc_helper_ptrs,
                predeclare_extfuncs,
                ]:
-        for t in fn(db, rtyper, optimize):
+        for t in fn(db, rtyper):
             yield t[1]
 
 # ____________________________________________________________

Modified: pypy/dist/pypy/translator/llvm/buildllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/buildllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/buildllvm.py	Wed Jul 19 18:10:41 2006
@@ -96,7 +96,7 @@
         llc_params = llvm_version() > 1.7 and '-enable-x86-fastcc' or ''
         if llc_params and exe_name and sys.platform != 'darwin':
             llc_params += ' -relocation-model=static'   #XXX while llvm jumptables not with PIC
-        cmds.append("llc %s %s %s.bc -f -o %s.s" % (llc_params, genllvm.db.exceptionpolicy.llc_options(), b, b))
+        cmds.append("llc %s %s.bc -f -o %s.s" % (llc_params, b, b))
         cmds.append("as %s.s -o %s.o" % (b, b))
 
         if exe_name:
@@ -104,7 +104,7 @@
             cmds.append(cmd)
         object_files.append("%s.o" % b)
     else:
-        cmds.append("llc %s %s.bc -march=c -f -o %s.c" % (genllvm.db.exceptionpolicy.llc_options(), b, b))
+        cmds.append("llc %s.bc -march=c -f -o %s.c" % (b, b))
         if exe_name:
             cmd = "gcc %s.c -c -O3 -pipe" % b
             if profile:

Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Wed Jul 19 18:10:41 2006
@@ -403,10 +403,11 @@
         return self.types[key]
         
     def repr(self, type_, value):
-        try:
-            return self.reprs[type_](type_, value)
-        except KeyError:
-            raise Exception, "unsupported primitive type %r, value %r" % (type_, value)
+        #XXX TMP
+        #try:
+        return self.reprs[type_](type_, value)
+        #except KeyError:
+        #    raise Exception, "unsupported primitive type %r, value %r" % (type_, value)
         
     def repr_default(self, type_, value):
         return str(value)

Modified: pypy/dist/pypy/translator/llvm/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/exception.py	Wed Jul 19 18:10:41 2006
@@ -1,402 +1,20 @@
-from pypy.objspace.flow.model import Variable, c_last_exception
 
-from pypy.translator.llvm.codewriter import DEFAULT_CCONV
-from pypy.translator.llvm.backendopt.exception import create_exception_handling
-from pypy.translator.llvm.module.excsupport import invokeunwind_code, none_code, \
-                                                   explicit_code, exctransform_code
-from pypy.translator.c.exceptiontransform import ExceptionTransformer
-from pypy import conftest
+def _noresult(returntype):
+    r = returntype.strip()
+    if r == 'void':
+        return 'void'
+    elif r == 'bool':
+        return 'bool false'
+    elif r in 'float double'.split():
+        return r + ' 0.0'
+    elif r in 'ubyte sbyte ushort short uint int ulong long'.split():
+        return r + ' 0'
+    return r + ' null'
+
+def llvm_implcode(entrynode):
+    from pypy.translator.llvm.codewriter import DEFAULT_CCONV as cconv
+    from pypy.translator.llvm.module.excsupport import exctransform_code
+    returntype, entrypointname = entrynode.getdecl().split('%', 1)
+    noresult = _noresult(returntype)
+    return exctransform_code % locals()
 
-
-def repr_if_variable(db, arg):
-    if isinstance(arg, Variable):
-        return db.repr_arg(arg)
-
-
-class ExceptionPolicy:
-    def __init__(self, db):
-        self.db = db
-        raise Exception, 'ExceptionPolicy should not be used directly'
-
-    def transform(self, translator, graph=None):
-        return
-
-    def llvm_declcode(self):
-        return ''
-
-    def llvm_implcode(self, entrynode):
-        return ''
-
-    def llc_options(self):
-    	import sys
-    	if sys.platform == 'linux2' and sys.maxint == 2**63-1:
-            s = '-enable-ia64-dag-isel'
-	else:
-            s = ''
-        #can be used with LLVM debug build...
-        #s += ' -view-legalize-dags -view-isel-dags -view-sched-dags'
-        return s
-    
-    def update_phi_data(self, funcnode, entrylinks, block, blocknames):
-        """ Exceptions handling code introduces intermediate blocks for
-        exception handling cases, hence we modify our input phi data
-        accordingly. """
-        for ii, link in enumerate(entrylinks):
-            if (link.prevblock.exitswitch == c_last_exception and
-                link.prevblock.exits[0].target != block):
-                blocknames[ii] += '_exception_found_branchto_'
-                blocknames[ii] += funcnode.block_to_name[block]
-
-    def _noresult(self, returntype):
-        r = returntype.strip()
-        if r == 'void':
-            return 'void'
-        elif r == 'bool':
-            return 'bool false'
-        elif r in 'float double'.split():
-            return r + ' 0.0'
-        elif r in 'ubyte sbyte ushort short uint int ulong long'.split():
-            return r + ' 0'
-        return r + ' null'
-
-    def _noresult2(self, returntype):
-        r = returntype.strip()
-        if r == 'void':
-            return 'void'
-        elif r == 'bool':
-            return 'false'
-        elif r in 'float double'.split():
-            return '0.0'
-        elif r in 'ubyte sbyte ushort short uint int ulong long'.split():
-            return '0'
-        return 'null'
-
-    def _nonoderesult(self, node):
-        returntype, name, dummy = node.getdecl_parts()
-        noresult = self._noresult(returntype)
-        return noresult
-
-    def new(db, exceptionpolicy=None):  #factory
-        exceptionpolicy = exceptionpolicy or 'transform' #was: explicit/transform
-        if exceptionpolicy == 'invokeunwind':
-            exceptionpolicy = InvokeUnwindExceptionPolicy(db)
-        elif exceptionpolicy == 'explicit':
-            exceptionpolicy = ExplicitExceptionPolicy(db)
-        elif exceptionpolicy == 'transform':
-            exceptionpolicy = TransformExceptionPolicy(db)
-        elif exceptionpolicy == 'none':
-            exceptionpolicy = NoneExceptionPolicy(db)
-        else:
-            raise Exception, 'unknown exceptionpolicy: ' + str(exceptionpolicy)
-        return exceptionpolicy
-    new = staticmethod(new)
-
-
-class NoneExceptionPolicy(ExceptionPolicy):
-    """  XXX untested """
-
-    def __init__(self, db):
-        self.db = db
-
-    def llvm_implcode(self, entrynode):
-        returntype, entrypointname = entrynode.getdecl().split('%', 1)
-        noresult = self._noresult(returntype)
-        cconv = DEFAULT_CCONV
-        return none_code % locals()
-
-    
-class TransformExceptionPolicy(ExceptionPolicy):
-    def __init__(self, db):
-        self.db = db
-        translator = db.translator
-        if translator is None or translator.rtyper is None:
-            self.exctransformer = None
-        else:
-            self.exctransformer = ExceptionTransformer(translator)
-
-    def llvm_implcode(self, entrynode):
-        returntype, entrypointname = entrynode.getdecl().split('%', 1)
-        noresult = self._noresult(returntype)
-        cconv = DEFAULT_CCONV
-        return exctransform_code % locals()
-
-    def transform(self, translator, graph=None):
-        if self.exctransformer:
-            n_need_exc_matching_blocks, n_gen_exc_checks = \
-                self.exctransformer.create_exception_handling(graph)
-            if n_need_exc_matching_blocks or n_gen_exc_checks:
-                if conftest.option.view:
-                    graph.show()
-                    #self.db.translator.view()
-
-    
-class InvokeUnwindExceptionPolicy(ExceptionPolicy):
-    """ uses issubclass() and llvm invoke&unwind
-    XXX Untested for a while """
-    
-    def __init__(self):
-        pass
-
-    def llvm_implcode(self, entrynode):
-        returntype, entrypointname = entrynode.getdecl().split('%', 1)
-        noresult = self._noresult(returntype)
-        cconv = DEFAULT_CCONV
-        return invokeunwind_code % locals()
-
-    def invoke(self, codewriter, targetvar, tail_, cconv, returntype,
-               functionref, args, label, except_label):
-
-        labels = 'to label %%%s except label %%%s' % (label, except_label)
-        if returntype == 'void':
-            #XXX
-            codewriter._indent('%sinvoke %s void %s(%s) %s' % (tail_,
-                                                               cconv,
-                                                               functionref,
-                                                               args,
-                                                               labels))
-        else:
-            codewriter._indent('%s = %sinvoke %s %s %s(%s) %s' % (targetvar,
-                                                                  tail_,
-                                                                  cconv,
-                                                                  returntype,
-                                                                  functionref,
-                                                                  args,
-                                                                  labels))
-
-    def _is_raise_new_exception(self, db, graph, block):
-        from pypy.objspace.flow.model import mkentrymap
-        is_raise_new = False
-        entrylinks = mkentrymap(graph)[block]
-        entrylinks = [x for x in entrylinks if x.prevblock is not None]
-        inputargs = db.repr_arg_multi(block.inputargs)
-        for i, arg in enumerate(inputargs):
-            names = db.repr_arg_multi([link.args[i] for link in entrylinks])
-            # these tests-by-name are a bit yikes, but I don't see a better way
-            # right now
-            for name in names:  
-                if (not name.startswith('%last_exception_') and
-                    not name.startswith('%last_exc_value_')):
-                    is_raise_new = True
-        return is_raise_new
-
-    def write_exceptblock(self, funcnode, codewriter, block):
-        assert len(block.inputargs) == 2
-
-        db    = funcnode.db
-        graph = funcnode.graph
-
-        if self._is_raise_new_exception(db, graph, block):
-            funcnode.write_block_phi_nodes(codewriter, block)
-
-            inputargs     = db.repr_arg_multi(block.inputargs)
-            inputargtypes = db.repr_arg_type_multi(block.inputargs)
-
-            codewriter.store(inputargtypes[0], inputargs[0], '%last_exception_type')
-            codewriter.store(inputargtypes[1], inputargs[1], '%last_exception_value')
-        else:
-            codewriter.comment('reraise last exception')
-            # Reraising last_exception.
-            # Which is already stored in the global variables.
-            # So nothing needs to happen here!
-
-        codewriter.unwind()
-
-    def fetch_exceptions(self, codewriter, exc_found_labels,
-                         lltype_of_exception_type, lltype_of_exception_value):
-        for label, target, last_exc_type_var, last_exc_value_var in exc_found_labels:
-            codewriter.label(label)
-            if last_exc_type_var:    
-                codewriter.load(last_exc_type_var,
-                                lltype_of_exception_type,
-                                '%last_exception_type')
-            if last_exc_value_var:   
-                codewriter.load(last_exc_value_var,
-                                lltype_of_exception_value,
-                                '%last_exception_value')
-            codewriter.br_uncond(target)
-
-    def reraise(self, funcnode, codewriter):
-        codewriter.comment('reraise when exception is not caught')
-        codewriter.unwind()
-
-    def llc_options(self):
-    	import sys
-    	if sys.platform == 'linux2' and sys.maxint == 2**63-1:
-            s = ' -enable-ia64-dag-isel'
-	else:
-            s = ''
-        return '-enable-correct-eh-support' + s
-
-
-class ExplicitExceptionPolicy(ExceptionPolicy):
-    """ uses issubclass() and last_exception tests after each call """
-    def __init__(self, db):
-        self.db = db
-        self.invoke_count = 0
-
-    def llvm_implcode(self, entrynode):
-        returntype, entrypointname = entrynode.getdecl().split('%', 1)
-        noresult = self._noresult(returntype)
-        cconv = DEFAULT_CCONV
-        return explicit_code % locals()
- 
-    def transform(self, translator, graph=None):
-        if graph:
-            create_exception_handling(translator, graph)
-        else:
-            for graph in translator.flowgraphs.itervalues():
-                create_exception_handling(translator, graph)
-
-    def invoke(self, codewriter, targetvar, returntype, functionref,
-               argrefs, argtypes,
-               node, block): # XXX Unsure of these being passed in
-
-        assert functionref != '%keepalive'
-
-        # at least one label and one exception label
-        assert len(block.exits) >= 2
-        link = block.exits[0]
-        assert link.exitcase is None
-
-        none_label  = node.block_to_name[link.target]
-        block_label = node.block_to_name[block]
-        exc_label   = block_label + '_exception_handling'
-
-        tmp = '%%invoke.tmp.%d' % self.invoke_count
-        exc = '%%invoke.exc.%d' % self.invoke_count
-        self.invoke_count += 1
-
-        # XXX Hardcoded type...
-        type_ = "%RPYTHON_EXCEPTION_VTABLE*"
-
-        codewriter.call(targetvar, returntype, functionref, argtypes, argrefs)
-        codewriter.load(tmp, type_, "%last_exception_type")
-        codewriter.binaryop("seteq", exc, type_, tmp, "null")
-        codewriter.br(exc, exc_label, none_label)
-
-        # write exception handling blocks
-        
-        e = self.db.translator.rtyper.getexceptiondata()
-        ll_exception_match = self.db.repr_value(e.fn_exception_match._obj)        
-        lltype_of_exception_type = self.db.repr_type(e.lltype_of_exception_type)
-        lltype_of_exception_value = self.db.repr_type(e.lltype_of_exception_value)
-        
-        # start with the exception handling block
-        # * load the last exception type
-        # * check it with call to ll_exception_match()
-        # * branch to to correct block?
-        
-        codewriter.label(exc_label)
-
-        catch_all = False
-        found_blocks_info = []
-        last_exception_type = None
-
-        # XXX tmp - debugging info 
-
-        # block_label = "block28"
-        # exc_label = "block28_exception_handling"
-        # ll_exception_match = function for catching exception
-        # lltype_of_exception_type, lltype_of_exception_value = generic
-        # catch_all = ???
-        # found_blocks_info = list of found block data to write those blocks 
-        # last_exception_type = Load exception pointer once for handle and not found blocks
-
-        # link = iteration thru rest of links in block 
-        # etype = node for exception
-        # current_exception_type = repr for node etype
-        # target = label of the destination block 
-        # exc_found_label = label of intermediate exc found block
-        # last_exc_type_var = ????
-        # last_exc_value_var = ???
-        
-        for link in block.exits[1:]:
-            assert issubclass(link.exitcase, Exception)
-
-            # information for found blocks
-            target = node.block_to_name[link.target]
-            exc_found_label = block_label + '_exception_found_branchto_' + target
-            link_exc_type = repr_if_variable(self.db, link.last_exception)
-            link_exc_value = repr_if_variable(self.db, link.last_exc_value)
-            found_blocks_info.append((exc_found_label, target,
-                                      link_exc_type, link_exc_value))
-
-            # XXX fix database to handle this case
-            etype = self.db.obj2node[link.llexitcase._obj]
-            current_exception_type = etype.get_ref()
-            not_this_exception_label = block_label + '_not_exception_' + etype.ref[1:]
-
-            # catch specific exception (class) type
-
-            # load pointer only once
-            if not last_exception_type:
-                last_exception_type = self.db.repr_tmpvar()
-                codewriter.load(last_exception_type,
-                                lltype_of_exception_type,
-                                '%last_exception_type')
-                codewriter.newline()
-
-            ll_issubclass_cond = self.db.repr_tmpvar()
-
-            codewriter.call(ll_issubclass_cond,
-                            'bool',
-                            ll_exception_match,
-                            [lltype_of_exception_type, lltype_of_exception_type],
-                            [last_exception_type, current_exception_type])
-
-            codewriter.br(ll_issubclass_cond,
-                          not_this_exception_label,
-                          exc_found_label)
-
-            codewriter.label(not_this_exception_label)
-
-        if not catch_all:
-            self.reraise(node, codewriter)
-
-        self.fetch_exceptions(codewriter,
-                              found_blocks_info,
-                              lltype_of_exception_type,
-                              lltype_of_exception_value)
-
-    def write_exceptblock(self, funcnode, codewriter, block):
-        """ Raises an exception - called from FuncNode """
-        
-        assert len(block.inputargs) == 2
-
-        returntype, name, dummy = funcnode.getdecl_parts()
-
-        funcnode.write_block_phi_nodes(codewriter, block)
-
-        inputargs = funcnode.db.repr_arg_multi(block.inputargs)
-        inputargtypes = funcnode.db.repr_arg_type_multi(block.inputargs)
-
-        codewriter.store(inputargtypes[0], inputargs[0], '%last_exception_type')
-        codewriter.store(inputargtypes[1], inputargs[1], '%last_exception_value')
-        codewriter.ret(returntype, self._noresult2(returntype))
-
-    def fetch_exceptions(self, codewriter, exc_found_labels,
-                         lltype_of_exception_type, lltype_of_exception_value):
-
-        for (label, target,
-             last_exc_type_var, last_exc_value_var) in exc_found_labels:
-
-            codewriter.label(label)
-            if last_exc_type_var:    
-                codewriter.load(last_exc_type_var,
-                                lltype_of_exception_type,
-                                '%last_exception_type')
-            if last_exc_value_var:   
-                codewriter.load(last_exc_value_var,
-                                lltype_of_exception_value,
-                                '%last_exception_value')
-            codewriter.store(lltype_of_exception_type,
-                             'null',
-                             '%last_exception_type')
-            codewriter.store(lltype_of_exception_value,
-                             'null',
-                             '%last_exception_value')
-            codewriter.br_uncond(target)
-
-    def reraise(self, funcnode, codewriter):
-        returntype, name, dummy = funcnode.getdecl_parts()
-        codewriter.ret(returntype, self._noresult2(returntype))

Modified: pypy/dist/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs2ll.py	(original)
+++ pypy/dist/pypy/translator/llvm/externs2ll.py	Wed Jul 19 18:10:41 2006
@@ -102,16 +102,15 @@
     return decl, impl
 
 
-def setup_externs(db):
+def setup_externs(c_db, db):
     rtyper = db.translator.rtyper
-    from pypy.translator.llvm.extfunchelper import predeclare_all
+    from pypy.translator.c.extfunc import predeclare_all
 
     # hacks to make predeclare_all work
     # XXX Rationalise this
     db.standalone = True
     
-    #XXX extfuncs need init. to use optimize=True
-    decls = list(predeclare_all(db, rtyper, optimize=False))
+    decls = list(predeclare_all(c_db, rtyper))
 
     for c_name, obj in decls:
         if isinstance(obj, lltype.LowLevelType):

Modified: pypy/dist/pypy/translator/llvm/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcnode.py	Wed Jul 19 18:10:41 2006
@@ -58,23 +58,17 @@
                 for op in block.operations:
                     map(self.db.prepare_arg, op.args)
                     self.db.prepare_arg(op.result)
-                    if block.exitswitch != c_last_exception:
-                        continue
-                    for link in block.exits[1:]:
-                        type_ = lltype.typeOf(link.llexitcase)
-                        self.db.prepare_constant(type_, link.llexitcase)
+                    assert block.exitswitch != c_last_exception
                                             
         assert self.graph, "cannot traverse"
-        self.db.exceptionpolicy.transform(self.db.translator, self.graph)
         traverse(visit, self.graph)
 
     # ______________________________________________________________________
     # main entry points from genllvm 
 
     def post_setup_transform(self):
-        #self.db.exceptionpolicy.transform(self.db.translator, self.graph)
         remove_double_links(self.db.translator.annotator, self.graph)
-    
+        
     def writedecl(self, codewriter): 
         codewriter.declare(self.getdecl())
 
@@ -89,7 +83,7 @@
             self.block_to_name[block] = "block%s" % i
         for block in graph.iterblocks():
             codewriter.label(self.block_to_name[block])
-            for name in 'startblock returnblock exceptblock'.split():
+            for name in 'startblock returnblock'.split():
                 if block is getattr(graph, name):
                     getattr(self, 'write_' + name)(codewriter, block)
                     break
@@ -102,6 +96,7 @@
     
     # ______________________________________________________________________
     # writing helpers for entry points
+
     def getdecl_parts(self):
         startblock = self.graph.startblock
         returnblock = self.graph.returnblock
@@ -122,7 +117,6 @@
     # helpers for block writers
     
     def get_phi_data(self, block):
-        exceptionpolicy = self.db.exceptionpolicy
         data = []
         
         entrylinks = mkentrymap(self.graph)[block]
@@ -143,9 +137,6 @@
                           for link in entrylinks]
 
             assert len(names) == len(blocknames)
-
-            # some exception policies will add new blocks...
-            exceptionpolicy.update_phi_data(self, entrylinks, block, blocknames)
             data.append((arg, type_, names, blocknames))
 
         return data
@@ -155,11 +146,9 @@
             if type_ != "void":
                 codewriter.phi(arg, type_, names, blocknames)
 
-    def write_block_branches(self, codewriter, block):
-        if block.exitswitch == c_last_exception:
-            # special case - handled by exception policy
-            return
-        
+    def write_block_branches(self, codewriter, block):        
+        assert block.exitswitch != c_last_exception
+
         if len(block.exits) == 1:
             codewriter.br_uncond(self.block_to_name[block.exits[0].target])
             return
@@ -198,27 +187,23 @@
         # XXX We dont need multiple of these
         opwriter = OpWriter(self.db, codewriter)
 
-        invoke_op = None
-        block_ops = block.operations        
-        if block.exitswitch == c_last_exception:
-            invoke_op = block.operations[-1]
-            block_ops = block.operations[:-1]
+        assert block.exitswitch != c_last_exception
 
         # emit operations
-        for op in block_ops:
+        for op in block.operations:
             opwriter.write_operation(op)
 
-        if invoke_op:
-            # could raise an exception and should therefore have a function
-            # implementation that can be invoked by the llvm-code.
-            opwriter.write_invoke_op(invoke_op, self, block)
-
     # ______________________________________________________________________
     # actual block writers
     
     def write_startblock(self, codewriter, block):
         self.write_block_operations(codewriter, block)
-        self.write_block_branches(codewriter, block)
+        # a start block may return also
+        if block.exitswitch is None and len(block.exits) == 0:
+            inputarg, inputargtype = self.db.repr_argwithtype(block.inputargs[0])
+            codewriter.ret(inputargtype, inputarg)
+        else:
+            self.write_block_branches(codewriter, block)
 
     def write_block(self, codewriter, block):
         self.write_block_phi_nodes(codewriter, block)
@@ -226,12 +211,8 @@
         self.write_block_branches(codewriter, block)
 
     def write_returnblock(self, codewriter, block):
+        block.exitswitch is None and len(block.exits) == 0
         assert len(block.inputargs) == 1
         self.write_block_phi_nodes(codewriter, block)
         inputarg, inputargtype = self.db.repr_argwithtype(block.inputargs[0])
         codewriter.ret(inputargtype, inputarg)
-
-    def write_exceptblock(self, codewriter, block):
-        self.db.exceptionpolicy.write_exceptblock(self,
-                                                  codewriter,
-                                                  block)

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Wed Jul 19 18:10:41 2006
@@ -16,28 +16,23 @@
 from pypy.translator.llvm.node import LLVMNode
 from pypy.translator.llvm.externs2ll import setup_externs, generate_llfile
 from pypy.translator.llvm.gc import GcPolicy
-from pypy.translator.llvm.exception import ExceptionPolicy
 from pypy.translator.llvm.log import log
 from pypy import conftest
 from pypy.translator.llvm.buildllvm import llvm_is_on_path
 
 class GenLLVM(object):
-
-    # see open_file() below
+    # see create_codewriter() below
     function_count = {}
 
-    def __init__(self, translator, gcpolicy, exceptionpolicy, standalone,
-                 debug=False, logging=True):
+    def __init__(self, translator, gcpolicy, standalone,
+                 debug=False, logging=True, stackless=False):
     
         # reset counters
         LLVMNode.nodename_count = {}    
 
-        # create and set internals
-        self.db = Database(self, translator)
-        self.db.gcpolicy = GcPolicy.new(self.db, gcpolicy)
-        self.db.exceptionpolicy = ExceptionPolicy.new(self.db,
-                                                      exceptionpolicy)
+        self.gcpolicy = gcpolicy
 
+        self.stackless = stackless
         self.standalone = standalone
         self.translator = translator
 
@@ -74,18 +69,29 @@
             create c file for externs
             create ll file for c file
             create codewriter """
-        
+
+        # please dont ask!
+        from pypy.translator.c.genc import CStandaloneBuilder
+        from pypy.translator.c import gc
+        cbuild = CStandaloneBuilder(self.translator, func, gc.NoneGcPolicy)
+        cbuild.stackless = self.stackless
+        c_db = cbuild.generate_graphs_for_llinterp()
+
+        self.db = Database(self, self.translator)
+        self.db.gcpolicy = GcPolicy.new(self.db, self.gcpolicy)
+
         # get entry point
         entry_point = self.get_entry_point(func)
         self._checkpoint('get_entry_point')
         
         # set up all nodes
         self.db.setup_all()
+        
         self.entrynode = self.db.set_entrynode(entry_point)
         self._checkpoint('setup_all all nodes')
 
         # set up externs nodes
-        self.extern_decls = setup_externs(self.db)
+        self.extern_decls = setup_externs(c_db, self.db)
         self.translator.rtyper.specialize_more_blocks()
         self.db.setup_all()
         self._checkpoint('setup_all externs')
@@ -120,10 +126,6 @@
         self.write_extern_decls(codewriter)
         self._checkpoint('write externs type declarations')
 
-        # write exception declarations
-        ep = self.db.exceptionpolicy
-        codewriter.write_lines(ep.llvm_declcode())
-
         # write node type declarations
         for typ_decl in self.db.getnodes():
             typ_decl.writedatatypedecl(codewriter)
@@ -162,8 +164,8 @@
         self._checkpoint('write support implentations')
 
         # write exception implementaions
-        ep = self.db.exceptionpolicy
-        codewriter.write_lines(ep.llvm_implcode(self.entrynode))
+        from pypy.translator.llvm.exception import llvm_implcode
+        codewriter.write_lines(llvm_implcode(self.entrynode))
 
         # write all node implementations
         for typ_decl in self.db.getnodes():
@@ -292,15 +294,14 @@
 
 #______________________________________________________________________________
 
-
 def genllvm_compile(function,
                     annotation,
 
                     # genllvm options
                     gcpolicy=None,
                     standalone=False,
-                    exceptionpolicy=None,
-
+                    stackless=False,
+                    
                     # debug options
                     view=False,
                     debug=False,
@@ -334,17 +335,21 @@
                               propagate=False,
                               constfold=False)
 
-    # note: this is without policy transforms
+    # note: this is without stackless and policy transforms
     if view or conftest.option.view:
         translator.view()
 
+    if stackless:
+        from pypy.translator.transform import insert_ll_stackcheck
+        insert_ll_stackcheck(translator)
+
     # create genllvm
     gen = GenLLVM(translator,
                   gcpolicy,
-                  exceptionpolicy,
                   standalone,
                   debug=debug,
-                  logging=logging)
+                  logging=logging,
+                  stackless=stackless)
 
     filename = gen.gen_llvm_source(function)
     

Modified: pypy/dist/pypy/translator/llvm/module/excsupport.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/excsupport.py	(original)
+++ pypy/dist/pypy/translator/llvm/module/excsupport.py	Wed Jul 19 18:10:41 2006
@@ -1,54 +1,4 @@
 
-invokeunwind_code = '''
-;XXX this should probably store the last_exception_type
-ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
-    %%result = invoke %(cconv)s %(returntype)s%%%(entrypointname)s to label %%no_exception except label %%exception
-
-no_exception:
-    store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
-    ret %(returntype)s %%result
-
-exception:
-    ret %(noresult)s
-}
-
-ccc int %%__entrypoint__raised_LLVMException() {
-    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
-    %%result = cast %%RPYTHON_EXCEPTION_VTABLE* %%tmp to int
-    ret int %%result
-}
-
-internal fastcc void %%unwind() {
-    unwind
-}
-'''
-
-explicit_code = '''
-ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
-    store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
-    %%result = call %(cconv)s %(returntype)s%%%(entrypointname)s
-    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
-    %%exc    = seteq %%RPYTHON_EXCEPTION_VTABLE* %%tmp, null
-    br bool %%exc, label %%no_exception, label %%exception
-
-no_exception:
-    ret %(returntype)s %%result
-
-exception:
-    ret %(noresult)s
-}
-
-ccc int %%__entrypoint__raised_LLVMException() {
-    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
-    %%result = cast %%RPYTHON_EXCEPTION_VTABLE* %%tmp to int
-    ret int %%result
-}
-
-internal fastcc void %%unwind() {
-    ret void
-}
-'''
-
 exctransform_code = '''
 ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
     store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
@@ -75,18 +25,3 @@
     ret void
 }
 '''
-
-none_code = '''
-ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
-    %%result = call %(cconv)s %(returntype)s%%%(entrypointname)s
-    ret %(returntype)s %%result
-}
-
-ccc int %%__entrypoint__raised_LLVMException() {
-    ret int 0
-}
-
-internal fastcc void %%unwind() {
-    ret void
-}
-'''

Modified: pypy/dist/pypy/translator/llvm/module/genexterns.c
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/genexterns.c	(original)
+++ pypy/dist/pypy/translator/llvm/module/genexterns.c	Wed Jul 19 18:10:41 2006
@@ -1,7 +1,4 @@
 
-// overflows/zeros/values raising operations
-#include "raisingop.h"
-
 // append some genc files here manually from python
 #include "c/src/thread.h"
 #include "c/src/ll_os.h"
@@ -63,11 +60,11 @@
     if (errmsg) goto error;
     
     list = _RPyListOfString_New(argc);
-    if (RPyExceptionOccurred()) goto memory_out;
+    if (_RPyExceptionOccurred()) goto memory_out;
     for (i=0; i<argc; i++) {
       RPyString *s = RPyString_FromString(argv[i]);
 
-      if (RPyExceptionOccurred()) {
+      if (_RPyExceptionOccurred()) {
 	goto memory_out;
       }
 
@@ -76,7 +73,7 @@
 
     exitcode = __ENTRY_POINT__(list);
 
-    if (RPyExceptionOccurred()) {
+    if (_RPyExceptionOccurred()) {
       goto error; // XXX see genc
     }
     return exitcode;

Modified: pypy/dist/pypy/translator/llvm/module/protos.h
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/protos.h	(original)
+++ pypy/dist/pypy/translator/llvm/module/protos.h	Wed Jul 19 18:10:41 2006
@@ -3,7 +3,7 @@
 char *RPyString_AsString(RPyString*);
 long RPyString_Size(RPyString*);
 RPyString *RPyString_FromString(char *);
-int RPyExceptionOccurred(void);
+int _RPyExceptionOccurred(void);
 char* LLVM_RPython_StartupCode(void);
 
 #define RPyRaiseSimpleException(exctype, errormsg) raise##exctype(errormsg)

Modified: pypy/dist/pypy/translator/llvm/opwriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/opwriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/opwriter.py	Wed Jul 19 18:10:41 2006
@@ -126,12 +126,6 @@
             if not meth:
                 raise Exception, "operation %s not found" % op.opname
             meth(opr)            
-
-    def write_invoke_op(self, op, node, block):
-        opr = OpReprInvoke(op, self.db)
-        ep = self.db.exceptionpolicy
-        ep.invoke(self.codewriter, opr.retref, opr.rettype, opr.functionref,
-                  opr.argrefs, opr.argtypes, node, block)
     
     def _generic_pow(self, opr, onestr): 
 
@@ -505,15 +499,3 @@
             cast_addr = incr_addr
 
         self.codewriter.load(opr.retref, opr.rettype, cast_addr) 
-        
-    # ______________________________________________________________________
-    # 
-    # XXX exception specific - move to policy?
-
-    def last_exception_type_ptr(self, opr):
-        op = opr.op
-        e = self.db.translator.rtyper.getexceptiondata()
-        self.codewriter.load('%' + str(op.result),
-                             self.db.repr_type(e.lltype_of_exception_type),
-                             '%last_exception_type')
-

Added: pypy/dist/pypy/translator/llvm/test/test_stackless.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/llvm/test/test_stackless.py	Wed Jul 19 18:10:41 2006
@@ -0,0 +1,268 @@
+import os
+
+from pypy.annotation.listdef import s_list_of_strings
+from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big
+from pypy.rpython.rstack import yield_current_frame_to_caller
+
+from pypy.translator.llvm.genllvm import genllvm_compile
+import py
+py.test.skip("not there yet!")
+
+
+class StacklessTest(object):
+    def wrap_stackless_function(self, fn):
+        def entry_point(argv):
+            os.write(1, str(fn()) + "\n")
+            return 0
+
+        exe_path = genllvm_compile(entry_point, [s_list_of_strings], optimize=False,
+                                   exe_name="stacktest", standalone=True,
+                                   stackless=True, logging=False)
+        res = os.system(exe_path)
+        return int(res.strip())
+
+# ____________________________________________________________
+
+
+class TestStackless(StacklessTest):
+
+    def test_stack_depth(self):
+        def g1():
+            "just to check Void special cases around the code"
+        def g2(ignored):
+            g1()
+        def f(n):
+            g1()
+            if n > 0:
+                res = f(n-1) + 0 # make sure it is not a tail call
+            else:
+                res = stack_frames_depth()
+            g2(g1)
+            return res
+
+        def fn():
+            count0 = f(0)
+            count10 = f(10)
+            return count10 - count0
+
+        res = self.wrap_stackless_function(fn)
+        assert res == 10
+
+    def test_stack_withptr(self):
+        def f(n):
+            if n > 0:
+                res, dummy = f(n-1)
+            else:
+                res, dummy = stack_frames_depth(), 1
+            return res, dummy
+
+        def fn():
+            count0, _ = f(0)
+            count10, _ = f(10)
+            return count10 - count0
+
+        res = self.wrap_stackless_function(fn)
+        assert res == 10
+
+    def test_stackless_manytimes(self):
+        def f(n):
+            if n > 0:
+                stack_frames_depth()
+                res, dummy = f(n-1)
+            else:
+                res, dummy = stack_frames_depth(), 1
+            return res, dummy
+
+        def fn():
+            count0, _ = f(0)
+            count10, _ = f(100)
+            return count10 - count0
+
+        res = self.wrap_stackless_function(fn)
+        assert res == 100
+
+    def test_stackless_arguments(self):
+        def f(n, d, t):
+            if n > 0:
+                a, b, c = f(n-1, d, t)
+            else:
+                a, b, c = stack_frames_depth(), d, t
+            return a, b, c
+
+        def fn():
+            count0, d, t = f(0, 5.5, (1, 2))
+            count10, d, t = f(10, 5.5, (1, 2))
+            result = (count10 - count0) * 1000000
+            result += t[0]              * 10000
+            result += t[1]              * 100
+            result += int(d*10)
+            return result
+
+        res = self.wrap_stackless_function(fn)
+        assert res == 10010255
+
+
+    def test_stack_too_big(self):
+        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)
+        res = self.wrap_stackless_function(fn)
+        assert res > 500
+
+
+    def test_stack_unwind(self):
+        def f():
+            stack_unwind()
+            return 42
+
+        res = self.wrap_stackless_function(f)
+        assert res == 42
+
+    def test_auto_stack_unwind(self):
+        def f(n):
+            if n == 1:
+                return 1
+            return (n+f(n-1)) % 1291
+
+        def fn():
+            return f(10**6)
+        res = self.wrap_stackless_function(fn)
+        assert res == 704
+
+    def test_yield_frame(self):
+
+        def g(lst):
+            lst.append(2)
+            frametop_before_5 = yield_current_frame_to_caller()
+            lst.append(4)
+            frametop_before_7 = frametop_before_5.switch()
+            lst.append(6)
+            return frametop_before_7
+
+        def f():
+            lst = [1]
+            frametop_before_4 = g(lst)
+            lst.append(3)
+            frametop_before_6 = frametop_before_4.switch()
+            lst.append(5)
+            frametop_after_return = frametop_before_6.switch()
+            lst.append(7)
+            assert frametop_after_return is None
+            n = 0
+            for i in lst:
+                n = n*10 + i
+            return n
+
+        res = self.wrap_stackless_function(f)
+        assert res == 1234567
+
+    def test_foo(self):
+        def f():
+            c = g()
+            c.switch()
+            return 1
+        def g():
+            d = yield_current_frame_to_caller()
+            return d
+        res = self.wrap_stackless_function(f)
+        assert res == 1
+        
+
+    def test_yield_noswitch_frame(self):
+        # this time we make sure that function 'g' does not
+        # need to switch and even does not need to be stackless
+
+        def g(lst):
+            lst.append(2)
+            frametop_before_5 = yield_current_frame_to_caller()
+            lst.append(4)
+            return frametop_before_5
+
+        def f():
+            lst = [1]
+            frametop_before_4 = g(lst)
+            lst.append(3)
+            frametop_after_return = frametop_before_4.switch()
+            lst.append(5)
+            assert frametop_after_return is None
+            n = 0
+            for i in lst:
+                n = n*10 + i
+            return n
+
+        res = self.wrap_stackless_function(f)
+        assert res == 12345
+
+    # tested with refcounting too for sanity checking
+    def test_yield_frame_mem_pressure(self):
+
+        class A:
+            def __init__(self, value):
+                self.lst = [0] * 10000
+                self.lst[5000] = value
+
+            def inc(self, delta):
+                self.lst[5000] += delta
+                return self.lst[5000]
+
+        def g(lst):
+            a = A(1)
+            lst.append(a.inc(1))
+            frametop_before_5 = yield_current_frame_to_caller()
+            malloc_a_lot()
+            lst.append(a.inc(2))
+            frametop_before_7 = frametop_before_5.switch()
+            malloc_a_lot()
+            lst.append(a.inc(2))
+            return frametop_before_7
+
+        def f():
+            lst = [1]
+            frametop_before_4 = g(lst)
+            lst.append(3)
+            malloc_a_lot()
+            frametop_before_6 = frametop_before_4.switch()
+            lst.append(5)
+            malloc_a_lot()
+            frametop_after_return = frametop_before_6.switch()
+            lst.append(7)
+            assert frametop_after_return is None
+            n = 0
+            for i in lst:
+                n = n*10 + i
+            return n
+
+        res = self.wrap_stackless_function(f)
+        assert res == 1234567
+
+
+# ____________________________________________________________
+
+def malloc_a_lot():
+    i = 0
+    while i < 10:
+        i += 1
+        a = [1] * 10
+        j = 0
+        while j < 20:
+            j += 1
+            a.append(j)
+    from pypy.rpython.lltypesystem.lloperation import llop
+    from pypy.rpython.lltypesystem import lltype
+    llop.gc__collect(lltype.Void)



More information about the Pypy-commit mailing list