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

ll2mu.py 78.8 KB
Newer Older
1
from rpython.annotator.model import SomeString, SomeBool
2
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
3
from rpython.translator.mu import mutype, layout
4
from rpython.rtyper.normalizecalls import TotalOrderSymbolic
5
from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
6
from rpython.rtyper.llannotation import lltype_to_annotation as l2a
7
from rpython.rlib.objectmodel import CDefinedIntSymbolic
John Zhang's avatar
John Zhang committed
8
from rpython.rlib import rarithmetic
9
from rpython.flowspace.model import Variable, Constant, SpaceOperation, Link
10
11
from rpython.translator.c.node import needs_gcheader
from random import randint
John Zhang's avatar
John Zhang committed
12
import weakref
13

14
15
16
17
18
19
20
21
try:
    from rpython.rlib.rmu import holstein as rmu
except Exception:
    try:
        from rpython.rlib.rmu import zebu as rmu
    except Exception:
        raise

22
23
24
25
26
27
from rpython.tool.ansi_print import AnsiLogger
from rpython.tool.ansi_mandelbrot import Driver

log = AnsiLogger("ll2mu")
mdb = Driver()

John Zhang's avatar
John Zhang committed
28
29

class LL2MuMapper:
30
    GC_IDHASH_FIELD = ('gc_idhash', mutype.MU_INT64)
31

32
    def __init__(self, rtyper=None):
John Zhang's avatar
John Zhang committed
33
34
35
        """
        :type mlha: rpython.rtyper.annlowlevel.MixLevelHelperAnnotator
        """
36
        self._type_cache = {}
John Zhang's avatar
John Zhang committed
37
        self._pending_ptr_types = []
38
        self._name_cache = {}
John Zhang's avatar
John Zhang committed
39
40
41
42
        self._val_cache = {}
        self._ptr_cache = {}
        self._topstt_map = {}
        self._pending_ptr_values = []
43
44
45
46
        if rtyper:
            self.mlha = MixLevelHelperAnnotator(rtyper)
        else:
            self.mlha = None
47
48

        if self.mlha:
49
            self._translate_llhelpers()
50

51
    def _translate_llhelpers(self):
52
53
54
55
56
57
58
59
60
61
62
        # code taken from rpython/memory/gctransform/boehm.py
        HDR = lltype.Struct("header", ("hash", lltype.Signed))
        HDRPTR = lltype.Ptr(HDR)

        def ll_identityhash(addr):
            obj = llmemory.cast_adr_to_ptr(addr, HDRPTR)
            h = obj.hash
            if h == 0:
                obj.hash = h = llmemory.cast_adr_to_int(addr)
            return h

63
        idhash_c = self.mlha.constfunc(ll_identityhash, [l2a(llmemory.Address)], l2a(lltype.Signed))
64
        try:
65
66
            g = filter(lambda g: getattr(g, 'func', None) is rffi.str2charp,
                       self.mlha.rtyper.annotator.translator.graphs)[0]
67
68
69
70
71
72
73
74
            fnp = lltype.functionptr(lltype.FuncType(
                [a.concretetype for a in g.startblock.inputargs], g.returnblock.inputargs[0].concretetype),
            g.name, graph=g)
            str2charp_c = Constant(fnp, lltype.typeOf(fnp))
        except IndexError:
            str2charp_c = self.mlha.constfunc(rffi.str2charp, [SomeString(), SomeBool()], l2a(rffi.CCHARP))

        try:
75
76
            g = filter(lambda g: getattr(g, 'func', None) is rffi.free_charp,
                       self.mlha.rtyper.annotator.translator.graphs)[0]
77
78
79
80
81
82
            fnp = lltype.functionptr(lltype.FuncType(
                [a.concretetype for a in g.startblock.inputargs], g.returnblock.inputargs[0].concretetype),
                g.name, graph=g)
            freecharp_c = Constant(fnp, lltype.typeOf(fnp))
        except IndexError:
            freecharp_c = self.mlha.constfunc(rffi.free_charp, [l2a(rffi.CCHARP), SomeBool()], l2a(lltype.Void))
83

84
85
        self.mlha.finish()
        self.mlha.backend_optimize()
86
87
88
89
90
91
92
93
94
95
        idhash_c.value = self.map_value(idhash_c.value)
        idhash_c.concretetype = mutype.mutypeOf(idhash_c.value)
        str2charp_c.value = self.map_value(str2charp_c.value)
        freecharp_c.value = self.map_value(freecharp_c.value)
        str2charp_c.concretetype = mutype.mutypeOf(str2charp_c.value)
        freecharp_c.concretetype = mutype.mutypeOf(freecharp_c.value)

        self.ll_identityhash_c = idhash_c
        self.ll_str2charp_c = str2charp_c
        self.ll_freecharp_c = freecharp_c
96

97
98
        self.llhelper_graphs = [c.value.graph for c in (self.ll_identityhash_c, self.ll_str2charp_c,
                                                        self.ll_freecharp_c)]
99
100
101
102
103
104
105
106
107
108

    def _new_typename(self, name):
        if name not in self._name_cache:
            n = 2
            self._name_cache[name] = n
            return name
        n = self._name_cache[name]
        self._name_cache[name] = n + 1
        return "%(name)s_%(n)d" % locals()

John Zhang's avatar
John Zhang committed
109
    def map_type(self, LLT):
110
111
112
113
114
        assert isinstance(LLT, lltype.LowLevelType)
        try:
            return self._type_cache[LLT]
        except KeyError:
            if LLT is llmemory.Address:
John Zhang's avatar
John Zhang committed
115
                MuT = self.map_type_addr(LLT)
116
            elif isinstance(LLT, lltype.Primitive):
John Zhang's avatar
John Zhang committed
117
                MuT = self.map_type_prim(LLT)
118
            elif isinstance(LLT, lltype.FixedSizeArray):
John Zhang's avatar
John Zhang committed
119
                MuT = self.map_type_arrfix(LLT)
120
121
122
            elif isinstance(LLT, lltype.Struct):
                MuT = self.map_type_stt(LLT)
            elif isinstance(LLT, lltype.Array):
John Zhang's avatar
John Zhang committed
123
                MuT = self.map_type_arr(LLT)
124
            elif isinstance(LLT, lltype.Ptr):
John Zhang's avatar
John Zhang committed
125
                MuT = self.map_type_ptr(LLT)
126
127
            elif isinstance(LLT, lltype.InteriorPtr):
                MuT = self.map_type_iptr(LLT)
128
129
            # elif isinstance(LLT, lltype.OpaqueType):
            #     MuT = self.map_type_opq(LLT)
130
            elif LLT is llmemory.WeakRef:
131
                MuT = self.map_wref(LLT)
John Zhang's avatar
John Zhang committed
132
133
            elif isinstance(LLT, lltype.Typedef):
                return self.map_type(LLT.OF)
134
135
136
137
138
            else:
                raise NotImplementedError("Don't know how to specialise %s using MuTS." % LLT)
            self._type_cache[LLT] = MuT
            return MuT

John Zhang's avatar
John Zhang committed
139
    def map_type_prim(self, LLT):
140
141
142
143
144
145
146
147
148
149
150
151
152
153
        type_map = {
            lltype.Signed:              mutype.MU_INT64,
            lltype.Unsigned:            mutype.MU_INT64,
            lltype.SignedLongLong:      mutype.MU_INT64,
            lltype.UnsignedLongLong:    mutype.MU_INT64,
            lltype.SignedLongLongLong:  mutype.MU_INT128,

            lltype.Float:               mutype.MU_DOUBLE,
            lltype.SingleFloat:         mutype.MU_FLOAT,
            lltype.LongFloat:           mutype.MU_DOUBLE,

            lltype.Char:                mutype.MU_INT8,
            lltype.Bool:                mutype.MU_INT8,
            lltype.Void:                mutype.MU_VOID,
154
            lltype.UniChar:             mutype.MU_INT32,    # wchar_t is 32-bits on OS X and Linux 64-bit machines
155
156
157
158
        }
        try:
            return type_map[LLT]
        except KeyError:
159
            if isinstance(LLT, lltype.Number) and issubclass(LLT._type, rarithmetic.base_int):  # integer type
160
                b = LLT._type.BITS
161
162
163
164
165
                if hasattr(mutype, "MU_INT%d" % b):
                    return getattr(mutype, "MU_INT%d" % b)
                else:
                    return mutype.MuIntType("MU_INT%d" % b,
                                            rarithmetic.build_int('r_uint%d' % b, False, b))    # unsigned
166
167
            raise NotImplementedError("Don't know how to specialise %s using MuTS." % LLT)

John Zhang's avatar
John Zhang committed
168
    def map_type_arrfix(self, LLT):
169
170
171
        if LLT.length == 1:
            return self.map_type(LLT.OF)    # consider length 1 fixed sized array transparent

John Zhang's avatar
John Zhang committed
172
        return mutype.MuArray(self.map_type(LLT.OF), LLT.length)
173
174
175

    def map_type_stt(self, LLT):
        if LLT._is_varsize():
John Zhang's avatar
John Zhang committed
176
            return self.map_type_varstt(LLT)
177
178
179

        flds = []
        if needs_gcheader(LLT):
John Zhang's avatar
John Zhang committed
180
            flds.append(LL2MuMapper.GC_IDHASH_FIELD)
181
182

        for n in LLT._names:
John Zhang's avatar
John Zhang committed
183
            MuT = self.map_type(LLT._flds[n])
184
185
186
            if MuT is not mutype.MU_VOID:
                flds.append((n, MuT))

John Zhang's avatar
John Zhang committed
187
188
189
190
191
192
193
        if len(flds) == 0:  # empty struct
            # Mu does not support empty struct
            # From the spec:
            #   In Mu, if it is desired to allocate an empty unit in the heap,
            #   the appropriate type is `void`
            return mutype.MU_VOID

194
195
196
        name = self._new_typename(LLT._name)
        return mutype.MuStruct(name, *flds)

John Zhang's avatar
John Zhang committed
197
198
    def map_type_varstt(self, LLT):
        VarT = self.map_type(LLT._flds[LLT._arrayfld].OF)
199
200
201
202
203
204
205

        _names = LLT._names_without_voids()[:-1]
        _flds = LLT._flds.copy()
        if 'length' not in _names:
            _names.append('length')
            _flds['length'] = lltype.Signed

John Zhang's avatar
John Zhang committed
206
        flds = [(n, self.map_type(_flds[n])) for n in _names] + \
207
208
               [(LLT._arrayfld, VarT)]
        if needs_gcheader(LLT):
John Zhang's avatar
John Zhang committed
209
            flds.insert(0, LL2MuMapper.GC_IDHASH_FIELD)
210

211
        name = self._new_typename(LLT._name)
212
213
        return mutype.MuHybrid(name, *flds)

John Zhang's avatar
John Zhang committed
214
    def map_type_arr(self, LLT):
John Zhang's avatar
John Zhang committed
215
216
217
        if LLT._hints.get('mu_render_as', None):
            return LLT._hints['mu_render_as']

John Zhang's avatar
John Zhang committed
218
        name = "arr" + ("%s" % LLT.OF.__name__ if hasattr(LLT.OF, '__name__') else str(LLT.OF))
219
220
221
222

        if LLT.OF is lltype.Void:
            return mutype.MuStruct(name, ('length', mutype.MU_INT64))

223
224
225
        if LLT._hints.get('render_as_void', False):
            return mutype.MU_VOID

226
227
228
229
230
231
232
        MuT_OF = self.map_type(LLT.OF)
        flds = [('items', MuT_OF)]

        no_length = LLT._hints.get('nolength', False)
        no_hashfield = LLT._hints.get('mu_nohashfield', False)

        if not no_length:
233
234
            flds.insert(0, ('length', mutype.MU_INT64))

235
        if not no_hashfield and needs_gcheader(LLT):
John Zhang's avatar
John Zhang committed
236
            flds.insert(0, LL2MuMapper.GC_IDHASH_FIELD)
237
238
239

        return mutype.MuHybrid(name, *flds)

John Zhang's avatar
John Zhang committed
240
    def map_type_ptr(self, LLT):
241
        if isinstance(LLT.TO, lltype.FuncType):
John Zhang's avatar
John Zhang committed
242
            return self.map_type_funcptr(LLT)
243

244
245
246
        elif isinstance(LLT.TO, lltype.OpaqueType):
            return self.map_type_opqptr(LLT)

247
248
249
250
251
252
        if LLT.TO._gckind == 'gc':
            cls = mutype.MuRef
        else:
            cls = mutype.MuUPtr

        MuObjT = mutype.MuForwardReference()
John Zhang's avatar
John Zhang committed
253
        self._pending_ptr_types.append((LLT.TO, MuObjT))
254
255
        return cls(MuObjT)

256
257
258
259
260
    def map_type_iptr(self, LLT):
        MuObjT = mutype.MuForwardReference()
        self._pending_ptr_types.append((LLT.TO, MuObjT))
        return mutype.MuIRef(MuObjT)

John Zhang's avatar
John Zhang committed
261
262
263
264
    def resolve_ptr_types(self):
        while len(self._pending_ptr_types) > 0:
            LLObjT, MuObjT = self._pending_ptr_types.pop()
            MuObjT.become(self.map_type(LLObjT))
265

John Zhang's avatar
John Zhang committed
266
    def map_type_addr(self, LLT):
267
        return mutype.MuUPtr(mutype.MU_INT8)  # NOTE: all Address types are mapped to uptr<int<8>>
268

269
270
271
    def map_type_opqptr(self, LLT):
        T = LLT.TO

272
273
274
275
        if T is lltype.RuntimeTypeInfo:
            return mutype.MU_VOIDP  # rtti is never used;
        elif T is llmemory.GCREF.TO:
            return mutype.MU_VOIDR  # translate GCREF as ref<void>
John Zhang's avatar
John Zhang committed
276
277
        elif 'mu_render_ptr_as' in T.hints:
            return T.hints['mu_render_ptr_as']
278
279
280
281
282
283

        if LLT.TO._gckind == 'gc':
            cls = mutype.MuRef
        else:
            cls = mutype.MuUPtr
        return cls(mutype.MU_INT64)     # default to ref/uptr<int<64>>
284

John Zhang's avatar
John Zhang committed
285
    def map_type_funcptr(self, LLT):
286
        LLFnc = LLT.TO
John Zhang's avatar
John Zhang committed
287
        ARG_TS = tuple(self.map_type(ARG) for ARG in LLFnc.ARGS if ARG != lltype.Void)
288
        RTN_TS = (self.map_type(LLFnc.RESULT),) if LLFnc.RESULT != lltype.Void else tuple()
289
290
        sig = mutype.MuFuncSig(ARG_TS, RTN_TS)
        return mutype.MuFuncRef(sig)
291
292

    def map_wref(self, LLT):
John Zhang's avatar
John Zhang committed
293
294
295
296
297
        """
        Translate weak references as struct<weakref<void>>
        This is because weakref can only be a memory location (not SSA variable).
        """
        return mutype.MuStruct('WeakRef', ('wref', mutype.MU_WEAKREF_VOID))
298

John Zhang's avatar
John Zhang committed
299
300
    # -----------------------------------------------------------------------------
    def map_value(self, llv, **kwargs):
301
        cache, v = (self._ptr_cache, llv._obj) \
302
            if isinstance(llv, lltype._abstract_ptr) \
303
304
305
306
307
308
309
            else (self._val_cache, llv)
        LLT = lltype.typeOf(llv)
        key = (LLT, v)
        try:
            return cache[key]
        except KeyError:
            if isinstance(LLT, lltype.Primitive):
John Zhang's avatar
John Zhang committed
310
                muv = self.map_value_prim(llv)
311
312

            elif isinstance(llv, lltype._fixedsizearray):
John Zhang's avatar
John Zhang committed
313
                muv = self.map_value_arrfix(llv)
314
315

            elif isinstance(llv, lltype._struct):
John Zhang's avatar
John Zhang committed
316
                muv = self.map_value_stt(llv, **kwargs)
317
318

            elif isinstance(llv, lltype._array):
John Zhang's avatar
John Zhang committed
319
                muv = self.map_value_arr(llv)
320
321

            elif isinstance(llv, lltype._ptr):
John Zhang's avatar
John Zhang committed
322
                muv = self.map_value_ptr(llv)
323

324
325
326
            elif isinstance(llv, lltype._interior_ptr):
                muv = self.map_value_iptr(llv)

327
            elif isinstance(llv, lltype._opaque):
John Zhang's avatar
John Zhang committed
328
                muv = self.map_value_opq(llv)
329
330

            elif isinstance(llv, llmemory._wref):
John Zhang's avatar
John Zhang committed
331
                muv = self.map_value_wref(llv)
332
333
334
335
336
337
338
339
340
341

            else:
                raise NotImplementedError(
                    "Don't know how to specialise value %r of type %r." % (llv, lltype.typeOf(llv)))

            if key not in cache:  # may have already been added to cache (in stt to prevent recursion).
                cache[key] = muv
            return muv
        except TypeError, e:
            if isinstance(llv, llmemory.AddressOffset):
John Zhang's avatar
John Zhang committed
342
                return self.map_value_adrofs(llv)
343
            if isinstance(LLT, lltype.Primitive):
John Zhang's avatar
John Zhang committed
344
                return self.map_value_prim(llv)
345
346
            raise e

John Zhang's avatar
John Zhang committed
347
348
    def map_value_prim(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
349
350
351
        if isinstance(llv, TotalOrderSymbolic):
            llv = llv.compute_fn()
        elif isinstance(llv, CDefinedIntSymbolic):
352
353
354
355
356
357
358
            from rpython.rlib import objectmodel, jit
            if llv is objectmodel._translated_to_c:
                llv = 1     # faking it to make it work
            elif llv is objectmodel.malloc_zero_filled:
                llv = 1     # Mu NEW zeros memory
            elif llv is jit._we_are_jitted:
                llv = 0     # this is AoT, not jitted
John Zhang's avatar
John Zhang committed
359
360
            elif 'FinalizerQueue TAG' in llv.expr:  # rgc.py:515
                llv = 0
361
362
363
            else:
                raise NotImplementedError("Unanticipated %s" % llv)

364
365
366
367
368
369
370
371
        elif isinstance(llv, (str, unicode)):
            assert len(llv) == 1  # char
            llv = ord(llv)
        elif isinstance(llv, rffi.CConstant):
            from pypy.module._minimal_curses.fficurses import ERR, OK
            if llv in (ERR, OK):
                llv = -1 if llv is ERR else 0
            else:
372
                raise NotImplementedError("Unanticipted %s" % llv)
373
374
375
        elif isinstance(llv, llmemory.fakeaddress):
            assert not llv  # must be NULL
            return MuT._null()
376

377
        return MuT._val_type(llv)
378

John Zhang's avatar
John Zhang committed
379
380
    def map_value_arrfix(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
381
382
        arr = mutype._muarray(MuT)
        for i in range(llv.getlength()):
John Zhang's avatar
John Zhang committed
383
            arr[i] = self.map_value(llv.getitem(i))
384
385
        return arr

John Zhang's avatar
John Zhang committed
386
    def map_value_stt(self, llv, building=False):
387
388
389
        LLT = lltype.typeOf(llv)
        topstt = llv._normalizedcontainer()
        if building:
John Zhang's avatar
John Zhang committed
390
            MuT = self.map_type(LLT)
391
            self.resolve_ptr_types()
392
393
394
            stt = mutype._mustruct(MuT)
            self._val_cache[(LLT, llv)] = stt

John Zhang's avatar
John Zhang committed
395
            gcidfld, gcidfld_T = self.GC_IDHASH_FIELD
396
397
398

            if len(llv._TYPE._names) != 0:  # origional value struct is non-empty
                for fld in filter(lambda n: n != gcidfld, MuT._names):
John Zhang's avatar
John Zhang committed
399
                    setattr(stt, fld, self.map_value(getattr(llv, fld), building=True))
400
401
402

            if hasattr(stt, gcidfld) and hasattr(topstt, '_hash_cache_'):
                _idhash = topstt._hash_cache_
403
                setattr(stt, gcidfld, gcidfld_T._val_type(_idhash))
404
405
406
407
408
409

            llprnt = llv._parentstructure()
            llprnt_t = lltype.typeOf(llprnt)
            if llprnt and isinstance(llprnt_t, lltype.Struct):
                key = (llprnt_t, llprnt)
                assert key in self._val_cache
John Zhang's avatar
John Zhang committed
410
                stt._setparentstructure(self._val_cache[key], llv._parent_index)
411
412
        else:
            if LLT._is_varsize():
John Zhang's avatar
John Zhang committed
413
                return self.map_value_varstt(llv)
414

415
416
417
418
            MuT = self.map_type(LLT)
            if MuT is mutype.MU_VOID:   # empty struct, struct<>
                return None

419
420
            if topstt not in self._topstt_map:
                # build from top
John Zhang's avatar
John Zhang committed
421
                topstt_mu = self.map_value(topstt, building=True)
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
                self._topstt_map[topstt] = topstt_mu
            else:
                topstt_mu = self._topstt_map[topstt]

            # work out the depth of parent structure
            depth = 0
            prnt = llv
            while not prnt is topstt:
                depth += 1
                prnt = prnt._parentstructure()

            # traverse down according to the depth
            stt = topstt_mu
            while depth > 0:
                depth -= 1
                stt = stt.super

        return stt

John Zhang's avatar
John Zhang committed
441
    def map_value_varstt(self, llv):
442
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
443
        MuT = self.map_type(LLT)
444
        arr = getattr(llv, LLT._arrayfld)
445
        hyb = mutype._muhybrid(MuT, MuT.length._val_type(arr.getlength()))
446

John Zhang's avatar
John Zhang committed
447
        gcidfld, gcidfld_T = self.GC_IDHASH_FIELD
448

John Zhang's avatar
John Zhang committed
449
        for fld in filter(lambda n: n != gcidfld and n != 'length', MuT._names[:-1]):
John Zhang's avatar
John Zhang committed
450
            setattr(hyb, fld, self.map_value(getattr(llv, fld)))
451
452
453

        if hasattr(hyb, gcidfld) and hasattr(llv, '_hash_cache_'):
            _idhash = llv._hash_cache_
454
            setattr(hyb, gcidfld, gcidfld_T._val_type(_idhash))
455
456
457

        _memarr = getattr(hyb, MuT._varfld)
        for i in range(arr.getlength()):
John Zhang's avatar
John Zhang committed
458
            _memarr[i] = self.map_value(arr.getitem(i))
459

John Zhang's avatar
John Zhang committed
460
        if hasattr(hyb, 'length'):
John Zhang's avatar
John Zhang committed
461
            hyb.length = self.map_value(arr.getlength())
462
463
        return hyb

John Zhang's avatar
John Zhang committed
464
    def map_value_arr(self, llv):
465
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
466
        MuT = self.map_type(LLT)
467

John Zhang's avatar
John Zhang committed
468
        if llv._TYPE.OF == lltype.Void:
469
            stt = mutype._mustruct(MuT)
John Zhang's avatar
John Zhang committed
470
            stt.length = self.map_value(llv.getlength())
471
472
            return stt

John Zhang's avatar
John Zhang committed
473
        hyb = mutype._muhybrid(MuT, self.map_value(llv.getlength()))
474

475
476
477
        if 'length' in MuT._names:
            hyb.length = mutype.mu_int64(llv.getlength())

478
        _memarr = getattr(hyb, MuT._varfld)
479
        for i in range(hyb.length):
John Zhang's avatar
John Zhang committed
480
            _memarr[i] = self.map_value(llv.getitem(i))
481
482
483

        return hyb

John Zhang's avatar
John Zhang committed
484
    def map_value_ptr(self, llv):
485
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
486
        MuT = self.map_type(LLT)
487
488

        if llv._obj0 is None:
489
            return MuT._null()
490
491

        if isinstance(LLT.TO, lltype.FuncType):
John Zhang's avatar
John Zhang committed
492
            return self.map_value_funcptr(llv)
493

494
        ref = MuT._null()     # set object later
495

John Zhang's avatar
John Zhang committed
496
        self._pending_ptr_values.append((llv._obj, ref))
497
498
        return ref

499
500
501
502
503
    def map_value_iptr(self, llv):
        parent = self.map_value(llv._parent._as_ptr())
        MuT = self.map_type(lltype.typeOf(llv))
        return mutype._muiref(MuT, parent, llv._offsets)

John Zhang's avatar
John Zhang committed
504
505
506
507
    def resolve_ptr_values(self):
        while len(self._pending_ptr_values) > 0:
            llv, ref = self._pending_ptr_values.pop()
            obj = self.map_value(llv)
John Zhang's avatar
John Zhang committed
508
509
            if isinstance(ref, mutype._muref):
                ref._obj = obj  # directly set _obj in _muref
John Zhang's avatar
John Zhang committed
510
511
            elif isinstance(ref, mutype._muweakref):
                ref._obj = weakref.ref(obj)
John Zhang's avatar
John Zhang committed
512
513
            else:
                ref._store(obj) # otherwise (iref, uptr) call _store
514

John Zhang's avatar
John Zhang committed
515
    def map_value_funcptr(self, llv):
516
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
517
        MuT = self.map_type(LLT)
518
519
520
521
522
523
524
525
526
527
        fnc = llv._obj
        graph = getattr(fnc, 'graph', None)
        if graph:
            return mutype._mufuncref(MuT, graph=graph,
                                     _name=getattr(fnc, '_name', ''))
        else:
            # external functions
            Sig = MuT.Sig
            MuT = mutype.MuUFuncPtr(Sig)
            c_name = fnc._name
John Zhang's avatar
John Zhang committed
528
            return mutype._muufuncptr(MuT, _name=c_name, eci=fnc.compilation_info, _llfnctype=LLT.TO)
529

John Zhang's avatar
John Zhang committed
530
    def map_value_adrofs(self, llv):
531
532
533
534
535
536
537
        def rec(llv):
            if isinstance(llv, llmemory.CompositeOffset):
                ofs = 0
                for llv2 in llv.offsets:
                    ofs += rec(llv2)
                return ofs
            elif isinstance(llv, llmemory.ItemOffset):
John Zhang's avatar
John Zhang committed
538
                MuT = mutype.MuArray(self.map_type(llv.TYPE), llv.repeat)
539
540
                return layout.mu_offsetOf(MuT, llv.repeat)
            elif isinstance(llv, llmemory.FieldOffset):
John Zhang's avatar
John Zhang committed
541
                MuT = self.map_type(llv.TYPE)
542
543
544
545
546
547
                if isinstance(MuT, mutype.MuHybrid) and \
                                llv.fldname == MuT._varfld and len(MuT._names) > 1:
                    # get the offset of the 'length' field instead of variable part
                    return layout.mu_offsetOf(MuT, MuT._names[-2])
                return layout.mu_offsetOf(MuT, llv.fldname)
            elif isinstance(llv, llmemory.ArrayItemsOffset):
John Zhang's avatar
John Zhang committed
548
549
                MuT = self.map_type(llv.TYPE)
                _ofs = 8 if self.GC_IDHASH_FIELD[0] in MuT._names else 0  # __gc_idhash field
550
551
552
                if llv.TYPE._hints.get("nolength", False):
                    return _ofs
                return _ofs + 8  # sizeof(i64)
553
554
555
            elif isinstance(llv, llmemory.ArrayLengthOffset):
                MuT = self.map_type(llv.TYPE)
                return layout.mu_offsetOf(MuT, 'length')
556
557
            else:
                raise AssertionError("Value {:r} of type {:r} shouldn't appear.".format(llv, type(llv)))
John Zhang's avatar
John Zhang committed
558
        MuT = self.map_type(lltype.typeOf(llv))
559
        return MuT._val_type(rec(llv))
560

John Zhang's avatar
John Zhang committed
561
    def map_value_opq(self, llv):
John Zhang's avatar
John Zhang committed
562
        if llv._TYPE == lltype.RuntimeTypeInfo:
563
564
            # RuntimeTypeInfo is not used, translate to NULL
            return None
565
566
567

        if hasattr(llv, 'container'):
            container = llv._normalizedcontainer()
John Zhang's avatar
John Zhang committed
568
            muv = self.map_value(container)
569
570
571
572
            # log.ll2mu_val("%(llv)r really is %(muv)r" % locals())
            return muv

        muv = mutype.mu_int64(randint(0, 0xffffffff))  # randomise it.
573
        # log.ll2mu_val("WARNING: specialising '%r' to '%r' of type '%s'." % (llv, muv, muv._TYPE))
574
575
        return muv

John Zhang's avatar
John Zhang committed
576
577
    def map_value_wref(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
578
        stt = mutype._mustruct(MuT)
John Zhang's avatar
John Zhang committed
579
580
581
582
583
        llptr = llv._dereference()
        wref = mutype.MU_WEAKREF_VOID._null()
        if llptr:
            self._pending_ptr_values.append((llptr._obj, wref))
        setattr(stt, 'wref', wref)
584
        return stt
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

    # -----------------------------------------------------------------------------
    def mapped_const(self, llv, LLT=None):
        if LLT is None:
            try:
                LLT = lltype.typeOf(llv)
            except TypeError:
                LLT = lltype.Void
        MuT = self.map_type(LLT)
        muv = self.map_value(llv) if LLT != lltype.Void else llv
        c = Constant(muv, MuT)
        return c

    def map_op(self, llop):
        """
        May RTyped operations to Mu operations.
        NOTE: the name of the original operation is changed.

        :param llop: SpaceOperation
        :return: [SpaceOperation]
        """
John Zhang's avatar
John Zhang committed
606
        if hasattr(self, 'map_op_' + llop.opname):
607
608
            return getattr(self, 'map_op_' + llop.opname)(llop)

John Zhang's avatar
John Zhang committed
609
610
611
612
613
614
615
        elif llop.opname in _binop_map:   # a binop
            if any(cmpop in llop.opname for cmpop in 'lt le eq ne ge gt'.split(' ')):
                return self._map_cmpop(llop)
            else:
                return self._map_binop(llop)
        elif llop.opname in _prim_castop_map:  # a convop
            return self._map_convop(llop)
John Zhang's avatar
John Zhang committed
616

John Zhang's avatar
John Zhang committed
617
        else:
618
619
620
621
622
623
624
625
626
627
            raise NotImplementedError("Has not implemented specialisation for operation '%s'" % llop)

    def dest_clause(self, blk, args):
        """ Destination clause is a Link """
        return Link(args, blk)

    def exc_clause(self, dst_nor, dst_exc):
        """ Exception clause is a tuple """
        return dst_nor, dst_exc

628
629
630
631
632
633
634
635
636
637
    def _same_as_false(self, llop):
        llop.__init__('same_as', [self.mapped_const(False)], llop.result)
        return [llop]

    def _same_as_true(self, llop):
        llop.__init__('same_as', [self.mapped_const(True)], llop.result)
        return [llop]

    def _rename_to_same_as(self, llop):
        llop.opname = 'same_as'
John Zhang's avatar
John Zhang committed
638
        return [llop]
639

640
641
    # ----------------
    # call ops
642
643
644
645
646
647
648
649
650
651
652
653
    def _prepare_call_args(self, args, Sig):
        ops = []
        call_args = []
        for (a, ARG) in zip(args, Sig.ARGS):
            if a.concretetype == ARG:
                call_args.append(a)
            else:
                a_cast = varof(ARG)
                ops.extend(self.map_op_force_cast(SpaceOperation('force_cast', [a], a_cast)))
                call_args.append(a_cast)
        return call_args, ops

654
655
    def map_op_direct_call(self, llop):
        fr = llop.args[0].value
656
657
658
659
        args, ops = self._prepare_call_args(llop.args[1:], mutype.mutypeOf(fr).Sig)
        mtd = self.gen_mu_ccall if isinstance(fr, mutype._muufuncptr) else self.gen_mu_call
        ops.append(mtd(llop.args[0], args, llop.result))
        return ops
660
661
662
663

    def map_op_indirect_call(self, llop):
        last = llop.args[-1]
        if isinstance(last, Constant) and isinstance(last.value, list):
John Zhang's avatar
John Zhang committed
664
            args = llop.args[1:-1]
665
        else:
John Zhang's avatar
John Zhang committed
666
            args = llop.args[1:]
667
668
669
        call_args, ops = self._prepare_call_args(args, llop.args[0].concretetype.Sig)
        ops.append(self.gen_mu_call(llop.args[0], call_args, llop.result))
        return ops
670
671
672
673
674

    # ----------------
    # primitive ops
    def map_op_bool_not(self, llop):
        ops = []
John Zhang's avatar
John Zhang committed
675
        if llop.args[0].concretetype is mutype.MU_INT1:
676
            ops.append(self.gen_mu_convop('ZEXT', mutype.MU_INT8, llop.args[0]))
677
            v = ops[-1].result
678
679
        else:
            v = llop.args[0]
680
        ops.append(self.gen_mu_binop('XOR', v, self.mapped_const(True), llop.result))
681
682
683
        return ops

    def map_op_int_is_true(self, llop):
684
685
686
687
688
        # x != 0
        MuT = llop.args[0].concretetype
        llop.__init__('int_ne', [llop.args[0], Constant(MuT._val_type(0), MuT)], llop.result)
        return self.map_op(llop)

John Zhang's avatar
John Zhang committed
689
690
691
692
    map_op_uint_is_true = map_op_int_is_true
    map_op_llong_is_true = map_op_int_is_true
    map_op_ullong_is_true = map_op_int_is_true
    map_op_lllong_is_true = map_op_int_is_true
693
694
695

    def map_op_int_neg(self, llop):
        MuT = llop.args[0].concretetype
John Zhang's avatar
John Zhang committed
696
        llop.__init__('int_sub', [
697
698
699
700
            Constant(MuT._val_type(0), MuT),
            llop.args[0],
        ],
                                llop.result)
John Zhang's avatar
John Zhang committed
701
702
703
704
        return self.map_op(llop)

    map_op_llong_neg = map_op_int_neg
    map_op_lllong_neg = map_op_int_neg
705
706
707
708

    def map_op_int_abs(self, llop):
        ops = []
        x = llop.args[0]
John Zhang's avatar
John Zhang committed
709
        MuT = x.concretetype
John Zhang's avatar
John Zhang committed
710
        # -x = 0 - x
711
        neg_x = varof(x.concretetype, 'neg_x')
712
713
        op_neg = SpaceOperation('int_neg', [x], neg_x)
        ops.extend(self.map_op(op_neg))
John Zhang's avatar
John Zhang committed
714
        # x > 0 ?
715
        cmp_res = varof(mutype.MU_INT1, 'cmp_res')
716
        ops.append(self.gen_mu_cmpop('SGT', x, Constant(MuT._val_type(0), MuT), cmp_res))
John Zhang's avatar
John Zhang committed
717
        # True -> x, False -> -x
718
        ops.append(self.gen_mu_select(cmp_res, x, neg_x, llop.result))
719
        return ops
John Zhang's avatar
John Zhang committed
720
721
722
723
724
725
726
727
728
729

    map_op_llong_abs = map_op_int_abs
    map_op_lllong_abs = map_op_int_abs

    def map_op_int_invert(self, llop):
        # 2's complement
        # x' = (-x) - 1
        ops = []
        x = llop.args[0]

730
        neg_x = varof(x.concretetype, 'neg_x')
John Zhang's avatar
John Zhang committed
731
732
        op_neg = SpaceOperation('int_neg', [x], neg_x)
        ops.extend(self.map_op(op_neg))
John Zhang's avatar
John Zhang committed
733
734
        op_sub = SpaceOperation('int_sub', [neg_x, Constant(x.concretetype._val_type(1), x.concretetype)], llop.result)
        ops.extend(self.map_op(op_sub))
735
        return ops
John Zhang's avatar
John Zhang committed
736
737
738
739
740
741
742
743

    map_op_uint_invert = map_op_int_invert
    map_op_llong_invert = map_op_int_invert
    map_op_ullong_invert = map_op_int_invert
    map_op_lllong_invert = map_op_int_invert

    def map_op_int_between(self, llop):
        muops = []
744
745
        ge_res = varof(mutype.MU_INT8, 'ge_res')
        lt_res = varof(mutype.MU_INT8, 'lt_res')
John Zhang's avatar
John Zhang committed
746
747
748
749
        op_ge = SpaceOperation('int_ge', [llop.args[1], llop.args[0]], ge_res)
        muops.extend(self.map_op(op_ge))
        op_lt = SpaceOperation('int_lt', [llop.args[1], llop.args[2]], lt_res)
        muops.extend(self.map_op(op_lt))
John Zhang's avatar
John Zhang committed
750
        llop.__init__('int_and', [ge_res, lt_res], llop.result)
John Zhang's avatar
John Zhang committed
751
752
753
754
755
756
757
758
        muops.extend(self.map_op(llop))
        return muops

    def map_op_int_force_ge_zero(self, llop):
        muops = []
        a = llop.args[0]
        MuT = a.concretetype
        zero = Constant(MuT._val_type(0), MuT)
759
        lt_zero = varof(mutype.MU_INT1, 'lt_zero')
760
761
        muops.append(self.gen_mu_cmpop('SLT', a, zero, lt_zero))
        muops.append(self.gen_mu_select(lt_zero, zero, a, llop.result))
762
        return muops
John Zhang's avatar
John Zhang committed
763
764

    def map_op_int_add_ovf(self, llop):
765
        flag_v = varof(mutype.MU_INT1, 'ovf_V')
766
        flag = 'V'
767
        return [self.gen_mu_binop('ADD', llop.args[0], llop.args[1], llop.result, flag, [flag_v])]
John Zhang's avatar
John Zhang committed
768
769
770
771

    map_op_int_add_nonneg_ovf = map_op_int_add_ovf

    def map_op_int_sub_ovf(self, llop):
772
        flag_v = varof(mutype.MU_INT1, 'ovf_V')
773
        flag = 'V'
774
        return [self.gen_mu_binop('SUB', llop.args[0], llop.args[1], llop.result, flag, [flag_v])]
John Zhang's avatar
John Zhang committed
775
776

    def map_op_int_mul_ovf(self, llop):
777
        flag_v = varof(mutype.MU_INT1, 'ovf_V')
778
        flag = 'V'
779
        return [self.gen_mu_binop('MUL', llop.args[0], llop.args[1], llop.result, flag, [flag_v])]
John Zhang's avatar
John Zhang committed
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
    def map_op_float_is_true(self, llop):
        # x != 0
        MuT = llop.args[0].concretetype
        llop.__init__('float_ne', [llop.args[0], Constant(MuT._val_type(0.0), MuT)], llop.result)
        return self.map_op(llop)

    def map_op_float_neg(self, llop):
        MuT = llop.args[0].concretetype
        llop.__init__('float_sub', [
            Constant(MuT._val_type(0.0), MuT),
            llop.args[0],
        ],
                      llop.result)
        return self.map_op(llop)

    def map_op_float_abs(self, llop):
        ops = []
        x = llop.args[0]
        MuT = x.concretetype
        # -x = 0 - x
        neg_x = varof(x.concretetype, 'neg_x')
        op_neg = SpaceOperation('float_neg', [x], neg_x)
        ops.extend(self.map_op(op_neg))
        # x > 0 ?
        cmp_res = varof(mutype.MU_INT1, 'cmp_res')
        ops.append(self.gen_mu_cmpop('FOGT', x, Constant(MuT._val_type(0.0), MuT), cmp_res))
        # True -> x, False -> -x
        ops.append(self.gen_mu_select(cmp_res, x, neg_x, llop.result))
        return ops

John Zhang's avatar
John Zhang committed
811
    def _map_binop(self, llop):
812
813
814
815
816
817
818
819
820
        optr = _binop_map[llop.opname]
        if optr in ('SHL', 'LSHR', 'ASHR') and llop.args[1].concretetype != llop.args[0].concretetype:
            # type mismatch, force_cast the second one
            res = varof(llop.args[0].concretetype)
            ops = self.map_op(SpaceOperation('force_cast', [llop.args[1]], res))
            ops.append(self.gen_mu_binop(optr, llop.args[0], res, llop.result))
        else:
            ops = [self.gen_mu_binop(optr, llop.args[0], llop.args[1], llop.result)]
        return ops
John Zhang's avatar
John Zhang committed
821
822
823

    def _map_cmpop(self, llop):
        muops = []
824
        cmpres = varof(mutype.MU_INT1, 'cmpres')
825
826
        muops.append(self.gen_mu_cmpop(_binop_map[llop.opname], llop.args[0], llop.args[1], cmpres))
        muops.append(self.gen_mu_convop('ZEXT', mutype.MU_INT8, cmpres, llop.result))
John Zhang's avatar
John Zhang committed
827
828
        return muops

John Zhang's avatar
John Zhang committed
829
    def _map_convop(self, llop):
830
        return [self.gen_mu_convop(_prim_castop_map[llop.opname],
831
                                    llop.result.concretetype, llop.args[0], llop.result)]
John Zhang's avatar
John Zhang committed
832

833
834
835
836
    map_op_cast_int_to_uint = _rename_to_same_as
    map_op_cast_uint_to_int = _rename_to_same_as
    map_op_cast_int_to_unichar = _rename_to_same_as

John Zhang's avatar
John Zhang committed
837
838
839
840
841
842
    # ----------------
    # memory and pointer ops
    def map_op_malloc(self, llop):
        flavor = llop.args[-1].value['flavor']
        if flavor == 'gc':
            assert isinstance(llop.result.concretetype, mutype.MuRef)
843
            return [self.gen_mu_new(llop.args[0].value, llop.result)]
John Zhang's avatar
John Zhang committed
844
845
        else:
            assert isinstance(llop.result.concretetype, mutype.MuUPtr)
846
847
848
            sz = layout.mu_sizeOf(llop.args[0].value)
            llop.__init__('raw_malloc', [Constant(mutype.mu_int64(sz), mutype.MU_INT64)], llop.result)
            return self.map_op(llop)
John Zhang's avatar
John Zhang committed
849
850
851
852

    def map_op_malloc_varsize(self, llop):
        ops = []
        MuT_c, hints_c, n_c = llop.args
853
        MuT = MuT_c.value
John Zhang's avatar
John Zhang committed
854
        flavor = hints_c.value['flavor']
855
856
857
858
859
860
861

        if isinstance(MuT, mutype.MuStruct):
            if isinstance(n_c, Constant):
                assert n_c.value == 0
            llop.__init__('malloc', [MuT_c, hints_c], llop.result)
            return self.map_op(llop)

John Zhang's avatar
John Zhang committed
862
863
        if flavor == 'gc':
            assert isinstance(llop.result.concretetype, mutype.MuRef)
864
            ops.append(self.gen_mu_newhybrid(MuT, n_c, llop.result))
John Zhang's avatar
John Zhang committed
865
866
        else:
            assert isinstance(llop.result.concretetype, mutype.MuUPtr)
867
868
869
870
871
            fix = layout.mu_hybsizeOf(MuT, 0)
            itm = layout.mu_hybsizeOf(MuT, 1) - fix

            # sz = fix + itm * n
            v = varof(mutype.MU_INT64)
John Zhang's avatar
John Zhang committed
872
            ops.extend(self.map_op(SpaceOperation('int_mul', [Constant(mutype.mu_int64(itm), mutype.MU_INT64), n_c], v)))
873
            sz = varof(mutype.MU_INT64, 'sz')
John Zhang's avatar
John Zhang committed
874
            ops.extend(self.map_op(SpaceOperation('int_add', [Constant(mutype.mu_int64(fix), mutype.MU_INT64), v], sz)))
875
            ops.extend(self.map_op(SpaceOperation('raw_malloc', [sz], llop.result)))
876

John Zhang's avatar
John Zhang committed
877
878
879
880
        if 'length' in MuT._names:
            ops.extend(self.map_op(SpaceOperation('setfield', [
                llop.result, Constant('length', mutype.MU_VOID), n_c
            ],
881
                                                  varof(mutype.MU_VOID, 'dummy'))))
John Zhang's avatar
John Zhang committed
882
883
884
885
886
887
888

        return ops

    def _getfieldiref(self, var, fldname_c):
        ops = []
        MuT = var.concretetype
        fldname = fldname_c.value
889
        cls = mutype.MuUPtr if isinstance(MuT, mutype.MuUPtr) else mutype.MuIRef
John Zhang's avatar
John Zhang committed
890
        if isinstance(MuT, mutype.MuRef):
891
            iref = varof(cls(MuT.TO), 'ir%s' % var.name)
892
            ops.append(self.gen_mu_getiref(var, iref))
John Zhang's avatar
John Zhang committed
893
894
        else:
            iref = var
John Zhang's avatar
John Zhang committed
895
896
897

        assert isinstance(MuT.TO, (mutype.MuStruct, mutype.MuHybrid))
        idx = MuT.TO._index_of(fldname)     # NOTE: may throw AttributeError
898
        iref_fld = varof(cls(getattr(MuT.TO, fldname)), 'irf%s_%s' % (var.name, fldname))
899
        ops.append(self.gen_mu_getfieldiref(iref, fldname, iref_fld))
John Zhang's avatar
John Zhang committed
900
901
902
903
904
905
906
        return iref_fld, ops

    def map_op_getfield(self, llop):
        var, fldname_c = llop.args
        try:
            iref_fld, ops = self._getfieldiref(var, fldname_c)
        except AttributeError:
907
            # log.error("Field '%s' not found in type '%s'; ignoring %s." % (fldname_c.value, var.concretetype.TO, llop))
908
            return []
John Zhang's avatar
John Zhang committed
909

910
        ops.append(self.gen_mu_load(iref_fld, llop.result))
John Zhang's avatar
John Zhang committed
911
912
913
914
915
916
917
        return ops

    def map_op_setfield(self, llop):
        var, fldname_c, val_c = llop.args
        try:
            iref_fld, ops = self._getfieldiref(var, fldname_c)
        except AttributeError:
918
            # log.error("Field '%s' not found in type '%s'; ignoring %s." % (fldname_c.value, var.concretetype.TO, llop))
919
920
            return []

921
        ops.append(self.gen_mu_store(iref_fld, val_c, llop.result))
John Zhang's avatar
John Zhang committed
922
923
        return ops

John Zhang's avatar
John Zhang committed
924
925
    def map_op_getsubstruct(self, llop):
        var, fldname_c = llop.args
926
927
928
929
930
931
932
933
934
        if isinstance(var.concretetype.TO, mutype.MuHybrid) and fldname_c.value == var.concretetype.TO._varfld:
            RES_T = llop.result.concretetype.TO
            assert isinstance(RES_T, mutype.MuHybrid)
            if hasattr(RES_T, 'length'):
                iref_fld, ops = self._getfieldiref(var, Constant('length'))     # get the length field instead
                ops.extend(self.map_op(SpaceOperation('cast_pointer',           # cast to correct type
                                                      [Constant(llop.result.concretetype), iref_fld], llop.result)))
            else:
                iref_fld, ops = self._getinterioriref(var, [fldname_c])
935
        else:
936
937
938
939
940
941
942
            try:
                iref_fld, ops = self._getfieldiref(var, fldname_c)
            except AttributeError:
                # log.error("Field '%s' not found in type '%s'; ignoring %s." % (fldname_c.value, var.concretetype.TO, llop))
                return []

        ops[-1].result = llop.result
John Zhang's avatar
John Zhang committed
943
944
945
946
947
        return ops

    def _getarrayitemiref(self, var, idx_vc):
        ops = []
        MuT = var.concretetype
948
        cls = mutype.MuUPtr if isinstance(MuT, mutype.MuUPtr) else mutype.MuIRef
John Zhang's avatar
John Zhang committed
949
        if isinstance(MuT, mutype.MuRef):
950
            iref = varof(cls(MuT.TO), 'ir%s' % var.name)
951
            ops.append(self.gen_mu_getiref(var, iref))
John Zhang's avatar
John Zhang committed
952
953
954
955
        else:
            iref = var

        if isinstance(MuT.TO, mutype.MuHybrid):
956
            iref_itm0 = varof(cls(MuT.TO._vartype.OF), 'ira%s' % var.name)
957
            ops.append(self.gen_mu_getvarpartiref(iref, iref_itm0))
John Zhang's avatar
John Zhang committed
958
959
        else:
            assert isinstance(MuT.TO, mutype.MuArray)
960
            iref_itm0 = varof(cls(MuT.TO.OF), 'ira%s' % var.name)
961
            ops.extend(self.map_op(SpaceOperation('cast_pointer', [iref], iref_itm0)))
John Zhang's avatar
John Zhang committed
962

963
        iref_itm = varof(cls(iref_itm0.concretetype.TO), 'ir%s_itm' % var.name)
964
        ops.append(self.gen_mu_shiftiref(iref_itm0, idx_vc, iref_itm))
John Zhang's avatar
John Zhang committed
965
966
967
968
969
        return iref_itm, ops

    def map_op_getarrayitem(self, llop):
        var, idx_vc = llop.args
        iref_itm, ops = self._getarrayitemiref(var, idx_vc)
970
        ops.append(self.gen_mu_load(iref_itm, llop.result))
John Zhang's avatar
John Zhang committed
971
972
973
        return ops

    def map_op_setarrayitem(self, llop):