[pypy-svn] r50285 - pypy/branch/asmgcroot/pypy/translator/c

arigo at codespeak.net arigo at codespeak.net
Thu Jan 3 12:18:33 CET 2008


Author: arigo
Date: Thu Jan  3 12:18:32 2008
New Revision: 50285

Modified:
   pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
Log:
Parses gcbench.


Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py	Thu Jan  3 12:18:32 2008
@@ -16,9 +16,12 @@
 r_jmptable_end  = re.compile(r"\t.text\s*$")
 r_binaryinsn    = re.compile(r"\t[a-z]\w*\s+("+OPERAND+"),\s*("+OPERAND+")\s*$")
 LOCALVAR        = r"%eax|%edx|%ecx|%ebx|%esi|%edi|%ebp|\d*[(]%esp[)]"
-r_gcroot_marker = re.compile(r"\t/[*] GCROOT ("+LOCALVAR+") [*]/")
-r_localvar      = re.compile(LOCALVAR)
+LOCALVARFP      = LOCALVAR + r"|-?\d*[(]%ebp[)]"
+r_gcroot_marker = re.compile(r"\t/[*] GCROOT ("+LOCALVARFP+") [*]/")
+r_localvarnofp  = re.compile(LOCALVAR)
+r_localvarfp    = re.compile(LOCALVARFP)
 r_localvar_esp  = re.compile(r"(\d*)[(]%esp[)]")
+r_localvar_ebp  = re.compile(r"(-?\d*)[(]%ebp[)]")
 
 
 class GcRootTracker(object):
@@ -87,8 +90,7 @@
                 print >> sys.stderr, label, '\t', state
         if tracker.funcname == entrypoint:
             self.seen_main = True
-            xxx
-            table = [(label, (-1,)) for label, _ in table]
+            table = [(label, (-1,)+info[1:]) for label, info in table]
             # ^^^ we set the framesize of the entry point to -1 as a marker
             # (the code in asmgcroot.py actually takes any odd-valued number
             # as marker.)
@@ -105,6 +107,8 @@
         assert self.funcname == match.group(1)
         assert self.funcname == match.group(2)
         self.lines = lines
+        self.uses_frame_pointer = False
+        self.r_localvar = r_localvarnofp
 
     def computegcmaptable(self, verbose=0):
         self.findlabels()
@@ -143,7 +147,10 @@
                 else:
                     regindex = CALLEE_SAVE_REGISTERS.index(tag)
                     info[1 + regindex] = loc
-            assert None not in info
+            if None in info:
+                reg = CALLEE_SAVE_REGISTERS[info.index(None) - 1]
+                raise AssertionError("cannot track where register %s is saved"
+                                     % (reg,))
             table.append((insn.global_label, tuple(info)))
         return table
 
@@ -216,7 +223,6 @@
         return [insn for insn in self.insns if isinstance(insn, InsnCall)]
 
     def findframesize(self):
-        self.insns[0].framesize = 0
 
         def walker(insn, size_delta):
             check = deltas.setdefault(insn, size_delta)
@@ -258,6 +264,13 @@
                         localvar = ofs_from_esp - insn.framesize
                         assert localvar != 0    # that's the return address
                         setattr(insn, name, localvar)
+                    elif self.uses_frame_pointer:
+                        match = r_localvar_ebp.match(localvar)
+                        if match:
+                            ofs_from_ebp = int(match.group(1) or '0')
+                            localvar = ofs_from_ebp - 4
+                            assert localvar != 0    # that's the return address
+                            setattr(insn, name, localvar)
 
     def trackgcroots(self):
 
@@ -281,16 +294,16 @@
         pending = []
         seen = {}
         def schedule(insn, state):
-            key = insn, state
-            if key not in seen:
-                seen[key] = True
-                pending.append(key)
+            for previnsn in insn.previous_insns:
+                key = previnsn, state
+                if key not in seen:
+                    seen[key] = True
+                    pending.append(key)
         schedule(initial_insn, initial_state)
         while pending:
             insn, state = pending.pop()
             for prevstate in walker(insn, state):
-                for previnsn in insn.previous_insns:
-                    schedule(previnsn, prevstate)
+                schedule(insn, prevstate)
 
     def extend_calls_with_labels(self):
         # walk backwards, because inserting the global labels in self.lines
@@ -364,7 +377,7 @@
             count = match.group(1)
             assert count.startswith('$')
             return InsnStackAdjust(sign * int(count[1:]))
-        elif r_localvar.match(target):
+        elif self.r_localvar.match(target):
             return InsnSetLocal(target)
         else:
             return []
@@ -375,7 +388,7 @@
     def unary_insn(self, line):
         match = r_unaryinsn.match(line)
         target = match.group(1)
-        if r_localvar.match(target):
+        if self.r_localvar.match(target):
             return InsnSetLocal(target)
         else:
             return []
@@ -390,7 +403,7 @@
         if not match:
             raise UnrecognizedOperation(line)
         target = match.group(2)
-        if r_localvar.match(target):
+        if self.r_localvar.match(target):
             return InsnSetLocal(target)
         else:
             raise UnrecognizedOperation(line)
@@ -417,8 +430,8 @@
     def insns_for_copy(self, source, target):
         if source == '%esp' or target == '%esp':
             raise UnrecognizedOperation('%s -> %s' % (source, target))
-        elif r_localvar.match(target):
-            if r_localvar.match(source):
+        elif self.r_localvar.match(target):
+            if self.r_localvar.match(source):
                 return [InsnCopyLocal(source, target)]
             else:
                 return [InsnSetLocal(target)]
@@ -429,6 +442,10 @@
         match = r_binaryinsn.match(line)
         source = match.group(1)
         target = match.group(2)
+        if source == '%esp' and target == '%ebp':
+            return self._visit_prologue()
+        elif source == '%ebp' and target == '%esp':
+            return self._visit_epilogue()
         return self.insns_for_copy(source, target)
 
     def visit_pushl(self, line):
@@ -436,10 +453,27 @@
         source = match.group(1)
         return [InsnStackAdjust(-4)] + self.insns_for_copy(source, '(%esp)')
 
+    def _visit_pop(self, target):
+        return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)]
+
     def visit_popl(self, line):
         match = r_unaryinsn.match(line)
         target = match.group(1)
-        return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)]
+        return self._visit_pop(target)
+
+    def _visit_prologue(self):
+        # for the prologue of functions that use %ebp as frame pointer
+        self.uses_frame_pointer = True
+        self.r_localvar = r_localvarfp
+        return [InsnPrologue()]
+
+    def _visit_epilogue(self):
+        if not self.uses_frame_pointer:
+            raise UnrecognizedOperation('epilogue without prologue')
+        return [InsnEpilogue()]
+
+    def visit_leave(self, line):
+        return self._visit_epilogue() + self._visit_pop('%ebp')
 
     def visit_ret(self, line):
         return InsnRet()
@@ -463,7 +497,7 @@
             raise LeaveBasicBlock
         if r_unaryinsn_star.match(line):
             # that looks like an indirect tail-call.
-            return InsnStop()
+            return InsnRet()    # tail-calls are equivalent to RET for us
         try:
             self.conditional_jump(line)
         except KeyError:
@@ -471,6 +505,7 @@
             match = r_unaryinsn.match(line)
             target = match.group(1)
             assert not target.startswith('.')
+            return InsnRet()    # tail-calls are equivalent to RET for us
         return InsnStop()
 
     def register_jump_to(self, label):
@@ -552,6 +587,7 @@
         self.previous_insns = []   # all insns that jump (or fallthrough) here
 
 class InsnFunctionStart(Insn):
+    framesize = 0
     previous_insns = ()
     def __init__(self):
         self.arguments = {}
@@ -596,6 +632,7 @@
     pass
 
 class InsnRet(InsnStop):
+    framesize = 0
     def requestgcroots(self):
         return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS))
 
@@ -631,11 +668,25 @@
 
 class InsnGCROOT(Insn):
     _args_ = ['loc']
+    _locals_ = ['loc']
     def __init__(self, loc):
         self.loc = loc
     def requestgcroots(self):
         return {self.loc: None}
 
+class InsnPrologue(Insn):
+    def __setattr__(self, attr, value):
+        if attr == 'framesize':
+            assert value == 4, ("unrecognized function prologue - "
+                                "only supports push %ebp; movl %esp, %ebp")
+        Insn.__setattr__(self, attr, value)
+
+class InsnEpilogue(Insn):
+    framesize = 4
+    def requestgcroots(self):
+        return dict(zip(CALLEE_SAVE_REGISTERS_NOEBP,
+                        CALLEE_SAVE_REGISTERS_NOEBP))
+
 
 FUNCTIONS_NOT_RETURNING = {
     'abort': None,
@@ -643,7 +694,8 @@
     '__assert_fail': None,
     }
 
-CALLEE_SAVE_REGISTERS = ['%ebx', '%esi', '%edi', '%ebp']
+CALLEE_SAVE_REGISTERS_NOEBP = ['%ebx', '%esi', '%edi']
+CALLEE_SAVE_REGISTERS = CALLEE_SAVE_REGISTERS_NOEBP + ['%ebp']
 
 
 if __name__ == '__main__':


More information about the pypy-svn mailing list