[pypy-svn] r24525 - in pypy/dist/pypy/translator/backendopt: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Mar 17 18:02:37 CET 2006


Author: cfbolz
Date: Fri Mar 17 18:02:25 2006
New Revision: 24525

Added:
   pypy/dist/pypy/translator/backendopt/canraise.py
   pypy/dist/pypy/translator/backendopt/test/test_canraise.py
Log:
functions to find out whether a function can raise


Added: pypy/dist/pypy/translator/backendopt/canraise.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/canraise.py	Fri Mar 17 18:02:25 2006
@@ -0,0 +1,55 @@
+from pypy.translator.simplify import get_graph
+from pypy.rpython.lltypesystem.lloperation import llop, LL_OPERATIONS
+from pypy.rpython.lltypesystem import lltype
+
+class ExceptionInfo(object):
+    def __init__(self, translator, can_raise, cannot_raise=None):
+        self.can_raise = can_raise
+        self.cannot_raise = cannot_raise
+        self.translator = translator
+
+    def exception_match(self, etype):
+        pass
+
+class RaiseAnalyzer(object):
+    def __init__(self, translator):
+        self.translator = translator
+        self.call_can_raise = {}
+
+    def can_raise(self, op, seen=None):
+        if op.opname == "direct_call":
+            graph = get_graph(op.args[0], self.translator)
+            print "graph", graph
+            if graph is None:
+                return True
+            return self.direct_call_can_raise(graph, seen)
+        elif op.opname == "indirect_call":
+            return self.indirect_call_can_raise(op.args[-1].value, seen)
+        else:
+            return bool(LL_OPERATIONS[op.opname].canraise)
+
+    def direct_call_can_raise(self, graph, seen=None):
+        if graph in self.call_can_raise:
+            return self.call_can_raise[graph]
+        if seen is None:
+            seen = {}
+        if graph in seen:
+            self.call_can_raise[graph] = False
+            return False
+        else:
+            seen[graph] = True
+        for block in graph.iterblocks():
+            if block is graph.exceptblock:
+                return True # the except block is reached
+            for op in block.operations:
+                if self.can_raise(op, seen):
+                    self.call_can_raise[graph] = True
+                    return True
+        self.call_can_raise[graph] = False
+        return False
+
+    def indirect_call_can_raise(self, graphs, seen=None):
+        for graph in graphs:
+            if self.direct_call_can_raise(graph, seen):
+                return True
+        return False

Added: pypy/dist/pypy/translator/backendopt/test/test_canraise.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/backendopt/test/test_canraise.py	Fri Mar 17 18:02:25 2006
@@ -0,0 +1,63 @@
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.backendopt.canraise import RaiseAnalyzer
+from pypy.conftest import option
+
+def translate(func, sig):
+    t = TranslationContext()
+    t.buildannotator().build_types(func, sig)
+    t.buildrtyper().specialize()
+    if option.view:
+        t.view()
+    return t, RaiseAnalyzer(t)
+
+def test_can_raise_simple():
+    def g(x):
+        return True
+
+    def f(x):
+        return g(x - 1)
+    t, ra = translate(f, [int])
+    fgraph = graphof(t, f)
+    result = ra.can_raise(fgraph.startblock.operations[0])
+    assert not result
+
+def test_can_raise_recursive():
+    def g(x):
+        return f(x)
+
+    def f(x):
+        if x:
+            return g(x - 1)
+        return 1
+    t, ra = translate(f, [int])
+    ggraph = graphof(t, g)
+    result = ra.can_raise(ggraph.startblock.operations[1])
+    assert not result # due to stack check every recursive function can raise
+
+def test_can_raise_exception():
+    def g():
+        raise ValueError
+    def f():
+        return g()
+    t, ra = translate(f, [])
+    fgraph = graphof(t, f)
+    result = ra.can_raise(fgraph.startblock.operations[0])
+    assert result
+
+def test_indirect_call():
+    def g1():
+        raise ValueError
+    def g2():
+        return 2
+    def f(x):
+        if x:
+            g = g1
+        else:
+            g = g2
+        return g()
+    def h(x):
+        return f(x)
+    t, ra = translate(h, [int])
+    hgraph = graphof(t, h)
+    result = ra.can_raise(hgraph.startblock.operations[0])
+    assert result



More information about the Pypy-commit mailing list