/rpython/jit/backend/llsupport/test/test_descr.py
Python | 473 lines | 402 code | 41 blank | 30 comment | 15 complexity | 5982d7fe0d1a498e44aca593c81ce857 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
- from rpython.rtyper.lltypesystem import lltype, rffi, rstr
- from rpython.jit.backend.llsupport.descr import *
- from rpython.jit.backend.llsupport import symbolic
- from rpython.rlib.objectmodel import Symbolic
- from rpython.rtyper.annlowlevel import llhelper
- from rpython.jit.metainterp import history
- from rpython.jit.codewriter import longlong
- import sys, struct, py
- def test_get_size_descr():
- c0 = GcCache(False)
- c1 = GcCache(True)
- T = lltype.GcStruct('T')
- S = lltype.GcStruct('S', ('x', lltype.Char),
- ('y', lltype.Ptr(T)))
- descr_s = get_size_descr(c0, S)
- descr_t = get_size_descr(c0, T)
- assert descr_s.size == symbolic.get_size(S, False)
- assert descr_t.size == symbolic.get_size(T, False)
- assert descr_s.is_immutable() == False
- assert descr_t.is_immutable() == False
- assert descr_t.gc_fielddescrs == []
- assert len(descr_s.gc_fielddescrs) == 1
- assert descr_s == get_size_descr(c0, S)
- assert descr_s != get_size_descr(c1, S)
- #
- descr_s = get_size_descr(c1, S)
- assert isinstance(descr_s.size, Symbolic)
- assert descr_s.is_immutable() == False
- PARENT = lltype.Struct('P', ('x', lltype.Ptr(T)))
- STRUCT = lltype.GcStruct('S', ('parent', PARENT), ('y', lltype.Ptr(T)))
- descr_struct = get_size_descr(c0, STRUCT)
- assert len(descr_struct.gc_fielddescrs) == 2
- def test_get_size_descr_immut():
- S = lltype.GcStruct('S', hints={'immutable': True})
- T = lltype.GcStruct('T', ('parent', S),
- ('x', lltype.Char),
- hints={'immutable': True})
- U = lltype.GcStruct('U', ('parent', T),
- ('u', lltype.Ptr(T)),
- ('v', lltype.Signed),
- hints={'immutable': True})
- V = lltype.GcStruct('V', ('parent', U),
- ('miss1', lltype.Void),
- ('miss2', lltype.Void),
- hints={'immutable': True})
- for STRUCT in [S, T, U, V]:
- for translated in [False, True]:
- c0 = GcCache(translated)
- descr_s = get_size_descr(c0, STRUCT)
- assert descr_s.is_immutable() == True
- def test_get_field_descr():
- U = lltype.Struct('U')
- T = lltype.GcStruct('T')
- S = lltype.GcStruct('S', ('x', lltype.Char),
- ('y', lltype.Ptr(T)),
- ('z', lltype.Ptr(U)),
- ('f', lltype.Float),
- ('s', lltype.SingleFloat))
- #
- c0 = GcCache(False)
- c1 = GcCache(True)
- assert get_field_descr(c0, S, 'y') == get_field_descr(c0, S, 'y')
- assert get_field_descr(c0, S, 'y') != get_field_descr(c1, S, 'y')
- for tsc in [False, True]:
- c2 = GcCache(tsc)
- descr_x = get_field_descr(c2, S, 'x')
- descr_y = get_field_descr(c2, S, 'y')
- descr_z = get_field_descr(c2, S, 'z')
- descr_f = get_field_descr(c2, S, 'f')
- descr_s = get_field_descr(c2, S, 's')
- assert isinstance(descr_x, FieldDescr)
- assert descr_x.name == 'S.x'
- assert descr_y.name == 'S.y'
- assert descr_z.name == 'S.z'
- assert descr_f.name == 'S.f'
- assert descr_s.name == 'S.s'
- if not tsc:
- assert descr_x.offset < descr_y.offset < descr_z.offset
- assert descr_x.sort_key() < descr_y.sort_key() < descr_z.sort_key()
- assert descr_x.field_size == rffi.sizeof(lltype.Char)
- assert descr_y.field_size == rffi.sizeof(lltype.Ptr(T))
- assert descr_z.field_size == rffi.sizeof(lltype.Ptr(U))
- assert descr_f.field_size == rffi.sizeof(lltype.Float)
- assert descr_s.field_size == rffi.sizeof(lltype.SingleFloat)
- else:
- assert isinstance(descr_x.offset, Symbolic)
- assert isinstance(descr_y.offset, Symbolic)
- assert isinstance(descr_z.offset, Symbolic)
- assert isinstance(descr_f.offset, Symbolic)
- assert isinstance(descr_s.offset, Symbolic)
- assert isinstance(descr_x.field_size, Symbolic)
- assert isinstance(descr_y.field_size, Symbolic)
- assert isinstance(descr_z.field_size, Symbolic)
- assert isinstance(descr_f.field_size, Symbolic)
- assert isinstance(descr_s.field_size, Symbolic)
- assert descr_x.flag == FLAG_UNSIGNED
- assert descr_y.flag == FLAG_POINTER
- assert descr_z.flag == FLAG_UNSIGNED
- assert descr_f.flag == FLAG_FLOAT
- assert descr_s.flag == FLAG_UNSIGNED
- def test_get_field_descr_sign():
- for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR, False),
- (rffi.SHORT, True), (rffi.USHORT, False),
- (rffi.INT, True), (rffi.UINT, False),
- (rffi.LONG, True), (rffi.ULONG, False)]:
- S = lltype.GcStruct('S', ('x', RESTYPE))
- for tsc in [False, True]:
- c2 = GcCache(tsc)
- descr_x = get_field_descr(c2, S, 'x')
- assert descr_x.flag == {False: FLAG_UNSIGNED,
- True: FLAG_SIGNED }[signed]
- def test_get_field_descr_longlong():
- if sys.maxint > 2147483647:
- py.test.skip("long long: for 32-bit only")
- c0 = GcCache(False)
- S = lltype.GcStruct('S', ('y', lltype.UnsignedLongLong))
- descr = get_field_descr(c0, S, 'y')
- assert descr.flag == FLAG_FLOAT
- assert descr.field_size == 8
- def test_get_array_descr():
- U = lltype.Struct('U')
- T = lltype.GcStruct('T')
- A1 = lltype.GcArray(lltype.Char)
- A2 = lltype.GcArray(lltype.Ptr(T))
- A3 = lltype.GcArray(lltype.Ptr(U))
- A4 = lltype.GcArray(lltype.Float)
- A5 = lltype.GcArray(lltype.Struct('x', ('v', lltype.Signed),
- ('k', lltype.Signed)))
- A6 = lltype.GcArray(lltype.SingleFloat)
- #
- c0 = GcCache(False)
- descr1 = get_array_descr(c0, A1)
- descr2 = get_array_descr(c0, A2)
- descr3 = get_array_descr(c0, A3)
- descr4 = get_array_descr(c0, A4)
- descr5 = get_array_descr(c0, A5)
- descr6 = get_array_descr(c0, A6)
- assert isinstance(descr1, ArrayDescr)
- assert descr1 == get_array_descr(c0, lltype.GcArray(lltype.Char))
- assert descr1.flag == FLAG_UNSIGNED
- assert descr2.flag == FLAG_POINTER
- assert descr3.flag == FLAG_UNSIGNED
- assert descr4.flag == FLAG_FLOAT
- assert descr5.flag == FLAG_STRUCT
- assert descr6.flag == FLAG_UNSIGNED
- #
- def get_alignment(code):
- # Retrieve default alignment for the compiler/platform
- return struct.calcsize(lltype.SignedFmt + code) - struct.calcsize(code)
- assert descr1.basesize == get_alignment('c')
- assert descr2.basesize == get_alignment('p')
- assert descr3.basesize == get_alignment('p')
- assert descr4.basesize == get_alignment('d')
- assert descr5.basesize == get_alignment('f')
- assert descr1.lendescr.offset == 0
- assert descr2.lendescr.offset == 0
- assert descr3.lendescr.offset == 0
- assert descr4.lendescr.offset == 0
- assert descr5.lendescr.offset == 0
- assert descr1.itemsize == rffi.sizeof(lltype.Char)
- assert descr2.itemsize == rffi.sizeof(lltype.Ptr(T))
- assert descr3.itemsize == rffi.sizeof(lltype.Ptr(U))
- assert descr4.itemsize == rffi.sizeof(lltype.Float)
- assert descr5.itemsize == rffi.sizeof(lltype.Signed) * 2
- assert descr6.itemsize == rffi.sizeof(lltype.SingleFloat)
- #
- CA = rffi.CArray(lltype.Signed)
- descr = get_array_descr(c0, CA)
- assert descr.flag == FLAG_SIGNED
- assert descr.basesize == 0
- assert descr.lendescr is None
- CA = rffi.CArray(lltype.Ptr(lltype.GcStruct('S')))
- descr = get_array_descr(c0, CA)
- assert descr.flag == FLAG_POINTER
- assert descr.basesize == 0
- assert descr.lendescr is None
- CA = rffi.CArray(lltype.Ptr(lltype.Struct('S')))
- descr = get_array_descr(c0, CA)
- assert descr.flag == FLAG_UNSIGNED
- assert descr.basesize == 0
- assert descr.lendescr is None
- CA = rffi.CArray(lltype.Float)
- descr = get_array_descr(c0, CA)
- assert descr.flag == FLAG_FLOAT
- assert descr.basesize == 0
- assert descr.lendescr is None
- CA = rffi.CArray(rffi.FLOAT)
- descr = get_array_descr(c0, CA)
- assert descr.flag == FLAG_UNSIGNED
- assert descr.basesize == 0
- assert descr.itemsize == rffi.sizeof(lltype.SingleFloat)
- assert descr.lendescr is None
- def test_get_array_descr_sign():
- for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR, False),
- (rffi.SHORT, True), (rffi.USHORT, False),
- (rffi.INT, True), (rffi.UINT, False),
- (rffi.LONG, True), (rffi.ULONG, False)]:
- A = lltype.GcArray(RESTYPE)
- for tsc in [False, True]:
- c2 = GcCache(tsc)
- arraydescr = get_array_descr(c2, A)
- assert arraydescr.flag == {False: FLAG_UNSIGNED,
- True: FLAG_SIGNED }[signed]
- #
- RA = rffi.CArray(RESTYPE)
- for tsc in [False, True]:
- c2 = GcCache(tsc)
- arraydescr = get_array_descr(c2, RA)
- assert arraydescr.flag == {False: FLAG_UNSIGNED,
- True: FLAG_SIGNED }[signed]
- def test_get_array_descr_str():
- c0 = GcCache(False)
- descr1 = get_array_descr(c0, rstr.STR)
- assert descr1.itemsize == rffi.sizeof(lltype.Char)
- assert descr1.flag == FLAG_UNSIGNED
- def test_get_call_descr_not_translated():
- c0 = GcCache(False)
- descr1 = get_call_descr(c0, [lltype.Char, lltype.Signed], lltype.Char)
- assert descr1.get_result_size() == rffi.sizeof(lltype.Char)
- assert descr1.get_result_type() == history.INT
- assert descr1.arg_classes == "ii"
- #
- T = lltype.GcStruct('T')
- descr2 = get_call_descr(c0, [lltype.Ptr(T)], lltype.Ptr(T))
- assert descr2.get_result_size() == rffi.sizeof(lltype.Ptr(T))
- assert descr2.get_result_type() == history.REF
- assert descr2.arg_classes == "r"
- #
- U = lltype.GcStruct('U', ('x', lltype.Signed))
- assert descr2 == get_call_descr(c0, [lltype.Ptr(U)], lltype.Ptr(U))
- #
- V = lltype.Struct('V', ('x', lltype.Signed))
- assert (get_call_descr(c0, [], lltype.Ptr(V)).get_result_type() ==
- history.INT)
- #
- assert (get_call_descr(c0, [], lltype.Void).get_result_type() ==
- history.VOID)
- #
- descr4 = get_call_descr(c0, [lltype.Float, lltype.Float], lltype.Float)
- assert descr4.get_result_size() == rffi.sizeof(lltype.Float)
- assert descr4.get_result_type() == history.FLOAT
- assert descr4.arg_classes == "ff"
- #
- descr5 = get_call_descr(c0, [lltype.SingleFloat], lltype.SingleFloat)
- assert descr5.get_result_size() == rffi.sizeof(lltype.SingleFloat)
- assert descr5.get_result_type() == "S"
- assert descr5.arg_classes == "S"
- def test_get_call_descr_not_translated_longlong():
- if sys.maxint > 2147483647:
- py.test.skip("long long: for 32-bit only")
- c0 = GcCache(False)
- #
- descr5 = get_call_descr(c0, [lltype.SignedLongLong], lltype.Signed)
- assert descr5.get_result_size() == 4
- assert descr5.get_result_type() == history.INT
- assert descr5.arg_classes == "L"
- #
- descr6 = get_call_descr(c0, [lltype.Signed], lltype.SignedLongLong)
- assert descr6.get_result_size() == 8
- assert descr6.get_result_type() == "L"
- assert descr6.arg_classes == "i"
- def test_get_call_descr_translated():
- c1 = GcCache(True)
- T = lltype.GcStruct('T')
- U = lltype.GcStruct('U', ('x', lltype.Signed))
- descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U))
- assert isinstance(descr3.get_result_size(), Symbolic)
- assert descr3.get_result_type() == history.REF
- assert descr3.arg_classes == "r"
- #
- descr4 = get_call_descr(c1, [lltype.Float, lltype.Float], lltype.Float)
- assert isinstance(descr4.get_result_size(), Symbolic)
- assert descr4.get_result_type() == history.FLOAT
- assert descr4.arg_classes == "ff"
- #
- descr5 = get_call_descr(c1, [lltype.SingleFloat], lltype.SingleFloat)
- assert isinstance(descr5.get_result_size(), Symbolic)
- assert descr5.get_result_type() == "S"
- assert descr5.arg_classes == "S"
- def test_call_descr_extra_info():
- c1 = GcCache(True)
- T = lltype.GcStruct('T')
- U = lltype.GcStruct('U', ('x', lltype.Signed))
- descr1 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U), "hello")
- extrainfo = descr1.get_extra_info()
- assert extrainfo == "hello"
- descr2 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U), "hello")
- assert descr1 is descr2
- descr3 = get_call_descr(c1, [lltype.Ptr(T)], lltype.Ptr(U))
- extrainfo = descr3.get_extra_info()
- assert extrainfo is None
- def test_get_call_descr_sign():
- for RESTYPE, signed in [(rffi.SIGNEDCHAR, True), (rffi.UCHAR, False),
- (rffi.SHORT, True), (rffi.USHORT, False),
- (rffi.INT, True), (rffi.UINT, False),
- (rffi.LONG, True), (rffi.ULONG, False)]:
- for tsc in [False, True]:
- c2 = GcCache(tsc)
- descr1 = get_call_descr(c2, [], RESTYPE)
- assert descr1.is_result_signed() == signed
- def test_repr_of_descr():
- def repr_of_descr(descr):
- s = descr.repr_of_descr()
- assert ',' not in s # makes the life easier for pypy.tool.jitlogparser
- return s
- c0 = GcCache(False)
- T = lltype.GcStruct('T')
- S = lltype.GcStruct('S', ('x', lltype.Char),
- ('y', lltype.Ptr(T)),
- ('z', lltype.Ptr(T)))
- descr1 = get_size_descr(c0, S)
- s = symbolic.get_size(S, False)
- assert repr_of_descr(descr1) == '<SizeDescr %d>' % s
- #
- descr2 = get_field_descr(c0, S, 'y')
- o, _ = symbolic.get_field_token(S, 'y', False)
- assert repr_of_descr(descr2) == '<FieldP S.y %d>' % o
- #
- descr2i = get_field_descr(c0, S, 'x')
- o, _ = symbolic.get_field_token(S, 'x', False)
- assert repr_of_descr(descr2i) == '<FieldU S.x %d>' % o
- #
- descr3 = get_array_descr(c0, lltype.GcArray(lltype.Ptr(S)))
- o = symbolic.get_size(lltype.Ptr(S), False)
- assert repr_of_descr(descr3) == '<ArrayP %d>' % o
- #
- descr3i = get_array_descr(c0, lltype.GcArray(lltype.Char))
- assert repr_of_descr(descr3i) == '<ArrayU 1>'
- #
- descr4 = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Ptr(S))
- assert repr_of_descr(descr4) == '<Callr %d ir>' % o
- #
- descr4i = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Char)
- assert repr_of_descr(descr4i) == '<Calli 1 ir>'
- #
- descr4f = get_call_descr(c0, [lltype.Char, lltype.Ptr(S)], lltype.Float)
- assert repr_of_descr(descr4f) == '<Callf 8 ir>'
- #
- descr5f = get_call_descr(c0, [lltype.Char], lltype.SingleFloat)
- assert repr_of_descr(descr5f) == '<CallS 4 i>'
- def test_call_stubs_1():
- c0 = GcCache(False)
- ARGS = [lltype.Char, lltype.Signed]
- RES = lltype.Char
- descr1 = get_call_descr(c0, ARGS, RES)
- def f(a, b):
- return 'c'
- fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
- res = descr1.call_stub_i(rffi.cast(lltype.Signed, fnptr),
- [1, 2], None, None)
- assert res == ord('c')
- def test_call_stubs_2():
- c0 = GcCache(False)
- ARRAY = lltype.GcArray(lltype.Signed)
- ARGS = [lltype.Float, lltype.Ptr(ARRAY)]
- RES = lltype.Float
- def f2(a, b):
- return float(b[0]) + a
- fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f2)
- descr2 = get_call_descr(c0, ARGS, RES)
- a = lltype.malloc(ARRAY, 3)
- opaquea = lltype.cast_opaque_ptr(llmemory.GCREF, a)
- a[0] = 1
- res = descr2.call_stub_f(rffi.cast(lltype.Signed, fnptr),
- [], [opaquea], [longlong.getfloatstorage(3.5)])
- assert longlong.getrealfloat(res) == 4.5
- def test_call_stubs_single_float():
- from rpython.rlib.longlong2float import uint2singlefloat, singlefloat2uint
- from rpython.rlib.rarithmetic import r_singlefloat, intmask
- #
- c0 = GcCache(False)
- ARGS = [lltype.SingleFloat, lltype.SingleFloat, lltype.SingleFloat]
- RES = lltype.SingleFloat
- def f(a, b, c):
- a = float(a)
- b = float(b)
- c = float(c)
- x = a - (b / c)
- return r_singlefloat(x)
- fnptr = llhelper(lltype.Ptr(lltype.FuncType(ARGS, RES)), f)
- descr2 = get_call_descr(c0, ARGS, RES)
- a = intmask(singlefloat2uint(r_singlefloat(-10.0)))
- b = intmask(singlefloat2uint(r_singlefloat(3.0)))
- c = intmask(singlefloat2uint(r_singlefloat(2.0)))
- res = descr2.call_stub_i(rffi.cast(lltype.Signed, fnptr),
- [a, b, c], [], [])
- assert float(uint2singlefloat(rffi.r_uint(res))) == -11.5
- def test_field_arraylen_descr():
- c0 = GcCache(True)
- A1 = lltype.GcArray(lltype.Signed)
- fielddescr = get_field_arraylen_descr(c0, A1)
- assert isinstance(fielddescr, FieldDescr)
- ofs = fielddescr.offset
- assert repr(ofs) == '< ArrayLengthOffset <GcArray of Signed > >'
- #
- fielddescr = get_field_arraylen_descr(c0, rstr.STR)
- ofs = fielddescr.offset
- assert repr(ofs) == ("< <FieldOffset <GcStruct rpy_string { hash, chars }>"
- " 'chars'> + < ArrayLengthOffset"
- " <Array of Char > > >")
- # caching:
- assert fielddescr is get_field_arraylen_descr(c0, rstr.STR)
- def test_bytearray_descr():
- c0 = GcCache(False)
- descr = get_array_descr(c0, rstr.STR) # for bytearray
- # note that we get a basesize that has 1 extra byte for the final null char
- # (only for STR)
- assert descr.flag == FLAG_UNSIGNED
- assert descr.basesize == struct.calcsize("PP") + 1 # hash, length, extra
- assert descr.lendescr.offset == struct.calcsize("P") # hash
- assert not descr.is_array_of_pointers()
- def test_descr_integer_bounded():
- descr = FieldDescr('descr', 0, symbolic.SIZEOF_CHAR, FLAG_SIGNED)
- assert descr.is_integer_bounded()
- descr = FieldDescr('descr', 0, symbolic.WORD, FLAG_UNSIGNED)
- assert not descr.is_integer_bounded()
- descr = FieldDescr('descr', 0, symbolic.SIZEOF_FLOAT, FLAG_FLOAT)
- assert not descr.is_integer_bounded()
- def test_descr_get_integer_bounds():
- descr = FieldDescr('decr', 0, 1, FLAG_UNSIGNED)
- assert descr.get_integer_min() == 0
- assert descr.get_integer_max() == 255
- descr = FieldDescr('descr', 0, 1, FLAG_SIGNED)
- assert descr.get_integer_min() == -128
- assert descr.get_integer_max() == 127
- def test_size_descr_stack_overflow_bug():
- c0 = GcCache(False)
- S = lltype.GcForwardReference()
- P = lltype.Ptr(S)
- fields = [('x%d' % i, P) for i in range(1500)]
- S.become(lltype.GcStruct('S', *fields))
- get_size_descr(c0, S)