[pypy-commit] pypy default: merge heads
arigo
noreply at buildbot.pypy.org
Wed Aug 31 21:39:18 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r46962:ed5fdaa7fbb7
Date: 2011-08-31 21:38 +0200
http://bitbucket.org/pypy/pypy/changeset/ed5fdaa7fbb7/
Log: merge heads
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -291,7 +291,7 @@
def get_call_conv(self):
from pypy.rlib.clibffi import get_call_conv
- return get_call_conv(self.ffi_flags)
+ return get_call_conv(self.ffi_flags, True)
def get_arg_types(self):
return self.arg_classes
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -34,6 +34,7 @@
from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
have_debug_prints)
from pypy.rlib import rgc
+from pypy.rlib.clibffi import FFI_DEFAULT_ABI
from pypy.jit.backend.x86.jump import remap_frame_layout
from pypy.jit.metainterp.history import ConstInt, BoxInt
from pypy.jit.codewriter.effectinfo import EffectInfo
@@ -1120,7 +1121,7 @@
return genop_cmp_guard_float
def _emit_call(self, force_index, x, arglocs, start=0, tmp=eax,
- argtypes=None):
+ argtypes=None, callconv=FFI_DEFAULT_ABI):
if IS_X86_64:
return self._emit_call_64(force_index, x, arglocs, start, argtypes)
@@ -1149,6 +1150,16 @@
# x is a location
self.mc.CALL(x)
self.mark_gc_roots(force_index)
+ #
+ if callconv != FFI_DEFAULT_ABI:
+ self._fix_stdcall(callconv, p)
+
+ def _fix_stdcall(self, callconv, p):
+ from pypy.rlib.clibffi import FFI_STDCALL
+ assert callconv == FFI_STDCALL
+ # it's a bit stupid, but we're just going to cancel the fact that
+ # the called function just added 'p' to ESP, by subtracting it again.
+ self.mc.SUB_ri(esp.value, p)
def _emit_call_64(self, force_index, x, arglocs, start, argtypes):
src_locs = []
@@ -2127,7 +2138,8 @@
tmp = eax
self._emit_call(force_index, x, arglocs, 3, tmp=tmp,
- argtypes=op.getdescr().get_arg_types())
+ argtypes=op.getdescr().get_arg_types(),
+ callconv=op.getdescr().get_call_conv())
if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
# a float or a long long return
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -527,6 +527,7 @@
NOP = insn('\x90')
RET = insn('\xC3')
+ RET16_i = insn('\xC2', immediate(1, 'h'))
PUSH_r = insn(rex_nw, register(1), '\x50')
PUSH_b = insn(rex_nw, '\xFF', orbyte(6<<3), stack_bp(1))
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -433,6 +433,91 @@
ops_offset[operations[2]] <=
ops_offset[None])
+ def test_calling_convention(self):
+ if WORD != 4:
+ py.test.skip("32-bit only test")
+ from pypy.jit.backend.x86.regloc import eax, edx
+ from pypy.jit.backend.x86 import codebuf
+ from pypy.jit.codewriter.effectinfo import EffectInfo
+ from pypy.rlib.libffi import types, clibffi
+ had_stdcall = hasattr(clibffi, 'FFI_STDCALL')
+ if not had_stdcall: # not running on Windows, but we can still test
+ clibffi.FFI_STDCALL = 12345
+ #
+ for ffi in [clibffi.FFI_DEFAULT_ABI, clibffi.FFI_STDCALL]:
+ cpu = self.cpu
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.MOV_rs(eax.value, 4) # argument 1
+ mc.MOV_rs(edx.value, 40) # argument 10
+ mc.SUB_rr(eax.value, edx.value) # return arg1 - arg10
+ if ffi == clibffi.FFI_DEFAULT_ABI:
+ mc.RET()
+ else:
+ mc.RET16_i(40)
+ rawstart = mc.materialize(cpu.asmmemmgr, [])
+ #
+ calldescr = cpu.calldescrof_dynamic([types.slong] * 10,
+ types.slong,
+ EffectInfo.MOST_GENERAL,
+ ffi_flags=-1)
+ calldescr.get_call_conv = lambda: ffi # <==== hack
+ funcbox = ConstInt(rawstart)
+ i1 = BoxInt()
+ i2 = BoxInt()
+ i3 = BoxInt()
+ i4 = BoxInt()
+ i5 = BoxInt()
+ i6 = BoxInt()
+ c = ConstInt(-1)
+ faildescr = BasicFailDescr(1)
+ # we must call it repeatedly: if the stack pointer gets increased
+ # by 40 bytes by the STDCALL call, and if we don't expect it,
+ # then we are going to get our stack emptied unexpectedly by
+ # several repeated calls
+ ops = [
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+ i3, descr=calldescr),
+ ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+ i4, descr=calldescr),
+ ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+ i5, descr=calldescr),
+ ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+ ResOperation(rop.CALL_RELEASE_GIL,
+ [funcbox, i1, c, c, c, c, c, c, c, c, i2],
+ i6, descr=calldescr),
+ ResOperation(rop.GUARD_NOT_FORCED, [], None, descr=faildescr),
+
+ ResOperation(rop.FINISH, [i3, i4, i5, i6], None,
+ descr=BasicFailDescr(0))
+ ]
+ ops[1].setfailargs([])
+ ops[3].setfailargs([])
+ ops[5].setfailargs([])
+ ops[7].setfailargs([])
+ looptoken = LoopToken()
+ self.cpu.compile_loop([i1, i2], ops, looptoken)
+
+ self.cpu.set_future_value_int(0, 123450)
+ self.cpu.set_future_value_int(1, 123408)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == 0
+ assert self.cpu.get_latest_value_int(0) == 42
+ assert self.cpu.get_latest_value_int(1) == 42
+ assert self.cpu.get_latest_value_int(2) == 42
+ assert self.cpu.get_latest_value_int(3) == 42
+
+ if not had_stdcall:
+ del clibffi.FFI_STDCALL
+
+
class TestDebuggingAssembler(object):
def setup_method(self, meth):
self.cpu = CPU(rtyper=None, stats=FakeStats())
diff --git a/pypy/rlib/clibffi.py b/pypy/rlib/clibffi.py
--- a/pypy/rlib/clibffi.py
+++ b/pypy/rlib/clibffi.py
@@ -408,11 +408,12 @@
FUNCFLAG_USE_ERRNO = 8
FUNCFLAG_USE_LASTERROR = 16
-def get_call_conv(flags):
+def get_call_conv(flags, from_jit):
if _WIN32 and (flags & FUNCFLAG_CDECL == 0):
return FFI_STDCALL
else:
return FFI_DEFAULT_ABI
+get_call_conv._annspecialcase_ = 'specialize:arg(1)' # hack :-/
class AbstractFuncPtr(object):
@@ -443,7 +444,7 @@
elif restype.c_size <= 8:
restype = ffi_type_sint64
- res = c_ffi_prep_cif(self.ll_cif, get_call_conv(flags),
+ res = c_ffi_prep_cif(self.ll_cif, get_call_conv(flags, False),
rffi.cast(rffi.UINT, argnum), restype,
self.ll_argtypes)
if not res == FFI_OK:
More information about the pypy-commit
mailing list