test_ll2mu.py 27.5 KB
Newer Older
1
from rpython.translator.mu.ll2mu import *
2
from rpython.translator.mu.ll2mu import _init_binop_map, varof
John Zhang's avatar
John Zhang committed
3
import pytest
4

5 6

def test_map_type_prim():
John Zhang's avatar
John Zhang committed
7 8 9
    ll2mu = LL2MuMapper()
    assert ll2mu.map_type(lltype.Signed) == mutype.MU_INT64
    assert ll2mu.map_type(lltype.Bool) == mutype.MU_INT8
10

John Zhang's avatar
John Zhang committed
11
    assert ll2mu.map_type(rffi.INT) == mutype.MU_INT32
12
    assert ll2mu.map_type(lltype.Void) == mutype.MU_VOID
13 14

def test_map_type_addr():
John Zhang's avatar
John Zhang committed
15
    ll2mu = LL2MuMapper()
16
    assert ll2mu.map_type(llmemory.Address) == mutype.MuUPtr(mutype.MU_INT8)
17 18

def test_map_type_struct():
John Zhang's avatar
John Zhang committed
19
    ll2mu = LL2MuMapper()
20
    LLT = lltype.GcStruct('Point', ('x', lltype.Signed), ('y', lltype.Signed))
John Zhang's avatar
John Zhang committed
21
    MuT = ll2mu.map_type(LLT)
22 23 24 25

    assert isinstance(MuT, mutype.MuStruct)
    assert len(MuT._names) == 3
    # a GC hash field is added to the front
John Zhang's avatar
John Zhang committed
26
    assert MuT._names[0] == LL2MuMapper.GC_IDHASH_FIELD[0]
27 28 29 30
    assert MuT[0] == mutype.MU_INT64
    assert MuT.x == mutype.MU_INT64

    # cached
John Zhang's avatar
John Zhang committed
31
    assert ll2mu.map_type(LLT) is MuT   # calling a second time return the same object
32

33 34 35 36 37 38 39
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)

40 41
def test_map_type_opqptr():
    ll2mu = LL2MuMapper()
42
    assert ll2mu.map_type(lltype.Ptr(lltype.RuntimeTypeInfo)) == mutype.MU_VOIDP
43
    assert ll2mu.map_type(llmemory.GCREF) == mutype.MU_VOIDR
John Zhang's avatar
John Zhang committed
44
    LL_META_CSTR = lltype.Ptr(lltype.GcOpaqueType("MuStr", hints={'mu_render_ptr_as': mutype.META_CSTR}))
45 46
    assert ll2mu.map_type(LL_META_CSTR) == mutype.META_CSTR

47 48 49
    def arrayofbytes(n):
        return mutype.MuArray(mutype.MU_INT8, n)

50 51 52
    # other opaque types
    # try translate the underlying opaque type first
    from rpython.rlib._rsocket_rffi import fd_set
53
    assert ll2mu.map_type(fd_set) == mutype.MuUPtr(arrayofbytes(fd_set.TO.hints['getsize']()))
54

55 56 57 58 59 60 61 62 63 64
    # 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<int<64>>
    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']()))
65

66
def test_map_type_hybrid():
John Zhang's avatar
John Zhang committed
67
    ll2mu = LL2MuMapper()
68
    from rpython.rtyper.lltypesystem.rstr import STR
John Zhang's avatar
John Zhang committed
69
    MuT = ll2mu.map_type(STR)
70 71 72

    assert isinstance(MuT, mutype.MuHybrid)
    assert MuT._vartype == mutype._MuMemArray(mutype.MU_INT8)
73

74
    A = lltype.GcArray(lltype.Char)
John Zhang's avatar
John Zhang committed
75
    MuT = ll2mu.map_type(A)
76
    assert MuT._names == ('gc_idhash', 'length', 'items')
77 78
    assert MuT.items.OF == mutype.MU_INT8

79 80 81 82 83 84 85 86
    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')

87
def test_map_type_ptr():
John Zhang's avatar
John Zhang committed
88
    ll2mu = LL2MuMapper()
89 90 91 92 93
    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)))

John Zhang's avatar
John Zhang committed
94
    MuT = ll2mu.map_type(PtrNode)
95 96
    assert isinstance(MuT, mutype.MuRef)    # GcStruct result in Ref
    assert isinstance(MuT.TO, mutype.MuForwardReference)    # resolve later to break loop
John Zhang's avatar
John Zhang committed
97
    ll2mu.resolve_ptr_types()
98 99 100 101 102
    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)
John Zhang's avatar
John Zhang committed
103
    assert isinstance(ll2mu.map_type(RawPtr), mutype.MuUPtr)    # non-GCed Struct result in UPtr
104

105
    from rpython.rtyper.rclass import OBJECTPTR
John Zhang's avatar
John Zhang committed
106 107
    MuT = ll2mu.map_type(OBJECTPTR)
    ll2mu.resolve_ptr_types()
108 109
    assert isinstance(MuT.TO.typeptr.TO, mutype.MuStruct)

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
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

125 126
def test_map_type_funcptr():
    from rpython.rtyper.rclass import OBJECTPTR
John Zhang's avatar
John Zhang committed
127 128 129
    ll2mu = LL2MuMapper()
    MuT = ll2mu.map_type(OBJECTPTR)
    ll2mu.resolve_ptr_types()
130
    FncRef = MuT.TO.typeptr.TO.instantiate
131
    Sig = FncRef.Sig
132 133
    assert Sig.ARGS == ()
    assert Sig.RESULTS == (MuT, )
134 135

# -----------------------------------------------------------------------------
136
def test_map_value_prim():
John Zhang's avatar
John Zhang committed
137 138 139
    ll2mu = LL2MuMapper()
    assert ll2mu.map_value(10) == mutype.mu_int64(10)
    assert ll2mu.map_value(rffi.INT._type(50)) == mutype.mu_int32(50)
140 141
    # XXX: what's the story for negative numbers in Mu? Check with Kunshan
    # for now, assume that negative number will be make unsigned
John Zhang's avatar
John Zhang committed
142
    assert ll2mu.map_value(rffi.INT._type(-50)) == mutype.mu_int32(4294967246)
143

John Zhang's avatar
John Zhang committed
144
    assert ll2mu.map_value(rarithmetic.r_singlefloat(1.5)) == mutype.mu_float(1.5)
145 146

    from rpython.rlib.objectmodel import malloc_zero_filled
147
    assert ll2mu.map_value(malloc_zero_filled) == mutype.mu_int64(1)
148

John Zhang's avatar
John Zhang committed
149
    assert ll2mu.map_value('c') == mutype.mu_int8(ord('c'))
150 151 152

def test_map_value_adrofs():
    from rpython.translator.mu.layout import mu_sizeOf, mu_offsetOf, mu_hybsizeOf
John Zhang's avatar
John Zhang committed
153 154
    ll2mu = LL2MuMapper()
    assert ll2mu.map_value(llmemory.sizeof(lltype.Char)) == mutype.mu_int64(1)
155
    S = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed))
John Zhang's avatar
John Zhang committed
156 157 158
    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')
159 160

    A = lltype.GcArray(lltype.Char)
John Zhang's avatar
John Zhang committed
161 162
    MuA = ll2mu.map_type(A)
    assert ll2mu.map_value(llmemory.itemoffsetof(A, 10)) == mu_hybsizeOf(MuA, 10)
163 164

def test_map_value_stt():
John Zhang's avatar
John Zhang committed
165
    ll2mu = LL2MuMapper()
166 167
    Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed))
    pt = lltype.malloc(Point, zero=True)._obj
John Zhang's avatar
John Zhang committed
168
    mupt = ll2mu.map_value(pt)
169 170 171 172 173 174 175 176 177
    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
John Zhang's avatar
John Zhang committed
178 179
    mupt3d = ll2mu.map_value(pt3d)
    assert mutype.mutypeOf(mupt3d) == ll2mu.map_type(Point3D)
180
    assert isinstance(mupt3d.super, mutype._mustruct)
John Zhang's avatar
John Zhang committed
181
    assert mutype.mutypeOf(mupt3d.super) == ll2mu.map_type(Point)
182 183
    mupt4d = mupt3d._parentstructure()
    assert isinstance(mupt4d, mutype._mustruct)
John Zhang's avatar
John Zhang committed
184
    assert mutype.mutypeOf(mupt4d) == ll2mu.map_type(Point4D)
185 186

def test_map_value_varstt():
John Zhang's avatar
John Zhang committed
187
    ll2mu = LL2MuMapper()
188 189 190 191 192 193 194

    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")

John Zhang's avatar
John Zhang committed
195
    mus = ll2mu.map_value(s)
196 197 198 199 200
    assert mus.hash == s.hash
    assert mus.length == 5
    for i in range(5):
        assert mus.chars[i] == ord(s.chars.getitem(i))

201 202 203 204 205 206 207 208 209 210 211 212 213
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))

214
def test_map_value_ptr():
John Zhang's avatar
John Zhang committed
215
    ll2mu = LL2MuMapper()
216 217 218 219
    Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed))
    PtrPoint = lltype.Ptr(Point)

    nullptr = lltype.nullptr(Point)
John Zhang's avatar
John Zhang committed
220
    assert ll2mu.map_value(nullptr)._is_null()
221 222

    p = lltype.malloc(Point, zero=True)
John Zhang's avatar
John Zhang committed
223 224
    r = ll2mu.map_value(p)
    ll2mu.resolve_ptr_values()
225
    assert isinstance(r, mutype._muref)
John Zhang's avatar
John Zhang committed
226
    assert mutype.mutypeOf(r._obj) == ll2mu.map_type(Point)
227 228 229 230 231 232 233 234

    # 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

John Zhang's avatar
John Zhang committed
235
    r = ll2mu.map_value(pobj)
236
    ll2mu.resolve_ptr_types()
John Zhang's avatar
John Zhang committed
237
    ll2mu.resolve_ptr_values()
238 239 240 241 242 243
    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')

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
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

266
def test_map_funcptr():
John Zhang's avatar
John Zhang committed
267
    ll2mu = LL2MuMapper()
268 269 270 271 272 273 274

    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()
John Zhang's avatar
John Zhang committed
275
    fnr = ll2mu.map_value(fncptr)
276 277 278 279 280
    assert fnr.graph is g
    assert fnr._name == g.name

    from rpython.rlib.rposix import c_read
    llfncptr = c_read._ptr
John Zhang's avatar
John Zhang committed
281
    extfnp = ll2mu.map_value(llfncptr)
282 283 284
    assert isinstance(extfnp, mutype._muufuncptr)
    assert extfnp._name == llfncptr._obj._name
    assert extfnp.eci == llfncptr._obj.compilation_info
John Zhang's avatar
John Zhang committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312


# -----------------------------------------------------------------------------
# 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()
313
    res = varof(mutype.MU_INT8, 'res')
John Zhang's avatar
John Zhang committed
314 315
    llop = SpaceOperation('bool_not',
                          [ll2mu.mapped_const(True)],
316
                          res)
John Zhang's avatar
John Zhang committed
317 318 319 320 321
    muops = ll2mu.map_op(llop)
    assert len(muops) == 1
    binop = muops[0]
    assert binop.opname == 'mu_binop'

John Zhang's avatar
John Zhang committed
322 323
def test_int_abs():
    ll2mu = LL2MuMapper()
324
    res = varof(mutype.MU_INT64, 'res')
John Zhang's avatar
John Zhang committed
325 326
    llop = SpaceOperation('int_abs',
                          [ll2mu.mapped_const(-125)],
327
                          res)
John Zhang's avatar
John Zhang committed
328 329 330 331
    muops = ll2mu.map_op(llop)
    assert len(muops) == 3
    assert [op.opname for op in muops] == ['mu_binop', 'mu_cmpop', 'mu_select']

John Zhang's avatar
John Zhang committed
332 333
def test_int_between():
    ll2mu = LL2MuMapper()
334
    res = varof(ll2mu.map_type(lltype.Bool), 'res')
John Zhang's avatar
John Zhang committed
335
    llop = SpaceOperation('int_between',
336
                          [ll2mu.mapped_const(42), varof(mutype.MU_INT64, 'x'), ll2mu.mapped_const(100)],
337
                          res)
John Zhang's avatar
John Zhang committed
338 339 340 341 342 343
    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()
344
    res = varof(mutype.MU_INT64, 'res')
John Zhang's avatar
John Zhang committed
345
    llop = SpaceOperation('int_mul_ovf',
346
                          [varof(mutype.MU_INT64, 'a'), varof(mutype.MU_INT64, 'b')],
347
                          res)
John Zhang's avatar
John Zhang committed
348 349
    muops = ll2mu.map_op(llop)
    assert len(muops) == 1
John Zhang's avatar
John Zhang committed
350 351 352 353 354 355
    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)
John Zhang's avatar
John Zhang committed
356

John Zhang's avatar
John Zhang committed
357 358
def test_cast_char_to_int():
    ll2mu = LL2MuMapper()
359
    res = varof(mutype.MU_INT64, 'res')
360
    llop = SpaceOperation('cast_char_to_int', [varof(ll2mu.map_type(lltype.Char), 'c')],
361
                          res)
John Zhang's avatar
John Zhang committed
362

John Zhang's avatar
John Zhang committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
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
John Zhang's avatar
John Zhang committed
465 466 467 468

def test_malloc_varsize():
    ll2mu = LL2MuMapper()
    Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8))
469
    rs = varof(mutype.MuRef(Hyb), "rs")
John Zhang's avatar
John Zhang committed
470 471 472 473 474 475
    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']
476
    assert muops[0].result is rs    # the result is of the first instruction rather than the last
John Zhang's avatar
John Zhang committed
477

478 479 480 481 482 483 484 485 486 487

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)
488
    assert [op.opname for op in muops] == ['mu_binop', 'mu_binop', 'mu_ccall', 'mu_getfieldiref', 'mu_store']
489 490


John Zhang's avatar
John Zhang committed
491 492 493
def test_setarrayitem():
    ll2mu = LL2MuMapper()
    Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8))
494
    rs = varof(mutype.MuRef(Hyb), "rs")
John Zhang's avatar
John Zhang committed
495 496 497 498
    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']
499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

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']
521 522 523 524 525 526 527 528


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))
529 530 531 532 533
    assert [op.opname for op in muops] == ['mu_cmpop', 'mu_convop']

def test_raw_memcopy():
    ll2mu = LL2MuMapper()
    VOIDP = ll2mu.map_type(rffi.VOIDP)
534 535
    src = varof(mutype.MU_INT64, 'src')
    dst = varof(mutype.MU_INT64, 'dst')
536 537 538
    sz = varof(mutype.MU_INT64, 'sz')
    llop = SpaceOperation('raw_memcopy', [src, dst, sz], varof(mutype.MU_VOID))
    muops = ll2mu.map_op(llop)
539 540
    assert [op.opname for op in muops] == ['mu_convop', 'mu_convop', 'mu_ccall']
    ccall = muops[-1]
541
    assert ccall.args[0].value._name == 'memcpy'
542 543 544 545 546
    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
John Zhang's avatar
John Zhang committed
547 548 549 550 551 552 553 554 555 556 557 558 559

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()

560
    ll2mu = LL2MuMapper(t.context.rtyper)
John Zhang's avatar
John Zhang committed
561 562 563 564 565 566

    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)
567
    ll2mu.resolve_ptr_types()
John Zhang's avatar
John Zhang committed
568 569

    muops = ll2mu.map_op(llop)
570
    assert [op.opname for op in muops] == ['mu_comminst', 'mu_convop', 'mu_call', 'mu_comminst']
John Zhang's avatar
John Zhang committed
571

572
    call = muops[2]
John Zhang's avatar
John Zhang committed
573
    callee_c = call.args[0]
574
    assert callee_c == ll2mu.ll_identityhash_c
John Zhang's avatar
John Zhang committed
575

John Zhang's avatar
John Zhang committed
576 577 578 579 580 581 582 583 584 585 586 587 588

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']

589 590 591 592
    # 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']

John Zhang's avatar
John Zhang committed
593 594 595
    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']

John Zhang's avatar
John Zhang committed
596 597 598 599 600 601 602 603 604 605 606 607 608
    # 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)
609
    ll2mu.resolve_ptr_values()
John Zhang's avatar
John Zhang committed
610
    assert muv._is_null()
611 612


613 614 615 616 617 618 619 620 621 622 623 624 625
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


626 627 628 629 630
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
John Zhang's avatar
John Zhang committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670


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']
671 672 673 674 675 676 677 678 679 680


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']
681 682 683 684 685 686 687 688 689 690 691 692 693


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
694 695 696 697


def test_typedescr_str():
    S = mutype.MuStruct('S', ('x', mutype.MU_INT64), ('y', mutype.MU_FLOAT), ('z', mutype.MuRef(mutype.MU_INT64)))
698
    assert get_typedescr_str(S) == '(lfr)'
699 700

    from rpython.rtyper.lltypesystem.rstr import STR
701 702
    H = ll2mu_type(STR)
    assert get_typedescr_str(H) == '{lll|b}'
703 704

    A = mutype.MuArray(S, 10)
705
    assert get_typedescr_str(A) == '[10|(lfr)]'
John Zhang's avatar
John Zhang committed
706

707 708 709 710 711 712 713 714
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']
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748


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']
749

750 751 752 753 754 755 756 757 758

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'
759 760 761 762 763 764 765 766 767


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'