from rpython.translator.mu.ll2mu import * from rpython.translator.mu.ll2mu import _init_binop_map, varof import pytest def test_map_type_prim(): ll2mu = LL2MuMapper() assert ll2mu.map_type(lltype.Signed) == mutype.MU_INT64 assert ll2mu.map_type(lltype.Bool) == mutype.MU_INT8 assert ll2mu.map_type(rffi.INT) == mutype.MU_INT32 assert ll2mu.map_type(lltype.Void) == mutype.MU_VOID def test_map_type_addr(): ll2mu = LL2MuMapper() assert ll2mu.map_type(llmemory.Address) == mutype.MuUPtr(mutype.MU_INT8) def test_map_type_struct(): ll2mu = LL2MuMapper() LLT = lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed)) MuT = ll2mu.map_type(LLT) assert isinstance(MuT, mutype.MuStruct) assert len(MuT._names) == 3 # a GC hash field is added to the front assert MuT._names[0] == LL2MuMapper.GC_IDHASH_FIELD[0] assert MuT[0] == mutype.MU_INT64 assert MuT.x == mutype.MU_INT64 # cached assert ll2mu.map_type(LLT) is MuT # calling a second time return the same object def test_map_type_voidp(): from rpython.rtyper.lltypesystem.rffi import VOIDP ll2mu = LL2MuMapper() MuT = ll2mu.map_type(VOIDP) ll2mu.resolve_ptr_types() assert MuT == mutype.MuUPtr(mutype.MU_VOID) def test_map_type_opqptr(): ll2mu = LL2MuMapper() assert ll2mu.map_type(lltype.Ptr(lltype.RuntimeTypeInfo)) == mutype.MU_VOIDP assert ll2mu.map_type(llmemory.GCREF) == mutype.MU_VOIDR LL_META_CSTR = lltype.Ptr(lltype.GcOpaqueType("MuStr", hints={'mu_render_ptr_as': mutype.META_CSTR})) assert ll2mu.map_type(LL_META_CSTR) == mutype.META_CSTR def arrayofbytes(n): return mutype.MuArray(mutype.MU_INT8, n) # other opaque types # try translate the underlying opaque type first from rpython.rlib._rsocket_rffi import fd_set assert ll2mu.map_type(fd_set) == mutype.MuUPtr(arrayofbytes(fd_set.TO.hints['getsize']())) # on Linux the exact definition of DIR struct cannot be found, # thus there will be problem when querying the size of it # thus on Linux DIRP will be translated to uptr> from rpython.rlib import rposix DIRP = rposix.DIRP import sys if sys.platform.startswith('linux'): assert ll2mu.map_type(rposix.DIRP) == mutype.MuUPtr(mutype.MU_INT64) elif sys.platform == 'darwin': assert ll2mu.map_type(rposix.DIRP) == mutype.MuUPtr(arrayofbytes(DIRP.TO.hints['getsize']())) def test_map_type_hybrid(): ll2mu = LL2MuMapper() from rpython.rtyper.lltypesystem.rstr import STR MuT = ll2mu.map_type(STR) assert isinstance(MuT, mutype.MuHybrid) assert MuT._vartype == mutype._MuMemArray(mutype.MU_INT8) A = lltype.GcArray(lltype.Char) MuT = ll2mu.map_type(A) assert MuT._names == ('gc_idhash', 'length', 'items') assert MuT.items.OF == mutype.MU_INT8 A = lltype.GcArray(lltype.Char, hints={'nolength': True}) MuT = ll2mu.map_type(A) assert MuT._names == ('gc_idhash', 'items') A = lltype.GcArray(lltype.Char, hints={'mu_nohashfield': True}) MuT = ll2mu.map_type(A) assert MuT._names == ('length', 'items') def test_map_type_ptr(): ll2mu = LL2MuMapper() Point = lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed)) Node = lltype.GcForwardReference() PtrNode = lltype.Ptr(Node) Node.become(lltype.GcStruct("Node", ("payload", Point), ("next", PtrNode))) MuT = ll2mu.map_type(PtrNode) assert isinstance(MuT, mutype.MuRef) # GcStruct result in Ref assert isinstance(MuT.TO, mutype.MuForwardReference) # resolve later to break loop ll2mu.resolve_ptr_types() assert isinstance(MuT.TO, mutype.MuStruct) assert MuT.TO.next is MuT # loop preserved RawPoint = lltype.Struct('Point', ('x', lltype.Signed), ('y', lltype.Signed)) RawPtr = lltype.Ptr(RawPoint) assert isinstance(ll2mu.map_type(RawPtr), mutype.MuUPtr) # non-GCed Struct result in UPtr from rpython.rtyper.rclass import OBJECTPTR MuT = ll2mu.map_type(OBJECTPTR) ll2mu.resolve_ptr_types() assert isinstance(MuT.TO.typeptr.TO, mutype.MuStruct) def test_map_type_iptr(): ll2mu = LL2MuMapper() PointPtr = lltype.Ptr(lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed))) IPtr_Signed = lltype.InteriorPtr(PointPtr, lltype.Signed, ['x']) MuT = ll2mu.map_type(IPtr_Signed) ll2mu.resolve_ptr_types() assert MuT == mutype.MuIRef(ll2mu.map_type(lltype.Signed)) MuMetaCStr = lltype.InteriorPtr(lltype.GcOpaqueType('MuMetaCStr'), lltype.FixedSizeArray(lltype.Char, 1), []) MuT = ll2mu.map_type(MuMetaCStr) ll2mu.resolve_ptr_types() assert MuT == mutype.META_CSTR def test_map_type_funcptr(): from rpython.rtyper.rclass import OBJECTPTR ll2mu = LL2MuMapper() MuT = ll2mu.map_type(OBJECTPTR) ll2mu.resolve_ptr_types() FncRef = MuT.TO.typeptr.TO.instantiate Sig = FncRef.Sig assert Sig.ARGS == () assert Sig.RESULTS == (MuT, ) # ----------------------------------------------------------------------------- def test_map_value_prim(): ll2mu = LL2MuMapper() assert ll2mu.map_value(10) == mutype.mu_int64(10) assert ll2mu.map_value(rffi.INT._type(50)) == mutype.mu_int32(50) # XXX: what's the story for negative numbers in Mu? Check with Kunshan # for now, assume that negative number will be make unsigned assert ll2mu.map_value(rffi.INT._type(-50)) == mutype.mu_int32(4294967246) assert ll2mu.map_value(rarithmetic.r_singlefloat(1.5)) == mutype.mu_float(1.5) from rpython.rlib.objectmodel import malloc_zero_filled assert ll2mu.map_value(malloc_zero_filled) == mutype.mu_int64(1) assert ll2mu.map_value('c') == mutype.mu_int8(ord('c')) def test_map_value_adrofs(): from rpython.translator.mu.layout import mu_sizeOf, mu_offsetOf, mu_hybsizeOf ll2mu = LL2MuMapper() assert ll2mu.map_value(llmemory.sizeof(lltype.Char)) == mutype.mu_int64(1) S = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed)) MuS = ll2mu.map_type(S) assert ll2mu.map_value(llmemory.sizeof(S)) == mutype.mu_int64(mu_sizeOf(MuS)) assert ll2mu.map_value(llmemory.offsetof(S, 'y')) == mu_offsetOf(MuS, 'y') A = lltype.GcArray(lltype.Char) MuA = ll2mu.map_type(A) assert ll2mu.map_value(llmemory.itemoffsetof(A, 10)) == mu_hybsizeOf(MuA, 10) def test_map_value_stt(): ll2mu = LL2MuMapper() Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed)) pt = lltype.malloc(Point, zero=True)._obj mupt = ll2mu.map_value(pt) assert mupt.x == mupt.y == mutype.mu_int64(0) # test build parent structure Point3D = lltype.GcStruct("Point3D", ('super', Point), ('z', lltype.Signed)) Point4D = lltype.GcStruct("Point4D", ('super', Point3D), ('w', lltype.Signed)) pt4d = lltype.malloc(Point4D, zero=True)._obj pt3d = pt4d.super # map a structure from the middle should return the middle struct but with the whole thing mapped mupt3d = ll2mu.map_value(pt3d) assert mutype.mutypeOf(mupt3d) == ll2mu.map_type(Point3D) assert isinstance(mupt3d.super, mutype._mustruct) assert mutype.mutypeOf(mupt3d.super) == ll2mu.map_type(Point) mupt4d = mupt3d._parentstructure() assert isinstance(mupt4d, mutype._mustruct) assert mutype.mutypeOf(mupt4d) == ll2mu.map_type(Point4D) def test_map_value_varstt(): ll2mu = LL2MuMapper() from rpython.rtyper.lltypesystem.rstr import STR s = lltype.malloc(STR, 5, zero=True)._obj for i, c in enumerate("hello"): s.chars.setitem(i, c) s.hash = hash("hello") mus = ll2mu.map_value(s) assert mus.hash == s.hash assert mus.length == 5 for i in range(5): assert mus.chars[i] == ord(s.chars.getitem(i)) def test_map_value_array(): ll2mu = LL2MuMapper() Arr = lltype.GcArray(lltype.Char) arr = lltype.malloc(Arr, 5, zero=True)._obj for i, c in enumerate("hello"): arr.setitem(i, c) muarr = ll2mu.map_value(arr) assert muarr.length == 5 for i in range(5): assert muarr.items[i] == ord(arr.getitem(i)) def test_map_value_ptr(): ll2mu = LL2MuMapper() Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed)) PtrPoint = lltype.Ptr(Point) nullptr = lltype.nullptr(Point) assert ll2mu.map_value(nullptr)._is_null() p = lltype.malloc(Point, zero=True) r = ll2mu.map_value(p) ll2mu.resolve_ptr_values() assert isinstance(r, mutype._muref) assert mutype.mutypeOf(r._obj) == ll2mu.map_type(Point) # a more complicated test, object pointer from rpython.rtyper.rclass import OBJECT, OBJECT_VTABLE pobj = lltype.malloc(OBJECT, zero=True) pvtbl = lltype.malloc(OBJECT_VTABLE, flavor='raw', zero=True) pobj.typeptr = pvtbl pvtbl.hash = 12345 r = ll2mu.map_value(pobj) ll2mu.resolve_ptr_types() ll2mu.resolve_ptr_values() assert isinstance(r._obj.typeptr, mutype._muuptr) assert isinstance(r._obj.typeptr._obj, mutype._mustruct) assert r._obj.typeptr._obj.hash == pvtbl.hash lltype.free(pvtbl, flavor='raw') def test_map_value_iptr(): ll2mu = LL2MuMapper() Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed)) PtrPoint = lltype.Ptr(Point) p = lltype.malloc(Point, zero=True) p.x = 3 p.y = 5 # construct an interior pointer # NOTE: in lltype, it seems that we can only get an _interior_pointer from _ptr when # the _ptr is pointing to a 'gc' flavored struct, # and the field it points to is a 'raw' struct (see lltype._ptr._expose) # The construction here is a slight abuse here. ipx = lltype._interior_ptr(lltype.Signed, p._obj, ['x']) muv = ll2mu.map_value(ipx) ll2mu.resolve_ptr_types() ll2mu.resolve_ptr_values() assert isinstance(muv, mutype._muiref) assert muv._TYPE == mutype.MuIRef(mutype.MU_INT64) assert muv._load() == mutype.mu_int64(3) # this traces through the offsets def test_map_funcptr(): ll2mu = LL2MuMapper() def add1(n): return n + 1 from rpython.rtyper.test.test_llinterp import gengraph _, _, g = gengraph(add1, [int]) fncptr = lltype._func(lltype.FuncType([lltype.Signed], lltype.Signed), graph=g, _name=g.name)._as_ptr() fnr = ll2mu.map_value(fncptr) assert fnr.graph is g assert fnr._name == g.name from rpython.rlib.rposix import c_read llfncptr = c_read._ptr extfnp = ll2mu.map_value(llfncptr) assert isinstance(extfnp, mutype._muufuncptr) assert extfnp._name == llfncptr._obj._name assert extfnp.eci == llfncptr._obj.compilation_info # ----------------------------------------------------------------------------- # operation map test def test_mapped_const(): ll2mu = LL2MuMapper() c = ll2mu.mapped_const(True) assert c.value == mutype.mu_int8(1) assert c.concretetype == mutype.MU_INT8 d = ll2mu.mapped_const({}) assert d.value == {} assert d.concretetype == mutype.MU_VOID t = ll2mu.mapped_const(mutype.MU_INT8) assert t.value == mutype.MU_INT8 assert t.concretetype == mutype.MU_VOID e = ll2mu.mapped_const(10) assert e.value == mutype.mu_int64(10) assert e.concretetype == mutype.MU_INT64 f = ll2mu.mapped_const(10, rffi.UCHAR) assert f.value == mutype.mu_int8(10) assert f.concretetype == mutype.MU_INT8 def test_bool_not(): ll2mu = LL2MuMapper() res = varof(mutype.MU_INT8, 'res') llop = SpaceOperation('bool_not', [ll2mu.mapped_const(True)], res) muops = ll2mu.map_op(llop) assert len(muops) == 1 binop = muops[0] assert binop.opname == 'mu_binop' def test_int_abs(): ll2mu = LL2MuMapper() res = varof(mutype.MU_INT64, 'res') llop = SpaceOperation('int_abs', [ll2mu.mapped_const(-125)], res) muops = ll2mu.map_op(llop) assert len(muops) == 3 assert [op.opname for op in muops] == ['mu_binop', 'mu_cmpop', 'mu_select'] def test_int_between(): ll2mu = LL2MuMapper() res = varof(ll2mu.map_type(lltype.Bool), 'res') llop = SpaceOperation('int_between', [ll2mu.mapped_const(42), varof(mutype.MU_INT64, 'x'), ll2mu.mapped_const(100)], res) muops = ll2mu.map_op(llop) assert len(muops) == 5 assert [op.opname for op in muops] == ['mu_cmpop', 'mu_convop', 'mu_cmpop', 'mu_convop', 'mu_binop'] def test_int_mul_ovf(): ll2mu = LL2MuMapper() res = varof(mutype.MU_INT64, 'res') llop = SpaceOperation('int_mul_ovf', [varof(mutype.MU_INT64, 'a'), varof(mutype.MU_INT64, 'b')], res) muops = ll2mu.map_op(llop) assert len(muops) == 1 op = muops[0] assert op.opname == 'mu_binop' metainfo = op.args[-1].value assert metainfo['status'][0] == 'V' assert len(metainfo['status'][1]) == 1 assert isinstance(metainfo['status'][1][0], Variable) def test_cast_char_to_int(): ll2mu = LL2MuMapper() res = varof(mutype.MU_INT64, 'res') llop = SpaceOperation('cast_char_to_int', [varof(ll2mu.map_type(lltype.Char), 'c')], res) def test_binop_map(): llbinops = { 'char_lt', 'char_le', 'char_eq', 'char_ne', 'char_gt', 'char_ge', 'unichar_eq', 'unichar_ne', 'int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod', 'int_lt', 'int_le', 'int_eq', 'int_ne', 'int_gt', 'int_ge', 'int_and', 'int_or', 'int_lshift', 'int_rshift', 'int_xor', 'uint_add', 'uint_sub', 'uint_mul', 'uint_floordiv', 'uint_mod', 'uint_lt', 'uint_le', 'uint_eq', 'uint_ne', 'uint_gt', 'uint_ge', 'uint_and', 'uint_or', 'uint_lshift', 'uint_rshift', 'uint_xor', 'float_add', 'float_sub', 'float_mul', 'float_truediv', 'float_lt', 'float_le', 'float_eq', 'float_ne', 'float_gt', 'float_ge', 'llong_add', 'llong_sub', 'llong_mul', 'llong_floordiv', 'llong_mod', 'llong_lt', 'llong_le', 'llong_eq', 'llong_ne', 'llong_gt', 'llong_ge', 'llong_and', 'llong_or', 'llong_lshift', 'llong_rshift', 'llong_xor', 'ullong_add', 'ullong_sub', 'ullong_mul', 'ullong_floordiv', 'ullong_mod', 'ullong_lt', 'ullong_le', 'ullong_eq', 'ullong_ne', 'ullong_gt', 'ullong_ge', 'ullong_and', 'ullong_or', 'ullong_lshift', 'ullong_rshift', 'ullong_xor', 'lllong_add', 'lllong_sub', 'lllong_mul', 'lllong_floordiv', 'lllong_mod', 'lllong_lt', 'lllong_le', 'lllong_eq', 'lllong_ne', 'lllong_gt', 'lllong_ge', 'lllong_and', 'lllong_or', 'lllong_lshift', 'lllong_rshift', 'lllong_xor', } assert llbinops.difference(_init_binop_map().keys()) == set() # all covered def test_malloc_varsize(): ll2mu = LL2MuMapper() Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8)) rs = varof(mutype.MuRef(Hyb), "rs") llop = SpaceOperation('malloc_varsize', [ll2mu.mapped_const(Hyb), ll2mu.mapped_const({'flavor': 'gc'}), ll2mu.mapped_const(10)], rs) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_newhybrid', 'mu_getiref', 'mu_getfieldiref', 'mu_store'] assert muops[0].result is rs # the result is of the first instruction rather than the last def test_malloc_varsize_raw(): ll2mu = LL2MuMapper() Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8)) rs = varof(mutype.MuUPtr(Hyb), "rs") llop = SpaceOperation('malloc_varsize', [ll2mu.mapped_const(Hyb), ll2mu.mapped_const({'flavor': 'raw'}), ll2mu.mapped_const(10)], rs) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_binop', 'mu_binop', 'mu_ccall', 'mu_getfieldiref', 'mu_store'] def test_setarrayitem(): ll2mu = LL2MuMapper() Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8)) rs = varof(mutype.MuRef(Hyb), "rs") res = Variable('res') llop = SpaceOperation('setarrayitem', [rs, ll2mu.mapped_const(5), ll2mu.mapped_const('c')], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getvarpartiref', 'mu_shiftiref', 'mu_store'] def test_getinteriorarraysize(): ll2mu = LL2MuMapper() Str = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8)) ps = varof(mutype.MuUPtr(Str), 'rs') res = varof(mutype.MU_INT64, 'res') llop = SpaceOperation('getinteriorarraysize', [ps, Constant('chars', mutype.MU_VOID)], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getfieldiref', 'mu_load'] assert isinstance(muops[0].result.concretetype, mutype.MuUPtr) def test_setinteriorfield(): ll2mu = LL2MuMapper() Stt = mutype.MuStruct('point', ('x', mutype.MU_INT64), ('y', mutype.MU_INT64)) Hyb = mutype.MuHybrid('array', ('length', mutype.MU_INT64), ('points', Stt)) rh = varof(mutype.MuRef(Hyb)) res = varof(mutype.MU_VOID) llop = SpaceOperation('setinteriorfield', [rh, Constant('points', mutype.MU_VOID), Constant(5, mutype.MU_INT64), Constant('x', mutype.MU_VOID), Constant(42, mutype.MU_INT64)], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getvarpartiref', 'mu_shiftiref', 'mu_getfieldiref', 'mu_store'] def test_ptr_nonzero(): ll2mu = LL2MuMapper() Stt = mutype.MuStruct('point', ('x', mutype.MU_INT64), ('y', mutype.MU_INT64)) rs = varof(mutype.MuRef(Stt)) res = varof(mutype.MU_INT8) muops = ll2mu.map_op(SpaceOperation('ptr_nonzero', [rs], res)) assert [op.opname for op in muops] == ['mu_cmpop', 'mu_convop'] def test_raw_memcopy(): ll2mu = LL2MuMapper() VOIDP = ll2mu.map_type(rffi.VOIDP) src = varof(mutype.MU_INT64, 'src') dst = varof(mutype.MU_INT64, 'dst') sz = varof(mutype.MU_INT64, 'sz') llop = SpaceOperation('raw_memcopy', [src, dst, sz], varof(mutype.MU_VOID)) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_convop', 'mu_convop', 'mu_ccall'] ccall = muops[-1] assert ccall.args[0].value._name == 'memcpy' assert muops[0].args[-1] is src src_cast = muops[0].result assert muops[1].args[-1] is dst dst_cast = muops[1].result assert ccall.args[1] is dst_cast and ccall.args[2] is src_cast def test_gc_identityhash(): from rpython.translator.interactive import Translation def f(pobj): return lltype.identityhash(pobj) Point = lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed)) PointPtr = lltype.Ptr(Point) t = Translation(f, [PointPtr]) t.rtype() ll2mu = LL2MuMapper(t.context.rtyper) llop = t.context.graphs[0].startblock.operations[0] assert llop.opname == 'gc_identityhash' llop.args[0].concretetype = ll2mu.map_type(llop.args[0].concretetype) llop.result.concretetype = ll2mu.map_type(llop.result.concretetype) ll2mu.resolve_ptr_types() muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_comminst', 'mu_convop', 'mu_call', 'mu_comminst'] call = muops[2] callee_c = call.args[0] assert callee_c == ll2mu.ll_identityhash_c def test_force_cast(): Stt = mutype.MuStruct('point', ('x', mutype.MU_INT64), ('y', mutype.MU_INT64)) ll2mu = LL2MuMapper() muops = ll2mu.map_op(SpaceOperation('force_cast', [varof(mutype.MuRef(Stt))], varof(mutype.MU_INT64))) assert [op.opname for op in muops] == ['mu_comminst', 'mu_convop'] # pin, then PTRCAST with pytest.raises(AssertionError): ll2mu.map_op(SpaceOperation('force_cast', [varof(mutype.MU_INT64)], varof(mutype.MuRef(Stt)))) muops = ll2mu.map_op(SpaceOperation('force_cast', [varof(mutype.MU_INT64)], varof(mutype.MuUPtr(Stt)))) assert [op.opname for op in muops] == ['mu_convop'] # allowing ref -> uptr through pinning muops = ll2mu.map_op(SpaceOperation('force_cast', [varof(mutype.MuRef(Stt))], varof(mutype.MuUPtr(mutype.MU_INT64)))) assert [op.opname for op in muops] == ['mu_comminst', 'mu_convop'] muops = ll2mu.map_op(SpaceOperation('force_cast', [varof(mutype.MuRef(Stt))], varof(mutype.MuRef(mutype.MU_INT64)))) assert [op.opname for op in muops] == ['mu_convop'] # TODO: test more cases for force_cast? Maybe it will be easier with a graph interpreter def test_empty_struct(): EMPTY = lltype.Struct("pbc", hints={'immutable': True}) ptr_empty = lltype.malloc(EMPTY, immortal=True) ll2mu = LL2MuMapper() MuT = ll2mu.map_type(lltype.typeOf(ptr_empty)) ll2mu.resolve_ptr_types() assert MuT == mutype.MuUPtr(mutype.MU_VOID) muv = ll2mu.map_value(ptr_empty) ll2mu.resolve_ptr_values() assert muv._is_null() def test_malloc_array_of_void(): T = mutype.MuStruct('Void', ('length', mutype.MU_INT64)) llop = SpaceOperation('malloc_varsize', [Constant(T, mutype.MU_VOID), Constant({'flavor': 'raw'}, mutype.MU_VOID), Constant(mutype.mu_int64(0), mutype.MU_INT64)], varof(mutype.MuUPtr(T))) ll2mu = LL2MuMapper() muops = ll2mu.map_op(llop) assert len(muops) == 1 assert muops[0].opname == 'mu_ccall' assert muops[0].args[0].value._name == 'malloc' assert muops[0].args[1].value == 8 def test_shl_type_mismatch(): ll2mu = LL2MuMapper() muops = ll2mu.map_op(SpaceOperation('lllong_lshift', [varof(mutype.MU_INT128), varof(mutype.MU_INT64)], varof(mutype.MU_INT128))) # not raising assertion error from type checking assert [op.opname for op in muops] == ['mu_convop', 'mu_binop'] # cast first def test_weakref(): ll2mu = LL2MuMapper() MuT = ll2mu.map_type(llmemory.WeakRef) assert isinstance(MuT, mutype.MuStruct) assert MuT.wref == mutype.MU_WEAKREF_VOID LLT = lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed)) pt = lltype.malloc(LLT) pt.x = 3 pt.y = 5 llwref = llmemory._wref(pt) muwref = ll2mu.map_value(llwref) ll2mu.resolve_ptr_values() assert isinstance(muwref, mutype._mustruct) assert isinstance(mutype.mutypeOf(muwref.wref), mutype.MuWeakRef) assert not muwref.wref._is_null() assert mutype.mutypeOf(muwref.wref._obj()) == ll2mu.map_type(LLT) assert muwref.wref._obj().x == 3 assert muwref.wref._obj().y == 5 ll_wref_null = lltype.nullptr(llmemory.WeakRef) mu_wref_null = ll2mu.map_value(ll_wref_null) ll2mu.resolve_ptr_types() ll2mu.resolve_ptr_values() assert mu_wref_null._is_null() op_wref_c = SpaceOperation('weakref_create', [varof(ll2mu.map_type(lltype.Ptr(LLT)))], varof(ll2mu.map_type(llmemory.WeakRefPtr))) ll2mu.resolve_ptr_types() muops = ll2mu.map_op(op_wref_c) assert [op.opname for op in muops] == ['mu_new', 'mu_convop', 'mu_getiref', 'mu_getfieldiref', 'mu_store'] op_wref_d = SpaceOperation('weakref_deref', [varof(ll2mu.map_type(llmemory.WeakRefPtr))], varof(ll2mu.map_type(lltype.Ptr(LLT)))) muops = ll2mu.map_op(op_wref_d) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getfieldiref', 'mu_load', 'mu_convop'] def test_direct_arrayitems(): ll2mu = LL2MuMapper() arr = varof(ll2mu.map_type(lltype.Ptr(lltype.GcArray(lltype.Char))), 'array') res = varof(ll2mu.map_type(lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1))), 'ptr') ll2mu.resolve_ptr_types() llop = SpaceOperation('direct_arrayitems', [arr], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getvarpartiref'] def test_getsubstruct(): from rpython.rlib import clibffi ll2mu = LL2MuMapper() x = varof(ll2mu.map_type(clibffi.FFI_STRUCT_P)) res = varof(ll2mu.map_type(lltype.Ptr(clibffi.FFI_STRUCT_P.TO.members))) ll2mu.resolve_ptr_types() llop = SpaceOperation('getsubstruct', [x, Constant('members', mutype.MU_VOID)], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getfieldiref', 'mu_convop'] assert muops[0].args[-1].value == 'length' # the array has length def test_typedescr_str(): S = mutype.MuStruct('S', ('x', mutype.MU_INT64), ('y', mutype.MU_FLOAT), ('z', mutype.MuRef(mutype.MU_INT64))) assert get_typedescr_str(S) == '(lfr)' from rpython.rtyper.lltypesystem.rstr import STR H = ll2mu_type(STR) assert get_typedescr_str(H) == '{lll|b}' A = mutype.MuArray(S, 10) assert get_typedescr_str(A) == '[10|(lfr)]' def test_cast_pointer_pin(): ll2mu = LL2MuMapper() llop = SpaceOperation('cast_pointer', [varof(ll2mu.map_type(llmemory.GCREF))], varof(ll2mu.map_type(llmemory.Address))) ll2mu.resolve_ptr_types() muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_comminst', 'mu_convop'] def test_map_op_mu_meta_barebuf2cstriref(): ll2mu = LL2MuMapper() llop = SpaceOperation('mu_meta_barebuf2cstriref', [varof(mutype.MuRef(mutype.MuHybrid('dummy', ('varpart', mutype.MU_INT8))))], varof(mutype.META_CSTR)) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getvarpartiref'] def test_map_op_mu_meta_lst2carr(): ll2mu = LL2MuMapper() ELM_LLT = lltype.Signed ARR_LLT = lltype.GcArray(lltype.Signed) LIST_LLT = lltype.GcStruct('list', ('length', lltype.Signed), ('items', lltype.Ptr(ARR_LLT))) ELM_MuT = ll2mu.map_type(ELM_LLT) ARR_MuT = ll2mu.map_type(ARR_LLT) LIST_MuT = ll2mu.map_type(LIST_LLT) ll2mu.resolve_ptr_types() # array case res = varof(mutype.MuIRef(ELM_MuT)) llop = SpaceOperation('mu_meta_lst2carr', [varof(mutype.MuRef(ARR_MuT))], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getvarpartiref', 'mu_shiftiref'] assert muops[-1].result is res # struct list case llop = SpaceOperation('mu_meta_lst2carr', [varof(mutype.MuRef(LIST_MuT))], res) muops = ll2mu.map_op(llop) assert [op.opname for op in muops] == ['mu_getiref', 'mu_getfieldiref', 'mu_load', 'mu_getiref', 'mu_getvarpartiref', 'mu_shiftiref'] def test_map_op_cast_longdouble_to_double(): ll2mu = LL2MuMapper() SRC = ll2mu.map_type(rffi.LONGDOUBLE) DST = ll2mu.map_type(rffi.DOUBLE) llop = SpaceOperation('force_cast', [varof(SRC)], varof(DST)) muops = ll2mu.map_op(llop) assert len(muops) == 1 assert muops[0].opname == 'same_as' def test_map_op_force_cast_uint_to_int(): ll2mu = LL2MuMapper() SRC = ll2mu.map_type(lltype.Unsigned) DST = ll2mu.map_type(lltype.Signed) llop = SpaceOperation('force_cast', [varof(SRC)], varof(DST)) muops = ll2mu.map_op(llop) assert muops[0].opname == 'same_as'