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

ll2mu.py 78.9 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

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
    def get_typedescr_str(self, MuT):  # JIT Mu back-end support
        descr_dict = {
            mutype.MuRef: 'r',
            mutype.MuUPtr: 'p',
            mutype.MuFuncRef: 'r',      # assuming function ref/uptr has same size as ref/uptr
            mutype.MuUFuncPtr: 'p',
            mutype.MU_INT8: 'b',
            mutype.MU_INT16: 's',
            mutype.MU_INT32: 'i',
            mutype.MU_INT64: 'l',
            mutype.MU_FLOAT: 'f',
            mutype.MU_DOUBLE: 'd'
        }
        if MuT.__class__ in descr_dict:
            return descr_dict[MuT.__class__]
        if MuT in descr_dict:
            return descr_dict[MuT]
        if isinstance(MuT, mutype.MuStruct):
            return '(%s)' % ''.join(map(self.get_typedescr_str, [getattr(MuT, fld) for fld in MuT._names]))
        if isinstance(MuT, mutype.MuHybrid):
            fix = ''.join(map(self.get_typedescr_str, [getattr(MuT, fld) for fld in MuT._names[:-1]]))
            var = self.get_typedescr_str(MuT._vartype.OF)
            return '{%(fix)s|%(var)s}' % locals()
        if isinstance(MuT, mutype.MuArray):
            return '[%d|%s]' % (MuT.length, self.get_typedescr_str(MuT.OF))

John Zhang's avatar
John Zhang committed
325
326
    # -----------------------------------------------------------------------------
    def map_value(self, llv, **kwargs):
327
        cache, v = (self._ptr_cache, llv._obj) \
328
            if isinstance(llv, lltype._abstract_ptr) \
329
330
331
332
333
334
335
            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
336
                muv = self.map_value_prim(llv)
337
338

            elif isinstance(llv, lltype._fixedsizearray):
John Zhang's avatar
John Zhang committed
339
                muv = self.map_value_arrfix(llv)
340
341

            elif isinstance(llv, lltype._struct):
John Zhang's avatar
John Zhang committed
342
                muv = self.map_value_stt(llv, **kwargs)
343
344

            elif isinstance(llv, lltype._array):
John Zhang's avatar
John Zhang committed
345
                muv = self.map_value_arr(llv)
346
347

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

350
351
352
            elif isinstance(llv, lltype._interior_ptr):
                muv = self.map_value_iptr(llv)

353
            elif isinstance(llv, lltype._opaque):
John Zhang's avatar
John Zhang committed
354
                muv = self.map_value_opq(llv)
355
356

            elif isinstance(llv, llmemory._wref):
John Zhang's avatar
John Zhang committed
357
                muv = self.map_value_wref(llv)
358
359
360
361
362
363
364
365
366
367

            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
368
                return self.map_value_adrofs(llv)
369
            if isinstance(LLT, lltype.Primitive):
John Zhang's avatar
John Zhang committed
370
                return self.map_value_prim(llv)
371
372
            raise e

John Zhang's avatar
John Zhang committed
373
374
    def map_value_prim(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
375
376
377
        if isinstance(llv, TotalOrderSymbolic):
            llv = llv.compute_fn()
        elif isinstance(llv, CDefinedIntSymbolic):
378
379
380
381
382
383
384
            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
385
386
            elif 'FinalizerQueue TAG' in llv.expr:  # rgc.py:515
                llv = 0
387
388
389
            else:
                raise NotImplementedError("Unanticipated %s" % llv)

390
391
392
393
394
395
396
397
        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:
398
                raise NotImplementedError("Unanticipted %s" % llv)
399
400
401
        elif isinstance(llv, llmemory.fakeaddress):
            assert not llv  # must be NULL
            return MuT._null()
402

403
        return MuT._val_type(llv)
404

John Zhang's avatar
John Zhang committed
405
406
    def map_value_arrfix(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
407
408
        arr = mutype._muarray(MuT)
        for i in range(llv.getlength()):
John Zhang's avatar
John Zhang committed
409
            arr[i] = self.map_value(llv.getitem(i))
410
411
        return arr

John Zhang's avatar
John Zhang committed
412
    def map_value_stt(self, llv, building=False):
413
414
415
        LLT = lltype.typeOf(llv)
        topstt = llv._normalizedcontainer()
        if building:
John Zhang's avatar
John Zhang committed
416
            MuT = self.map_type(LLT)
417
            self.resolve_ptr_types()
418
419
420
            stt = mutype._mustruct(MuT)
            self._val_cache[(LLT, llv)] = stt

John Zhang's avatar
John Zhang committed
421
            gcidfld, gcidfld_T = self.GC_IDHASH_FIELD
422
423
424

            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
425
                    setattr(stt, fld, self.map_value(getattr(llv, fld), building=True))
426
427
428

            if hasattr(stt, gcidfld) and hasattr(topstt, '_hash_cache_'):
                _idhash = topstt._hash_cache_
429
                setattr(stt, gcidfld, gcidfld_T._val_type(_idhash))
430
431
432
433
434
435

            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
436
                stt._setparentstructure(self._val_cache[key], llv._parent_index)
437
438
        else:
            if LLT._is_varsize():
John Zhang's avatar
John Zhang committed
439
                return self.map_value_varstt(llv)
440

441
442
443
444
            MuT = self.map_type(LLT)
            if MuT is mutype.MU_VOID:   # empty struct, struct<>
                return None

445
446
            if topstt not in self._topstt_map:
                # build from top
John Zhang's avatar
John Zhang committed
447
                topstt_mu = self.map_value(topstt, building=True)
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
                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
467
    def map_value_varstt(self, llv):
468
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
469
        MuT = self.map_type(LLT)
470
        arr = getattr(llv, LLT._arrayfld)
471
        hyb = mutype._muhybrid(MuT, MuT.length._val_type(arr.getlength()))
472

John Zhang's avatar
John Zhang committed
473
        gcidfld, gcidfld_T = self.GC_IDHASH_FIELD
474

John Zhang's avatar
John Zhang committed
475
        for fld in filter(lambda n: n != gcidfld and n != 'length', MuT._names[:-1]):
John Zhang's avatar
John Zhang committed
476
            setattr(hyb, fld, self.map_value(getattr(llv, fld)))
477
478
479

        if hasattr(hyb, gcidfld) and hasattr(llv, '_hash_cache_'):
            _idhash = llv._hash_cache_
480
            setattr(hyb, gcidfld, gcidfld_T._val_type(_idhash))
481
482
483

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

John Zhang's avatar
John Zhang committed
486
        if hasattr(hyb, 'length'):
John Zhang's avatar
John Zhang committed
487
            hyb.length = self.map_value(arr.getlength())
488
489
        return hyb

John Zhang's avatar
John Zhang committed
490
    def map_value_arr(self, llv):
491
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
492
        MuT = self.map_type(LLT)
493

John Zhang's avatar
John Zhang committed
494
        if llv._TYPE.OF == lltype.Void:
495
            stt = mutype._mustruct(MuT)
John Zhang's avatar
John Zhang committed
496
            stt.length = self.map_value(llv.getlength())
497
498
            return stt

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

501
502
503
        if 'length' in MuT._names:
            hyb.length = mutype.mu_int64(llv.getlength())

504
        _memarr = getattr(hyb, MuT._varfld)
505
        for i in range(hyb.length):
John Zhang's avatar
John Zhang committed
506
            _memarr[i] = self.map_value(llv.getitem(i))
507
508
509

        return hyb

John Zhang's avatar
John Zhang committed
510
    def map_value_ptr(self, llv):
511
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
512
        MuT = self.map_type(LLT)
513
514

        if llv._obj0 is None:
515
            return MuT._null()
516
517

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

520
        ref = MuT._null()     # set object later
521

John Zhang's avatar
John Zhang committed
522
        self._pending_ptr_values.append((llv._obj, ref))
523
524
        return ref

525
526
527
528
529
    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
530
531
532
533
    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
534
535
            if isinstance(ref, mutype._muref):
                ref._obj = obj  # directly set _obj in _muref
John Zhang's avatar
John Zhang committed
536
537
            elif isinstance(ref, mutype._muweakref):
                ref._obj = weakref.ref(obj)
John Zhang's avatar
John Zhang committed
538
539
            else:
                ref._store(obj) # otherwise (iref, uptr) call _store
540

John Zhang's avatar
John Zhang committed
541
    def map_value_funcptr(self, llv):
542
        LLT = lltype.typeOf(llv)
John Zhang's avatar
John Zhang committed
543
        MuT = self.map_type(LLT)
544
545
546
547
548
549
550
551
552
553
        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
554
            return mutype._muufuncptr(MuT, _name=c_name, eci=fnc.compilation_info, _llfnctype=LLT.TO)
555

John Zhang's avatar
John Zhang committed
556
    def map_value_adrofs(self, llv):
557
558
559
560
561
562
563
        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
564
                MuT = mutype.MuArray(self.map_type(llv.TYPE), llv.repeat)
565
566
                return layout.mu_offsetOf(MuT, llv.repeat)
            elif isinstance(llv, llmemory.FieldOffset):
John Zhang's avatar
John Zhang committed
567
                MuT = self.map_type(llv.TYPE)
568
569
570
571
572
573
                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
574
575
                MuT = self.map_type(llv.TYPE)
                _ofs = 8 if self.GC_IDHASH_FIELD[0] in MuT._names else 0  # __gc_idhash field
576
577
578
                if llv.TYPE._hints.get("nolength", False):
                    return _ofs
                return _ofs + 8  # sizeof(i64)
579
580
581
            elif isinstance(llv, llmemory.ArrayLengthOffset):
                MuT = self.map_type(llv.TYPE)
                return layout.mu_offsetOf(MuT, 'length')
582
583
            else:
                raise AssertionError("Value {:r} of type {:r} shouldn't appear.".format(llv, type(llv)))
John Zhang's avatar
John Zhang committed
584
        MuT = self.map_type(lltype.typeOf(llv))
585
        return MuT._val_type(rec(llv))
586

John Zhang's avatar
John Zhang committed
587
    def map_value_opq(self, llv):
John Zhang's avatar
John Zhang committed
588
        if llv._TYPE == lltype.RuntimeTypeInfo:
589
590
            # RuntimeTypeInfo is not used, translate to NULL
            return None
591
592
593

        if hasattr(llv, 'container'):
            container = llv._normalizedcontainer()
John Zhang's avatar
John Zhang committed
594
            muv = self.map_value(container)
595
596
597
598
            # log.ll2mu_val("%(llv)r really is %(muv)r" % locals())
            return muv

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

John Zhang's avatar
John Zhang committed
602
603
    def map_value_wref(self, llv):
        MuT = self.map_type(lltype.typeOf(llv))
604
        stt = mutype._mustruct(MuT)
John Zhang's avatar
John Zhang committed
605
606
607
608
609
        llptr = llv._dereference()
        wref = mutype.MU_WEAKREF_VOID._null()
        if llptr:
            self._pending_ptr_values.append((llptr._obj, wref))
        setattr(stt, 'wref', wref)
610
        return stt
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

    # -----------------------------------------------------------------------------
    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
632
        if hasattr(self, 'map_op_' + llop.opname):
633
634
            return getattr(self, 'map_op_' + llop.opname)(llop)

John Zhang's avatar
John Zhang committed
635
636
637
638
639
640
641
        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
642

John Zhang's avatar
John Zhang committed
643
        else:
644
645
646
647
648
649
650
651
652
653
            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

654
655
656
657
658
659
660
661
662
663
    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
664
        return [llop]
665

666
667
    # ----------------
    # call ops
668
669
670
671
672
673
674
675
676
677
678
679
    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

680
681
    def map_op_direct_call(self, llop):
        fr = llop.args[0].value
682
683
684
685
        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
686
687
688
689

    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
690
            args = llop.args[1:-1]
691
        else:
John Zhang's avatar
John Zhang committed
692
            args = llop.args[1:]
693
694
695
        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
696
697
698
699
700

    # ----------------
    # primitive ops
    def map_op_bool_not(self, llop):
        ops = []
John Zhang's avatar
John Zhang committed
701
        if llop.args[0].concretetype is mutype.MU_INT1:
702
            ops.append(self.gen_mu_convop('ZEXT', mutype.MU_INT8, llop.args[0]))
703
            v = ops[-1].result
704
705
        else:
            v = llop.args[0]
706
        ops.append(self.gen_mu_binop('XOR', v, self.mapped_const(True), llop.result))
707
708
709
        return ops

    def map_op_int_is_true(self, llop):
710
711
712
713
714
        # 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
715
716
717
718
    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
719
720
721

    def map_op_int_neg(self, llop):
        MuT = llop.args[0].concretetype
John Zhang's avatar
John Zhang committed
722
        llop.__init__('int_sub', [
723
724
725
726
            Constant(MuT._val_type(0), MuT),
            llop.args[0],
        ],
                                llop.result)
John Zhang's avatar
John Zhang committed
727
728
729
730
        return self.map_op(llop)

    map_op_llong_neg = map_op_int_neg
    map_op_lllong_neg = map_op_int_neg
731
732
733
734

    def map_op_int_abs(self, llop):
        ops = []
        x = llop.args[0]
John Zhang's avatar
John Zhang committed
735
        MuT = x.concretetype
John Zhang's avatar
John Zhang committed
736
        # -x = 0 - x
737
        neg_x = varof(x.concretetype, 'neg_x')
738
739
        op_neg = SpaceOperation('int_neg', [x], neg_x)
        ops.extend(self.map_op(op_neg))
John Zhang's avatar
John Zhang committed
740
        # x > 0 ?
741
        cmp_res = varof(mutype.MU_INT1, 'cmp_res')
742
        ops.append(self.gen_mu_cmpop('SGT', x, Constant(MuT._val_type(0), MuT), cmp_res))
John Zhang's avatar
John Zhang committed
743
        # True -> x, False -> -x
744
        ops.append(self.gen_mu_select(cmp_res, x, neg_x, llop.result))
745
        return ops
John Zhang's avatar
John Zhang committed
746
747
748
749
750
751
752
753
754
755

    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]

756
        neg_x = varof(x.concretetype, 'neg_x')
John Zhang's avatar
John Zhang committed
757
758
        op_neg = SpaceOperation('int_neg', [x], neg_x)
        ops.extend(self.map_op(op_neg))
John Zhang's avatar
John Zhang committed
759
760
        op_sub = SpaceOperation('int_sub', [neg_x, Constant(x.concretetype._val_type(1), x.concretetype)], llop.result)
        ops.extend(self.map_op(op_sub))
761
        return ops
John Zhang's avatar
John Zhang committed
762
763
764
765
766
767
768
769

    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 = []
770
771
        ge_res = varof(mutype.MU_INT8, 'ge_res')
        lt_res = varof(mutype.MU_INT8, 'lt_res')
John Zhang's avatar
John Zhang committed
772
773
774
775
        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
776
        llop.__init__('int_and', [ge_res, lt_res], llop.result)
John Zhang's avatar
John Zhang committed
777
778
779
780
781
782
783
784
        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)
785
        lt_zero = varof(mutype.MU_INT1, 'lt_zero')
786
787
        muops.append(self.gen_mu_cmpop('SLT', a, zero, lt_zero))
        muops.append(self.gen_mu_select(lt_zero, zero, a, llop.result))
788
        return muops
John Zhang's avatar
John Zhang committed
789
790

    def map_op_int_add_ovf(self, llop):
791
        flag_v = varof(mutype.MU_INT1, 'ovf_V')
792
        flag = 'V'
793
        return [self.gen_mu_binop('ADD', llop.args[0], llop.args[1], llop.result, flag, [flag_v])]
John Zhang's avatar
John Zhang committed
794
795
796
797

    map_op_int_add_nonneg_ovf = map_op_int_add_ovf

    def map_op_int_sub_ovf(self, llop):
798
        flag_v = varof(mutype.MU_INT1, 'ovf_V')
799
        flag = 'V'
800
        return [self.gen_mu_binop('SUB', llop.args[0], llop.args[1], llop.result, flag, [flag_v])]
John Zhang's avatar
John Zhang committed
801
802

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

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
    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
837
    def _map_binop(self, llop):
838
839
840
841
842
843
844
845
846
        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
847
848
849

    def _map_cmpop(self, llop):
        muops = []
850
        cmpres = varof(mutype.MU_INT1, 'cmpres')
851
852
        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
853
854
        return muops

John Zhang's avatar
John Zhang committed
855
    def _map_convop(self, llop):
856
        return [self.gen_mu_convop(_prim_castop_map[llop.opname],
857
                                    llop.result.concretetype, llop.args[0], llop.result)]
John Zhang's avatar
John Zhang committed
858

859
860
861
862
    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
863
864
865
866
867
868
    # ----------------
    # 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)
869
            return [self.gen_mu_new(llop.args[0].value, llop.result)]
John Zhang's avatar
John Zhang committed
870
871
        else:
            assert isinstance(llop.result.concretetype, mutype.MuUPtr)
872
873
874
            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
875
876
877
878

    def map_op_malloc_varsize(self, llop):
        ops = []
        MuT_c, hints_c, n_c = llop.args
879
        MuT = MuT_c.value
John Zhang's avatar
John Zhang committed
880
        flavor = hints_c.value['flavor']
881
882
883
884
885
886
887

        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
888
889
        if flavor == 'gc':
            assert isinstance(llop.result.concretetype, mutype.MuRef)
890
            ops.append(self.gen_mu_newhybrid(MuT, n_c, llop.result))
John Zhang's avatar
John Zhang committed
891
892
        else:
            assert isinstance(llop.result.concretetype, mutype.MuUPtr)
893
894
895
896
897
            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
898
            ops.extend(self.map_op(SpaceOperation('int_mul', [Constant(mutype.mu_int64(itm), mutype.MU_INT64), n_c], v)))
899
            sz = varof(mutype.MU_INT64, 'sz')
John Zhang's avatar
John Zhang committed
900
            ops.extend(self.map_op(SpaceOperation('int_add', [Constant(mutype.mu_int64(fix), mutype.MU_INT64), v], sz)))
901
            ops.extend(self.map_op(SpaceOperation('raw_malloc', [sz], llop.result)))
902

John Zhang's avatar
John Zhang committed
903
904
905
906
        if 'length' in MuT._names:
            ops.extend(self.map_op(SpaceOperation('setfield', [
                llop.result, Constant('length', mutype.MU_VOID), n_c
            ],
907
                                                  varof(mutype.MU_VOID, 'dummy'))))
John Zhang's avatar
John Zhang committed
908
909
910
911
912
913
914

        return ops

    def _getfieldiref(self, var, fldname_c):
        ops = []
        MuT = var.concretetype
        fldname = fldname_c.value
915
        cls = mutype.MuUPtr if isinstance(MuT, mutype.MuUPtr) else mutype.MuIRef
John Zhang's avatar
John Zhang committed
916
        if isinstance(MuT, mutype.MuRef):
917
            iref = varof(cls(MuT.TO), 'ir%s' % var.name)
918
            ops.append(self.gen_mu_getiref(var, iref))
John Zhang's avatar
John Zhang committed
919
920
        else:
            iref = var
John Zhang's avatar
John Zhang committed
921
922
923

        assert isinstance(MuT.TO, (mutype.MuStruct, mutype.MuHybrid))
        idx = MuT.TO._index_of(fldname)     # NOTE: may throw AttributeError
924
        iref_fld = varof(cls(getattr(MuT.TO, fldname)), 'irf%s_%s' % (var.name, fldname))
925
        ops.append(self.gen_mu_getfieldiref(iref, fldname, iref_fld))
John Zhang's avatar
John Zhang committed
926
927
928
929
930
931
932
        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:
933
            # log.error("Field '%s' not found in type '%s'; ignoring %s." % (fldname_c.value, var.concretetype.TO, llop))
934
            return []
John Zhang's avatar
John Zhang committed
935

936
        ops.append(self.gen_mu_load(iref_fld, llop.result))
John Zhang's avatar
John Zhang committed
937
938
939
940
941
942
943
        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:
944
            # log.error("Field '%s' not found in type '%s'; ignoring %s." % (fldname_c.value, var.concretetype.TO, llop))
945
946
            return []

947
        ops.append(self.gen_mu_store(iref_fld, val_c, llop.result))
John Zhang's avatar
John Zhang committed
948
949
        return ops

John Zhang's avatar
John Zhang committed
950
951
    def map_op_getsubstruct(self, llop):
        var, fldname_c = llop.args
952
953
954
955
956
957
958
959
960
        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])
961
        else:
962
963
964
965
966
967
968
            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
969
970
971
972
973
        return ops

    def _getarrayitemiref(self, var, idx_vc):
        ops = []
        MuT = var.concretetype
974
        cls = mutype.MuUPtr if isinstance(MuT, mutype.MuUPtr) else mutype.MuIRef
John Zhang's avatar
John Zhang committed
975
        if isinstance(MuT, mutype.MuRef):
976
            iref = varof(cls(MuT.TO), 'ir%s' % var.name)
977
            ops.append(self.gen_mu_getiref(var, iref))
John Zhang's avatar
John Zhang committed
978
979
980
981
        else:
            iref = var

        if isinstance(MuT.TO, mutype.MuHybrid):
982
            iref_itm0 = varof(cls(MuT.TO._vartype.OF), 'ira%s' % var.name)
983
            ops.append(self.gen_mu_getvarpartiref(iref, iref_itm0))
John Zhang's avatar
John Zhang committed
984
985
        else:
            assert isinstance(MuT.TO, mutype.MuArray)
986
            iref_itm0 = varof(cls(MuT.TO.OF), 'ira%s' % var.name)
987
            ops.extend(self.map_op(SpaceOperation('cast_pointer', [iref], iref_itm0)))
John Zhang's avatar
John Zhang committed