[pypy-svn] r68348 - in pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc: . test/darwin

afa at codespeak.net afa at codespeak.net
Mon Oct 12 18:18:26 CEST 2009


Author: afa
Date: Mon Oct 12 18:18:24 2009
New Revision: 68348

Added:
   pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/test/darwin/track_switch0.s
Modified:
   pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/trackgcroot.py
Log:
Handle table-based switches on Darwin: where the address is computed in several instructions,
we walk backwards to find all possible inputs for the indirect jump, and use the first label we meet.


Added: pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/test/darwin/track_switch0.s
==============================================================================
--- (empty file)
+++ pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/test/darwin/track_switch0.s	Mon Oct 12 18:18:24 2009
@@ -0,0 +1,94 @@
+_pypy_g_MetaInterp_prepare_resume_from_failure:
+	subl	$28, %esp
+	movl	%ebx, 20(%esp)
+	movl	%esi, 24(%esp)
+	call	L2245
+"L00000000130$pb":
+L2245:
+	popl	%ebx
+	movl	32(%esp), %edx
+L2231:
+	movl	36(%esp), %eax
+	subl	$6, %eax
+	cmpl	$7, %eax
+	jbe	L2244
+L2243:
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	ret
+	.align 4,0x90
+L2244:
+	movl	L2237-"L00000000130$pb"(%ebx,%eax,4), %eax
+	addl	%ebx, %eax
+	jmp	*%eax
+	.align 2,0x90
+L2237:
+	.long	L2233-"L00000000130$pb"
+	.long	L2234-"L00000000130$pb"
+	.long	L2243-"L00000000130$pb"
+	.long	L2243-"L00000000130$pb"
+	.long	L2243-"L00000000130$pb"
+	.long	L2235-"L00000000130$pb"
+	.long	L2235-"L00000000130$pb"
+	.long	L2236-"L00000000130$pb"
+L2236:
+	movl	%edx, 32(%esp)
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	jmp	L_pypy_g_MetaInterp_raise_overflow_error$stub
+L2235:
+	movl	%edx, 32(%esp)
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	jmp	L_pypy_g_MetaInterp_handle_exception$stub
+L2234:
+	movl	16(%edx), %eax
+	movl	8(%eax), %edx
+	movl	4(%eax), %eax
+	movl	4(%edx,%eax,4), %eax
+	movl	%eax, 32(%esp)
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	jmp	L_pypy_g_MIFrame_dont_follow_jump$stub
+L2233:
+	movl	16(%edx), %eax
+	movl	8(%eax), %edx
+	movl	4(%eax), %eax
+	movl	4(%edx,%eax,4), %esi
+	movl	8(%esi), %ecx
+	movl	52(%esi), %eax
+	testl	%eax, %eax
+	js	L2238
+	movl	%eax, %edx
+L2240:
+	cmpb	$0, 12(%ecx,%edx)
+	je	L2241
+L2242:
+	movl	L_pypy_g_exceptions_AssertionError$non_lazy_ptr-"L00000000130$pb"(%ebx), %eax
+	movl	%eax, 36(%esp)
+	movl	L_pypy_g_exceptions_AssertionError_vtable$non_lazy_ptr-"L00000000130$pb"(%ebx), %eax
+	movl	%eax, 32(%esp)
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	jmp	L_pypy_g_RPyRaiseException$stub
+L2241:
+	incl	%eax
+	movl	%eax, 52(%esi)
+	movl	%esi, (%esp)
+	call	L_pypy_g_MIFrame_load_3byte$stub
+        ;; expected {28(%esp) | 20(%esp), 24(%esp), %edi, %ebp | }
+	movl	%eax, 52(%esi)
+	movl	20(%esp), %ebx
+	movl	24(%esp), %esi
+	addl	$28, %esp
+	ret
+L2238:
+	movl	%eax, %edx
+	addl	8(%ecx), %edx
+	jmp	L2240
+	.align 4,0x90

Modified: pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/trackgcroot.py	(original)
+++ pypy/branch/asmgcc-mingw32-2/pypy/translator/c/gcc/trackgcroot.py	Mon Oct 12 18:18:24 2009
@@ -37,6 +37,8 @@
 r_jmp_switch    = re.compile(r"\tjmp\t[*]"+LABEL+"[(]")
 r_jmptable_item = re.compile(r"\t.long\t"+LABEL+"\s*$")
 r_jmptable_end  = re.compile(r"\t.text|\t.section\s+.text")
+r_jmptable_item = re.compile(r"\t.long\t"+LABEL+"(-\"[A-Za-z0-9$]+\")?\s*$")
+r_jmptable_end  = re.compile(r"\t.text|\t.section\s+.text|"+LABEL)
 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[)]"
 LOCALVARFP      = LOCALVAR + r"|-?\d*[(]%ebp[)]"
@@ -462,6 +464,11 @@
 
     def fixlocalvars(self):
         def fixvar(localvar):
+            if localvar is None:
+                return None
+            elif isinstance(localvar, (list, tuple)):
+                return [fixvar(var) for var in localvar]
+
             match = r_localvar_esp.match(localvar)
             if match:
                 if localvar == '0(%esp)': # for pushl and popl, by
@@ -597,6 +604,7 @@
 
     def visit_addl(self, line, sign=+1):
         match = r_binaryinsn.match(line)
+        source = match.group(1)
         target = match.group(2)
         if target == '%esp':
             count = match.group(1)
@@ -605,7 +613,7 @@
                 return InsnCannotFollowEsp()
             return InsnStackAdjust(sign * int(count[1:]))
         elif self.r_localvar.match(target):
-            return InsnSetLocal(target)
+            return InsnSetLocal(target, [source, target])
         else:
             return []
 
@@ -624,6 +632,7 @@
         match = r_binaryinsn.match(line)
         if not match:
             raise UnrecognizedOperation(line)
+        source = match.group(1)
         target = match.group(2)
         if self.r_localvar.match(target):
             return InsnSetLocal(target)
@@ -694,7 +703,7 @@
             if self.r_localvar.match(source):
                 return [InsnCopyLocal(source, target)]
             else:
-                return [InsnSetLocal(target)]
+                return [InsnSetLocal(target, [source])]
         else:
             return []
 
@@ -742,31 +751,38 @@
         return InsnRet()
 
     def visit_jmp(self, line):
-        tablelabel = None
+        tablelabels = []
         match = r_jmp_switch.match(line)
         if match:
             # this is a jmp *Label(%index), used for table-based switches.
             # Assume that the table is just a list of lines looking like
             # .long LABEL or .long 0, ending in a .text or .section .text.hot.
-            tablelabel = match.group(1)
+            tablelabels.append(match.group(1))
         elif r_unaryinsn_star.match(line):
             # maybe a jmp similar to the above, but stored in a
             # registry:
             #     movl L9341(%eax), %eax
             #     jmp *%eax
             operand = r_unaryinsn_star.match(line).group(1)[1:]
-            prev_line = self.lines[self.currentlineno-1]
-            match = r_insn.match(prev_line)
-            binaryinsn = r_binaryinsn.match(prev_line)
-            if (match and binaryinsn and
-                match.group(1) == 'movl' and binaryinsn.group(2) == operand
-                and '(' in binaryinsn.group(1)):
-                tablelabel = binaryinsn.group(1).split('(')[0]
-                if tablelabel not in self.labels:
-                    # Probably an indirect tail-call.
-                    tablelabel = None
-        if tablelabel:
-            tablelin = self.labels[tablelabel].lineno + 1
+            def walker(insn, locs):
+                sources = []
+                for loc in locs:
+                    sources.extend(insn.all_sources_of(loc))
+                for source in sources:
+                    label_match = re.compile(LABEL).match(source)
+                    if label_match:
+                        tablelabels.append(label_match.group(0))
+                        return
+                yield tuple(sources)
+            insn = InsnStop()
+            insn.previous_insns = [self.insns[-1]]
+            self.walk_instructions_backwards(walker, insn, (operand,))
+
+            # Probably an indirect tail-call.
+            tablelabels = [label for label in tablelabels if label in self.labels]
+        assert len(tablelabels) <= 1
+        if tablelabels:
+            tablelin = self.labels[tablelabels[0]].lineno + 1
             while not r_jmptable_end.match(self.lines[tablelin]):
                 match = r_jmptable_item.match(self.lines[tablelin])
                 if not match:
@@ -920,6 +936,13 @@
     def source_of(self, localvar, tag):
         return localvar
 
+    def all_sources_of(self, localvar):
+        source = self.source_of(localvar, None)
+        if source is somenewvalue:
+            return []
+        else:
+            return [source]
+
 class Label(Insn):
     _args_ = ['label', 'lineno']
     def __init__(self, label, lineno):
@@ -952,14 +975,19 @@
         return self.arguments[localvar]
 
 class InsnSetLocal(Insn):
-    _args_ = ['target']
-    _locals_ = ['target']
-    def __init__(self, target):
+    _args_ = ['target', 'sources']
+    _locals_ = ['target', 'sources']
+    def __init__(self, target, sources=()):
         self.target = target
+        self.sources = sources
     def source_of(self, localvar, tag):
         if localvar == self.target:
             return somenewvalue
         return localvar
+    def all_sources_of(self, localvar):
+        if localvar == self.target:
+            return self.sources
+        return [localvar]
 
 class InsnCopyLocal(Insn):
     _args_ = ['source', 'target']



More information about the Pypy-commit mailing list