To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

test_ll2mu.py 26.1 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
def test_map_type_hybrid():
John Zhang's avatar
John Zhang committed
48
    ll2mu = LL2MuMapper()
49
    from rpython.rtyper.lltypesystem.rstr import STR
John Zhang's avatar
John Zhang committed
50
    MuT = ll2mu.map_type(STR)
51
52
53

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

John Zhang's avatar
John Zhang committed
55
    A = lltype.GcArray(lltype.Char)
John Zhang's avatar
John Zhang committed
56
    MuT = ll2mu.map_type(A)
57
    assert MuT._names == ('gc_idhash', 'length', 'items')
John Zhang's avatar
John Zhang committed
58
59
    assert MuT.items.OF == mutype.MU_INT8

60
61
62
63
64
65
66
67
    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')

68
def test_map_type_ptr():
John Zhang's avatar
John Zhang committed
69
    ll2mu = LL2MuMapper()
70
71
72
73
74
    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
75
    MuT = ll2mu.map_type(PtrNode)
76
77
    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
78
    ll2mu.resolve_ptr_types()
79
80
81
82
83
    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
84
    assert isinstance(ll2mu.map_type(RawPtr), mutype.MuUPtr)    # non-GCed Struct result in UPtr
85

John Zhang's avatar
John Zhang committed
86
    from rpython.rtyper.rclass import OBJECTPTR
John Zhang's avatar
John Zhang committed
87
88
    MuT = ll2mu.map_type(OBJECTPTR)
    ll2mu.resolve_ptr_types()
John Zhang's avatar
John Zhang committed
89
90
    assert isinstance(MuT.TO.typeptr.TO, mutype.MuStruct)

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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

106
107
def test_map_type_funcptr():
    from rpython.rtyper.rclass import OBJECTPTR
John Zhang's avatar
John Zhang committed
108
109
110
    ll2mu = LL2MuMapper()
    MuT = ll2mu.map_type(OBJECTPTR)
    ll2mu.resolve_ptr_types()
111
    FncRef = MuT.TO.typeptr.TO.instantiate
John Zhang's avatar
John Zhang committed
112
    Sig = FncRef.Sig
113
114
    assert Sig.ARGS == ()
    assert Sig.RESULTS == (MuT, )
115
116

# -----------------------------------------------------------------------------
John Zhang's avatar
John Zhang committed
117
def test_map_value_prim():
John Zhang's avatar
John Zhang committed
118
119
120
    ll2mu = LL2MuMapper()
    assert ll2mu.map_value(10) == mutype.mu_int64(10)
    assert ll2mu.map_value(rffi.INT._type(50)) == mutype.mu_int32(50)
John Zhang's avatar
John Zhang committed
121
122
    # 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
123
    assert ll2mu.map_value(rffi.INT._type(-50)) == mutype.mu_int32(4294967246)
John Zhang's avatar
John Zhang committed
124

John Zhang's avatar
John Zhang committed
125
    assert ll2mu.map_value(rarithmetic.r_singlefloat(1.5)) == mutype.mu_float(1.5)
John Zhang's avatar
John Zhang committed
126
127

    from rpython.rlib.objectmodel import malloc_zero_filled
128
    assert ll2mu.map_value(malloc_zero_filled) == mutype.mu_int64(1)
John Zhang's avatar
John Zhang committed
129

John Zhang's avatar
John Zhang committed
130
    assert ll2mu.map_value('c') == mutype.mu_int8(ord('c'))
John Zhang's avatar
John Zhang committed
131
132
133

def test_map_value_adrofs():
    from rpython.translator.mu.layout import mu_sizeOf, mu_offsetOf, mu_hybsizeOf
John Zhang's avatar
John Zhang committed
134
135
    ll2mu = LL2MuMapper()
    assert ll2mu.map_value(llmemory.sizeof(lltype.Char)) == mutype.mu_int64(1)
John Zhang's avatar
John Zhang committed
136
    S = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed))
John Zhang's avatar
John Zhang committed
137
138
139
    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')
John Zhang's avatar
John Zhang committed
140
141

    A = lltype.GcArray(lltype.Char)
John Zhang's avatar
John Zhang committed
142
143
    MuA = ll2mu.map_type(A)
    assert ll2mu.map_value(llmemory.itemoffsetof(A, 10)) == mu_hybsizeOf(MuA, 10)
John Zhang's avatar
John Zhang committed
144
145

def test_map_value_stt():
John Zhang's avatar
John Zhang committed
146
    ll2mu = LL2MuMapper()
John Zhang's avatar
John Zhang committed
147
148
    Point = lltype.GcStruct("Point", ('x', lltype.Signed), ('y', lltype.Signed))
    pt = lltype.malloc(Point, zero=True)._obj
John Zhang's avatar
John Zhang committed
149
    mupt = ll2mu.map_value(pt)
John Zhang's avatar
John Zhang committed
150
151
152
153
154
155
156
157
158
    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
159
160
    mupt3d = ll2mu.map_value(pt3d)
    assert mutype.mutypeOf(mupt3d) == ll2mu.map_type(Point3D)
John Zhang's avatar
John Zhang committed
161
    assert isinstance(mupt3d.super, mutype._mustruct)
John Zhang's avatar
John Zhang committed
162
    assert mutype.mutypeOf(mupt3d.super) == ll2mu.map_type(Point)
John Zhang's avatar
John Zhang committed
163
164
    mupt4d = mupt3d._parentstructure()
    assert isinstance(mupt4d, mutype._mustruct)
John Zhang's avatar
John Zhang committed
165
    assert mutype.mutypeOf(mupt4d) == ll2mu.map_type(Point4D)
John Zhang's avatar
John Zhang committed
166
167

def test_map_value_varstt():
John Zhang's avatar
John Zhang committed
168
    ll2mu = LL2MuMapper()
John Zhang's avatar
John Zhang committed
169
170
171
172
173
174
175

    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
176
    mus = ll2mu.map_value(s)
John Zhang's avatar
John Zhang committed
177
178
179
180
181
    assert mus.hash == s.hash
    assert mus.length == 5
    for i in range(5):
        assert mus.chars[i] == ord(s.chars.getitem(i))

182
183
184
185
186
187
188
189
190
191
192
193
194
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))

John Zhang's avatar
John Zhang committed
195
def test_map_value_ptr():
John Zhang's avatar
John Zhang committed
196
    ll2mu = LL2MuMapper()
John Zhang's avatar
John Zhang committed
197
198
199
200
    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
201
    assert ll2mu.map_value(nullptr)._is_null()
John Zhang's avatar
John Zhang committed
202
203

    p = lltype.malloc(Point, zero=True)
John Zhang's avatar
John Zhang committed
204
205
    r = ll2mu.map_value(p)
    ll2mu.resolve_ptr_values()
John Zhang's avatar
John Zhang committed
206
    assert isinstance(r, mutype._muref)
John Zhang's avatar
John Zhang committed
207
    assert mutype.mutypeOf(r._obj) == ll2mu.map_type(Point)
John Zhang's avatar
John Zhang committed
208
209
210
211
212
213
214
215

    # 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
216
    r = ll2mu.map_value(pobj)
217
    ll2mu.resolve_ptr_types()
John Zhang's avatar
John Zhang committed
218
    ll2mu.resolve_ptr_values()
John Zhang's avatar
John Zhang committed
219
220
221
222
223
224
    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')

225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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

John Zhang's avatar
John Zhang committed
247
def test_map_funcptr():
John Zhang's avatar
John Zhang committed
248
    ll2mu = LL2MuMapper()
John Zhang's avatar
John Zhang committed
249
250
251
252
253
254
255

    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
256
    fnr = ll2mu.map_value(fncptr)
John Zhang's avatar
John Zhang committed
257
258
259
260
261
    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
262
    extfnp = ll2mu.map_value(llfncptr)
John Zhang's avatar
John Zhang committed
263
264
265
    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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293


# -----------------------------------------------------------------------------
# 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()
294
    res = varof(mutype.MU_INT8, 'res')
John Zhang's avatar
John Zhang committed
295
296
    llop = SpaceOperation('bool_not',
                          [ll2mu.mapped_const(True)],
297
                          res)
John Zhang's avatar
John Zhang committed
298
299
300
301
302
    muops = ll2mu.map_op(llop)
    assert len(muops) == 1
    binop = muops[0]
    assert binop.opname == 'mu_binop'

John Zhang's avatar
John Zhang committed
303
304
def test_int_abs():
    ll2mu = LL2MuMapper()
305
    res = varof(mutype.MU_INT64, 'res')
John Zhang's avatar
John Zhang committed
306
307
    llop = SpaceOperation('int_abs',
                          [ll2mu.mapped_const(-125)],
308
                          res)
John Zhang's avatar
John Zhang committed
309
310
311
312
    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
313
314
def test_int_between():
    ll2mu = LL2MuMapper()
315
    res = varof(ll2mu.map_type(lltype.Bool), 'res')
John Zhang's avatar
John Zhang committed
316
    llop = SpaceOperation('int_between',
317
                          [ll2mu.mapped_const(42), varof(mutype.MU_INT64, 'x'), ll2mu.mapped_const(100)],
318
                          res)
John Zhang's avatar
John Zhang committed
319
320
321
322
323
324
    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()
325
    res = varof(mutype.MU_INT64, 'res')
John Zhang's avatar
John Zhang committed
326
    llop = SpaceOperation('int_mul_ovf',
327
                          [varof(mutype.MU_INT64, 'a'), varof(mutype.MU_INT64, 'b')],
328
                          res)
John Zhang's avatar
John Zhang committed
329
330
    muops = ll2mu.map_op(llop)
    assert len(muops) == 1
John Zhang's avatar
John Zhang committed
331
332
333
334
335
336
    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
337

John Zhang's avatar
John Zhang committed
338
339
def test_cast_char_to_int():
    ll2mu = LL2MuMapper()
340
    res = varof(mutype.MU_INT64, 'res')
341
    llop = SpaceOperation('cast_char_to_int', [varof(ll2mu.map_type(lltype.Char), 'c')],
342
                          res)
John Zhang's avatar
John Zhang committed
343

John Zhang's avatar
John Zhang committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
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
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
446
447
448
449

def test_malloc_varsize():
    ll2mu = LL2MuMapper()
    Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8))
450
    rs = varof(mutype.MuRef(Hyb), "rs")
John Zhang's avatar
John Zhang committed
451
452
453
454
455
456
    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']
457
    assert muops[0].result is rs    # the result is of the first instruction rather than the last
John Zhang's avatar
John Zhang committed
458

459
460
461
462
463
464
465
466
467
468

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


John Zhang's avatar
John Zhang committed
472
473
474
def test_setarrayitem():
    ll2mu = LL2MuMapper()
    Hyb = mutype.MuHybrid('string', ('hash', mutype.MU_INT64), ('length', mutype.MU_INT64), ('chars', mutype.MU_INT8))
475
    rs = varof(mutype.MuRef(Hyb), "rs")
John Zhang's avatar
John Zhang committed
476
477
478
479
    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']
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501

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']
502
503
504
505
506
507
508
509


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))
510
511
512
513
514
    assert [op.opname for op in muops] == ['mu_cmpop', 'mu_convop']

def test_raw_memcopy():
    ll2mu = LL2MuMapper()
    VOIDP = ll2mu.map_type(rffi.VOIDP)
515
516
    src = varof(mutype.MU_INT64, 'src')
    dst = varof(mutype.MU_INT64, 'dst')
517
518
519
    sz = varof(mutype.MU_INT64, 'sz')
    llop = SpaceOperation('raw_memcopy', [src, dst, sz], varof(mutype.MU_VOID))
    muops = ll2mu.map_op(llop)
520
521
    assert [op.opname for op in muops] == ['mu_convop', 'mu_convop', 'mu_ccall']
    ccall = muops[-1]
522
    assert ccall.args[0].value._name == 'memcpy'
523
524
525
526
527
    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
528
529
530
531
532
533
534
535
536
537
538
539
540

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

541
    ll2mu = LL2MuMapper(t.context.rtyper)
John Zhang's avatar
John Zhang committed
542
543
544
545
546
547

    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)
548
    ll2mu.resolve_ptr_types()
John Zhang's avatar
John Zhang committed
549
550

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

553
    call = muops[2]
John Zhang's avatar
John Zhang committed
554
    callee_c = call.args[0]
555
    assert callee_c == ll2mu.ll_identityhash_c
John Zhang's avatar
John Zhang committed
556

John Zhang's avatar
John Zhang committed
557
558
559
560
561
562
563
564
565
566
567
568
569

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

570
571
572
573
    # 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
574
575
576
    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
577
578
579
580
581
582
583
584
585
586
587
588
589
    # 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)
590
    ll2mu.resolve_ptr_values()
John Zhang's avatar
John Zhang committed
591
    assert muv._is_null()
592
593


594
595
596
597
598
599
600
601
602
603
604
605
606
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


607
608
609
610
611
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
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651


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']
652
653
654
655
656
657
658
659
660
661


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']
662
663
664
665
666
667
668
669
670
671
672
673
674


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
675
676
677
678


def test_typedescr_str():
    S = mutype.MuStruct('S', ('x', mutype.MU_INT64), ('y', mutype.MU_FLOAT), ('z', mutype.MuRef(mutype.MU_INT64)))
679
    assert get_typedescr_str(S) == '(lfr)'
680
681

    from rpython.rtyper.lltypesystem.rstr import STR
682
683
    H = ll2mu_type(STR)
    assert get_typedescr_str(H) == '{lll|b}'
684
685

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

688
689
690
691
692
693
694
695
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']
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729


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