[pypy-svn] r50427 - pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler

arigo at codespeak.net arigo at codespeak.net
Mon Jan 7 16:45:44 CET 2008


Author: arigo
Date: Mon Jan  7 16:45:43 2008
New Revision: 50427

Modified:
   pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py
Log:
Labels and jumps.


Modified: pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py
==============================================================================
--- pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py	(original)
+++ pypy/branch/simpler-pyassem/pypy/interpreter/astcompiler/pyassem.py	Mon Jan  7 16:45:43 2008
@@ -43,6 +43,8 @@
         self.varnames = list(argnames)
         # The bytecode we are building, as a list of characters
         self.co_code = []
+        # Pending label targets to fix: [(label, index-in-co_code-to-fix, abs)]
+        self.pending_label_fixes = []
 
     def setDocstring(self, doc):
         self.docstring = doc
@@ -168,9 +170,66 @@
     del name, obj, opname
 
     # ____________________________________________________________
+    # Labels and jumps
+
+    def newBlock(self):
+        """This really returns a new label, initially not pointing anywhere."""
+        return Label()
+
+    def nextBlock(self, label):
+        if label.position >= 0:
+            raise InternalCompilerError("Label target already seen")
+        label.position = len(self.co_code)
+
+    def emitop_block(self, opname, label):
+        absolute = opname in self.hasjabs
+        target = label.position
+        if target < 0:     # unknown yet
+            i = len(self.co_code)
+            self.pending_label_fixes.append((label, i, absolute))
+            target = 0xFFFF
+        else:
+            if not absolute:
+                # if the target was already seen, it must be backward,
+                # which is forbidden for these instructions
+                raise InternalCompilerError("%s cannot do a back jump" %
+                                            (opname,))
+        self.emitop_int(opname, target)
+
+    hasjabs = {}
+    for i in pythonopcode.hasjabs:
+        hasjabs[pythonopcode.opname[i]] = True
+    del i
+
+    # ____________________________________________________________
 
     def getCode(self):
+        self.computeStackDepth()
+        self.fixLabelTargets()
+        return self.newCodeObject()
+
+    def computeStackDepth(self):
         self.stacksize = 20  # XXX!
+
+    def fixLabelTargets(self):
+        for label, i, absolute in self.pending_label_fixes:
+            target = label.position
+            if target < 0:
+                raise InternalCompilerError("Label target not found")
+            if not absolute:
+                target = target - (i+3)   # relative jump
+                if target < 0:
+                    raise InternalCompilerError("Unexpected backward jump")
+            if target > 0xFFFF:
+                # CPython has the same limitation, for the same practical
+                # reason
+                msg = "function too large (bytecode would jump too far away)"
+                space = self.space
+                raise OperationError(space.w_SystemError, space.wrap(msg))
+            self.co_code[i+1] = chr(target & 0xFF)
+            self.co_code[i+2] = chr(target >> 8)
+
+    def newCodeObject(self):
         if (self.flags & CO_NEWLOCALS) == 0:
             nlocals = 0
         else:
@@ -202,3 +261,8 @@
             w_v = space.unpacktuple(w_key)[0]
             l_w[index] = w_v
         return l_w
+
+# ____________________________________________________________
+
+class Label(object):
+    position = -1



More information about the Pypy-commit mailing list