File: test_calling_convention.py

package info (click to toggle)
pypy 5.6.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 97,040 kB
  • ctags: 185,069
  • sloc: python: 1,147,862; ansic: 49,642; cpp: 5,245; asm: 5,169; makefile: 529; sh: 481; xml: 232; lisp: 45
file content (139 lines) | stat: -rw-r--r-- 5,777 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import py

from rpython.rtyper.annlowlevel import llhelper
from rpython.jit.metainterp.history import JitCellToken
from rpython.jit.backend.test.calling_convention_test import CallingConvTests, parse
from rpython.rtyper.lltypesystem import lltype
from rpython.jit.codewriter.effectinfo import EffectInfo

from rpython.jit.backend.arm.codebuilder import InstrBuilder
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm.test.support import skip_unless_run_slow_tests
from rpython.jit.backend.arm.test.test_runner import boxfloat, constfloat
from rpython.jit.metainterp.resoperation import rop, InputArgInt, InputArgFloat
from rpython.jit.metainterp.history import JitCellToken

skip_unless_run_slow_tests()

boxint = InputArgInt
boxfloat = InputArgFloat.fromfloat

class TestARMCallingConvention(CallingConvTests):
    # ../../test/calling_convention_test.py

    def make_function_returning_stack_pointer(self):
        mc = InstrBuilder()
        mc.MOV_rr(r.r0.value, r.sp.value)
        mc.MOV_rr(r.pc.value, r.lr.value)
        return mc.materialize(self.cpu, [])

    def get_alignment_requirements(self):
        return 8

    def test_call_argument_spilling(self):
        # bug when we have a value in r0, that is overwritten by an argument
        # and needed after the call, so that the register gets spilled after it
        # was overwritten with the argument to the call
        def func(a):
            return a + 16

        I = lltype.Signed
        FUNC = self.FuncType([I], I)
        FPTR = self.Ptr(FUNC)
        func_ptr = llhelper(FPTR, func)
        calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL)
        funcbox = self.get_funcbox(self.cpu, func_ptr)

        args = ', '.join(['i%d' % i for i in range(11)])
        ops = """
        [%s]
        i99 = call(ConstClass(func_ptr), 22, descr=calldescr)
        guard_true(i0) [%s, i99]
        finish()""" % (args, args)
        loop = parse(ops, namespace=locals())
        looptoken = JitCellToken()
        self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
        args = [x for x in range(11)]
        deadframe = self.cpu.execute_token(looptoken, *args)
        for x in range(11):
            assert self.cpu.get_int_value(deadframe, x) == x
        assert self.cpu.get_int_value(deadframe, 11) == 38


    def test_float_hf_call_mixed(self):
        if not self.cpu.supports_floats:
            py.test.skip("requires floats")
        cpu = self.cpu
        callargs = []
        def func(f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9):
            callargs.append(zip(range(12),
                        [f0, f1, f2, f3, f4, f5, f6, i0, f7, i1, f8, f9]))
            return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
        F = lltype.Float
        I = lltype.Signed
        FUNC = self.FuncType([F] * 7 + [I] + [F] + [I] + [F]* 2, F)
        FPTR = self.Ptr(FUNC)
        func_ptr = llhelper(FPTR, func)
        calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                    EffectInfo.MOST_GENERAL)
        funcbox = self.get_funcbox(cpu, func_ptr)
        args = ([boxfloat(.1) for i in range(7)] +
                [boxint(1), boxfloat(.2), boxint(2), boxfloat(.3),
                 boxfloat(.4)])
        res = self.execute_operation(rop.CALL_F,
                                     [funcbox] + args,
                                     'float', descr=calldescr)
        for i,j in enumerate(callargs[0]):
            box = args[i]
            if box.type == 'f':
                assert (i, args[i].getfloat()) == j
            else:
                assert (i, args[i].getint()) == j
        assert abs(res.getfloat() - 4.6) < 0.0001

    def test_float_hf_call_float(self):
        if not self.cpu.supports_floats:
            py.test.skip("requires floats")
        cpu = self.cpu
        callargs = []
        def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
            callargs.append(zip(range(10),
                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
            return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9
        F = lltype.Float
        FUNC = self.FuncType([F] * 10, F)
        FPTR = self.Ptr(FUNC)
        func_ptr = llhelper(FPTR, func)
        calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                    EffectInfo.MOST_GENERAL)
        funcbox = self.get_funcbox(cpu, func_ptr)
        args = ([boxfloat(.1) for i in range(10)])
        res = self.execute_operation(rop.CALL_F,
                                     [funcbox] + args,
                                     'float', descr=calldescr)
        for i,j in enumerate(callargs[0]):
            assert (i, 0.1) == j
        assert abs(res.getfloat() - 1) < 0.0001

    def test_float_hf_call_int(self):
        cpu = self.cpu
        callargs = []
        def func(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9):
            callargs.append(zip(range(10),
                        [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]))
            return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9

        I = lltype.Signed
        FUNC = self.FuncType([I] * 10, I)
        FPTR = self.Ptr(FUNC)
        func_ptr = llhelper(FPTR, func)
        calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                    EffectInfo.MOST_GENERAL)
        funcbox = self.get_funcbox(cpu, func_ptr)
        args = ([boxint(1) for i in range(10)])
        res = self.execute_operation(rop.CALL_I,
                                     [funcbox] + args,
                                     'int', descr=calldescr)
        for i,j in enumerate(callargs[0]):
            assert (i, 1) == j
        assert res.getint() == 10