Author: Armin Rigo <ar...@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: _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit