Exemplo n.º 1
0
def test_follow_jump_instructions_32():
    buf = lltype.malloc(rffi.CCHARP.TO, 80, flavor='raw')
    raw = rffi.cast(lltype.Signed, buf)
    mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
    mc.RET()
    mc.copy_to_raw_memory(raw)
    mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
    assert follow_jump(raw) == raw
    mc.JMP(imm(raw))
    mc.copy_to_raw_memory(raw + 20)
    assert buf[20] == '\xE9'    # JMP
    assert buf[21] == '\xE7'    #     -25
    assert buf[22] == '\xFF'
    assert buf[23] == '\xFF'
    assert buf[24] == '\xFF'
    mc = codebuf.MachineCodeBlockWrapper(); mc.WORD = 4; mc.relocations = []
    assert follow_jump(raw + 20) == raw
    mc.JMP(imm(raw))
    mc.copy_to_raw_memory(raw + 40)
    assert buf[40] == '\xE9'    # JMP
    assert buf[41] == '\xD3'    #     -45
    assert buf[42] == '\xFF'
    assert buf[43] == '\xFF'
    assert buf[44] == '\xFF'
    assert follow_jump(raw + 40) == raw
    lltype.free(buf, flavor='raw')
Exemplo n.º 2
0
def test_relocation():
    from rpython.rtyper.lltypesystem import lltype, rffi
    for target in [0x01020304, -0x05060708, 0x0102030405060708]:
        if target > sys.maxint:
            continue
        mc = codebuf.MachineCodeBlockWrapper()
        mc.CALL(ImmedLoc(target))
        length = mc.get_relative_pos()
        buf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw')
        rawstart = rffi.cast(lltype.Signed, buf)
        if IS_X86_32:
            assert length == 5
            assert mc.relocations == [5]
            expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
        elif IS_X86_64:
            assert mc.relocations is None
            if 0 <= target <= 0xffffffff:
                assert length == 9
                expected = (
                    "\x41\xBB\x04\x03\x02\x01"      # MOV %r11, target
                    "\x41\xFF\xD3")                 # CALL *%r11
            elif -0x80000000 <= target < 0:
                assert length == 10
                expected = (
                    "\x49\xC7\xC3\xF8\xF8\xF9\xFA"  # MOV %r11, target
                    "\x41\xFF\xD3")                 # CALL *%r11
            else:
                assert length == 13
                expected = (
                    "\x49\xBB\x08\x07\x06\x05\x04\x03\x02\x01" # MOV %r11, targ
                    "\x41\xFF\xD3")                 # CALL *%r11
        mc.copy_to_raw_memory(rawstart)
        assert ''.join([buf[i] for i in range(length)]) == expected
        lltype.free(buf, flavor='raw')
Exemplo n.º 3
0
    def invalidate_loop(self, looptoken):
        from rpython.jit.backend.x86 import codebuf

        for addr, tgt in looptoken.compiled_loop_token.invalidate_positions:
            mc = codebuf.MachineCodeBlockWrapper()
            mc.JMP_l(tgt)
            assert mc.get_relative_pos() == 5      # [JMP] [tgt 4 bytes]
            mc.copy_to_raw_memory(addr - 1)
        # positions invalidated
        looptoken.compiled_loop_token.invalidate_positions = []
Exemplo n.º 4
0
    def test_calling_convention(self, monkeypatch):
        if WORD != 4:
            py.test.skip("32-bit only test")
        from rpython.jit.backend.x86.regloc import eax, edx
        from rpython.jit.backend.x86 import codebuf, callbuilder
        from rpython.jit.codewriter.effectinfo import EffectInfo
        from rpython.rlib.libffi import types, clibffi
        had_stdcall = hasattr(clibffi, 'FFI_STDCALL')
        if not had_stdcall:  # not running on Windows, but we can still test
            monkeypatch.setattr(clibffi, 'FFI_STDCALL', 12345, raising=False)
            monkeypatch.setattr(callbuilder, 'stdcall_or_cdecl', True)
        else:
            assert callbuilder.stdcall_or_cdecl
        #
        for real_ffi, reported_ffi in [
            (clibffi.FFI_DEFAULT_ABI, clibffi.FFI_DEFAULT_ABI),
            (clibffi.FFI_STDCALL, clibffi.FFI_DEFAULT_ABI),
            (clibffi.FFI_STDCALL, 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 real_ffi == clibffi.FFI_DEFAULT_ABI:
                mc.RET()
            else:
                mc.RET16_i(40)
            rawstart = mc.materialize(cpu, [])
            #
            calldescr = cpu._calldescr_dynamic_for_tests([types.slong] * 10,
                                                         types.slong)
            calldescr.get_call_conv = lambda: reported_ffi  # <==== hack
            # ^^^ we patch get_call_conv() so that the test also makes sense
            #     on Linux, because clibffi.get_call_conv() would always
            #     return FFI_DEFAULT_ABI on non-Windows platforms.
            funcbox = ConstInt(rawstart)
            i1 = InputArgInt()
            i2 = InputArgInt()
            c = ConstInt(-1)
            faildescr = BasicFailDescr(1)
            cz = ConstInt(0)
            # 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_I,
                             [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
                             descr=calldescr),
                ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
                ResOperation(rop.CALL_RELEASE_GIL_I,
                             [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
                             descr=calldescr),
                ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
                ResOperation(rop.CALL_RELEASE_GIL_I,
                             [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
                             descr=calldescr),
                ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
                ResOperation(rop.CALL_RELEASE_GIL_I,
                             [cz, funcbox, i1, c, c, c, c, c, c, c, c, i2],
                             descr=calldescr),
                ResOperation(rop.GUARD_NOT_FORCED, [], descr=faildescr),
            ]
            i3 = ops[0]
            i4 = ops[2]
            i5 = ops[4]
            i6 = ops[6]

            ops += [
                ResOperation(rop.GUARD_FALSE, [i3], descr=BasicFailDescr(0)),
                ResOperation(rop.FINISH, [], descr=BasicFinalDescr(1))
            ]
            ops[-2].setfailargs([i3, i4, i5, i6])
            ops[1].setfailargs([])
            ops[3].setfailargs([])
            ops[5].setfailargs([])
            ops[7].setfailargs([])
            looptoken = JitCellToken()
            self.cpu.compile_loop([i1, i2], ops, looptoken)

            deadframe = self.cpu.execute_token(looptoken, 123450, 123408)
            fail = self.cpu.get_latest_descr(deadframe)
            assert fail.identifier == 0
            assert self.cpu.get_int_value(deadframe, 0) == 42
            assert self.cpu.get_int_value(deadframe, 1) == 42
            assert self.cpu.get_int_value(deadframe, 2) == 42
            assert self.cpu.get_int_value(deadframe, 3) == 42
Exemplo n.º 5
0
 def make_function_returning_stack_pointer(self):
     mc = codebuf.MachineCodeBlockWrapper()
     mc.MOV(eax, esp)
     mc.ADD_ri(eax.value, WORD)
     mc.RET()
     return mc.materialize(self.cpu, [])