[pypy-commit] pypy emit-call-x86: Move load_result() into callbuilder too.

arigo noreply at buildbot.pypy.org
Sun May 19 14:14:38 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: emit-call-x86
Changeset: r64324:7dbd98504eff
Date: 2013-05-19 14:09 +0200
http://bitbucket.org/pypy/pypy/changeset/7dbd98504eff/

Log:	Move load_result() into callbuilder too.

diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1003,8 +1003,8 @@
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         return bool(gcrootmap) and not gcrootmap.is_shadow_stack
 
-    def simple_call(self, fnaddr, arglocs):
-        cb = callbuilder.CallBuilder(self, imm(fnaddr), arglocs)
+    def simple_call(self, fnloc, arglocs):
+        cb = callbuilder.CallBuilder(self, fnloc, arglocs)
         cb.emit()
 
     def _reload_frame_if_necessary(self, mc, align_stack=False):
@@ -1814,65 +1814,25 @@
     def genop_call(self, op, arglocs, resloc):
         return self._genop_call(op, arglocs, resloc)
 
-    def _genop_call(self, op, arglocs, resloc, is_call_release_gil=False):
+    def _genop_call(self, op, arglocs, resloc):
         from rpython.jit.backend.llsupport.descr import CallDescr
 
-        sizeloc = arglocs[0]
-        assert isinstance(sizeloc, ImmedLoc)
-        size = sizeloc.value
-        signloc = arglocs[1]
-
-        cb = callbuilder.CallBuilder(self, arglocs[2], arglocs[3:])
+        cb = callbuilder.CallBuilder(self, arglocs[2], arglocs[3:], resloc)
 
         descr = op.getdescr()
         assert isinstance(descr, CallDescr)
+        cb.callconv = descr.get_call_conv()
         cb.argtypes = descr.get_arg_types()
-        cb.callconv = descr.get_call_conv()
-
-        if is_call_release_gil:
-            if self._is_asmgcc():
-                from rpython.memory.gctransform import asmgcroot
-                stack_max -= asmgcroot.JIT_USE_WORDS
-            XXXXXX
+        cb.restype  = descr.get_result_type()
+        sizeloc = arglocs[0]
+        assert isinstance(sizeloc, ImmedLoc)
+        cb.ressize = sizeloc.value
+        signloc = arglocs[1]
+        assert isinstance(signloc, ImmedLoc)
+        cb.ressign = signloc.value
 
         cb.emit()
 
-        if IS_X86_32 and isinstance(resloc, FrameLoc) and resloc.type == FLOAT:
-            # a float or a long long return
-            if descr.get_result_type() == 'L':
-                self.mc.MOV_br(resloc.value, eax.value)      # long long
-                self.mc.MOV_br(resloc.value + 4, edx.value)
-                # XXX should ideally not move the result on the stack,
-                #     but it's a mess to load eax/edx into a xmm register
-                #     and this way is simpler also because the result loc
-                #     can just be always a stack location
-            else:
-                self.mc.FSTPL_b(resloc.value)   # float return
-        elif descr.get_result_type() == 'S':
-            # singlefloat return
-            assert resloc is eax
-            if IS_X86_32:
-                # must convert ST(0) to a 32-bit singlefloat and load it into EAX
-                # mess mess mess
-                self.mc.SUB_ri(esp.value, 4)
-                self.mc.FSTPS_s(0)
-                self.mc.POP_r(eax.value)
-            elif IS_X86_64:
-                # must copy from the lower 32 bits of XMM0 into eax
-                self.mc.MOVD_rx(eax.value, xmm0.value)
-        elif size == WORD:
-            assert resloc is eax or resloc is xmm0    # a full word
-        elif size == 0:
-            pass    # void return
-        else:
-            # use the code in load_from_mem to do the zero- or sign-extension
-            assert resloc is eax
-            if size == 1:
-                srcloc = eax.lowest8bits()
-            else:
-                srcloc = eax
-            self.load_from_mem(eax, srcloc, sizeloc, signloc)
-
     def _store_force_index(self, guard_op):
         faildescr = guard_op.getdescr()
         ofs = self.cpu.get_ofs_of_frame_field('jf_force_descr')
@@ -1996,11 +1956,11 @@
         self.call_assembler(op, guard_op, argloc, vloc, result_loc, eax)
         self._emit_guard_not_forced(guard_token)
 
-    def _call_assembler_emit_call(self, addr, argloc, tmploc):
-        self._emit_call(addr, [argloc], 0, tmp=tmploc)
+    def _call_assembler_emit_call(self, addr, argloc, _):
+        self.simple_call(addr, [argloc])
 
     def _call_assembler_emit_helper_call(self, addr, arglocs, _):
-         self._emit_call(addr, arglocs, 0, tmp=self._second_tmp_reg)
+        self.simple_call(addr, arglocs)
 
     def _call_assembler_check_descr(self, value, tmploc):
         ofs = self.cpu.get_ofs_of_frame_field('jf_descr')
diff --git a/rpython/jit/backend/x86/callbuilder.py b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -6,7 +6,7 @@
 from rpython.jit.backend.x86.regloc import (eax, ecx, edx, ebx, esp, ebp, esi,
     xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, r8, r9, r10, r11, edi,
     r12, r13, r14, r15, X86_64_SCRATCH_REG, X86_64_XMM_SCRATCH_REG,
-    RegLoc, RawEspLoc)
+    RegLoc, RawEspLoc, FrameLoc)
 from rpython.jit.backend.x86.jump import remap_frame_layout
 
 
@@ -28,6 +28,9 @@
     # this can be set to guide more complex calls: gives the detailed
     # type of the arguments
     argtypes = None
+    restype = INT
+    ressize = WORD
+    ressign = False
 
     # this is the calling convention (can be FFI_STDCALL on Windows)
     callconv = FFI_DEFAULT_ABI
@@ -36,11 +39,12 @@
     is_call_release_gil = False
 
 
-    def __init__(self, assembler, fnloc, arglocs):
+    def __init__(self, assembler, fnloc, arglocs, resloc=eax):
         self.asm = assembler
         self.mc = assembler.mc
         self.fnloc = fnloc
         self.arglocs = arglocs
+        self.resloc = resloc
         self.current_esp = 0
 
     def emit(self):
@@ -49,6 +53,7 @@
         self.push_gcmap()
         self.emit_raw_call()
         self.pop_gcmap()
+        self.load_result()
         self.restore_esp()
 
     def emit_raw_call(self):
@@ -61,6 +66,22 @@
             self.mc.SUB_ri(esp.value, self.current_esp)
             self.current_esp = 0
 
+    def load_result(self):
+        """Overridden in CallBuilder32 and CallBuilder64"""
+        if self.ressize == 0:
+            return      # void result
+        # use the code in load_from_mem to do the zero- or sign-extension
+        if self.restype == FLOAT:
+            srcloc = xmm0
+        elif self.ressize == 1:
+            srcloc = eax.lowest8bits()
+        else:
+            srcloc = eax
+        if self.ressize >= WORD and self.resloc is srcloc:
+            return      # no need for any move
+        self.asm.load_from_mem(self.resloc, srcloc,
+                               imm(self.ressize), imm(self.ressign))
+
     def push_gcmap(self):
         # we push *now* the gcmap, describing the status of GC registers
         # after the rearrangements done just above, ignoring the return
@@ -127,6 +148,27 @@
         assert callconv == FFI_STDCALL
         return self.total_stack_used_by_arguments
 
+    def load_result(self):
+        resloc = self.resloc
+        if isinstance(resloc, FrameLoc) and resloc.type == FLOAT:
+            # a float or a long long return
+            if self.restype == 'L':
+                self.mc.MOV_br(resloc.value, eax.value)      # long long
+                self.mc.MOV_br(resloc.value + 4, edx.value)
+                # XXX should ideally not move the result on the stack,
+                #     but it's a mess to load eax/edx into a xmm register
+                #     and this way is simpler also because the result loc
+                #     can just be always a stack location
+            else:
+                self.mc.FSTPL_b(resloc.value)   # float return
+        elif self.restype == 'S':
+            # singlefloat return: must convert ST(0) to a 32-bit singlefloat
+            # and load it into self.resloc.  mess mess mess
+            self.mc.SUB_ri(esp.value, 4)
+            self.mc.FSTPS_s(0)
+            self.mc.POP(self.resloc)
+        else:
+            AbstractCallBuilder.load_result(self)
 
 
 class CallBuilder64(AbstractCallBuilder):
@@ -222,6 +264,16 @@
     def _fix_stdcall(self, callconv):
         assert 0     # should not occur on 64-bit
 
+    def load_result(self):
+        if self.restype == 'S':
+            # singlefloat return: use MOVD to load the target register
+            # with the lower 32 bits of XMM0
+            resloc = self.resloc
+            assert isinstance(resloc, RegLoc)
+            self.mc.MOVD_rx(resloc.value, xmm0.value)
+        else:
+            AbstractCallBuilder.load_result(self)
+
 
 if IS_X86_32:
     CallBuilder = CallBuilder32


More information about the pypy-commit mailing list