[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