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
|