[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