1
/**
2
 * Converts expressions to Intermediate Representation (IR) for the backend.
3
 *
4
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/e2ir.d, _e2ir.d)
8
 * Documentation: https://dlang.org/phobos/dmd_e2ir.html
9
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/e2ir.d
10
 */
11

12
module dmd.e2ir;
13

14
import core.stdc.stdio;
15
import core.stdc.stddef;
16
import core.stdc.string;
17
import core.stdc.time;
18

19
import dmd.root.array;
20
import dmd.root.ctfloat;
21
import dmd.root.rmem;
22
import dmd.root.rootobject;
23
import dmd.root.stringtable;
24

25
import dmd.aggregate;
26
import dmd.arraytypes;
27
import dmd.attrib;
28
import dmd.canthrow;
29
import dmd.ctfeexpr;
30
import dmd.dclass;
31
import dmd.declaration;
32
import dmd.denum;
33
import dmd.dmodule;
34
import dmd.dscope;
35
import dmd.dstruct;
36
import dmd.dsymbol;
37
import dmd.dtemplate;
38
import dmd.errors;
39
import dmd.expression;
40
import dmd.func;
41
import dmd.globals;
42
import dmd.glue;
43
import dmd.id;
44
import dmd.init;
45
import dmd.mtype;
46
import dmd.objc_glue;
47
import dmd.s2ir;
48
import dmd.sideeffect;
49
import dmd.statement;
50
import dmd.target;
51
import dmd.tocsym;
52
import dmd.toctype;
53
import dmd.toir;
54
import dmd.tokens;
55
import dmd.toobj;
56
import dmd.typinf;
57
import dmd.visitor;
58

59
import dmd.backend.cc;
60
import dmd.backend.cdef;
61
import dmd.backend.cgcv;
62
import dmd.backend.code;
63
import dmd.backend.code_x86;
64
import dmd.backend.cv4;
65
import dmd.backend.dt;
66
import dmd.backend.el;
67
import dmd.backend.global;
68
import dmd.backend.obj;
69
import dmd.backend.oper;
70
import dmd.backend.rtlsym;
71
import dmd.backend.ty;
72
import dmd.backend.type;
73

74
extern (C++):
75

76
alias Elems = Array!(elem *);
77

78
alias toSymbol = dmd.tocsym.toSymbol;
79
alias toSymbol = dmd.glue.toSymbol;
80

81
void* mem_malloc2(uint);
82

83

84 1
@property int REGSIZE() { return _tysize[TYnptr]; }
85

86
/* If variable var is a reference
87
 */
88
bool ISREF(Declaration var)
89
{
90 1
    if (var.isOut() || var.isRef())
91
    {
92 1
        return true;
93
    }
94

95 1
    return ISX64REF(var);
96
}
97

98
/* If variable var of type typ is a reference due to x64 calling conventions
99
 */
100
bool ISX64REF(Declaration var)
101
{
102 1
    if (var.isOut() || var.isRef())
103
    {
104 1
        return false;
105
    }
106

107 1
    if (var.isParameter())
108
    {
109 1
        if (config.exe == EX_WIN64)
110
        {
111 0
            return var.type.size(Loc.initial) > REGSIZE
112 0
                || (var.storage_class & STC.lazy_)
113 0
                || (var.type.isTypeStruct() && !var.type.isTypeStruct().sym.isPOD());
114
        }
115 1
        else if (!global.params.isWindows)
116
        {
117 1
            return !(var.storage_class & STC.lazy_) && var.type.isTypeStruct() && !var.type.isTypeStruct().sym.isPOD();
118
        }
119
    }
120

121 1
    return false;
122
}
123

124
/* If variable exp of type typ is a reference due to x64 calling conventions
125
 */
126
bool ISX64REF(IRState* irs, Expression exp)
127
{
128 1
    if (config.exe == EX_WIN64)
129
    {
130 0
        return exp.type.size(Loc.initial) > REGSIZE
131 0
            || (exp.type.isTypeStruct() && !exp.type.isTypeStruct().sym.isPOD());
132
    }
133 1
    else if (!irs.params.isWindows)
134
    {
135 1
        return exp.type.isTypeStruct() && !exp.type.isTypeStruct().sym.isPOD();
136
    }
137

138 0
    return false;
139
}
140

141
/******************************************
142
 * If argument to a function should use OPstrpar,
143
 * fix it so it does and return it.
144
 */
145
private elem *useOPstrpar(elem *e)
146
{
147 1
    tym_t ty = tybasic(e.Ety);
148 1
    if (ty == TYstruct || ty == TYarray)
149
    {
150 1
        e = el_una(OPstrpar, TYstruct, e);
151 1
        e.ET = e.EV.E1.ET;
152 1
        assert(e.ET);
153
    }
154 1
    return e;
155
}
156

157
/************************************
158
 * Call a function.
159
 */
160

161
private elem *callfunc(const ref Loc loc,
162
        IRState *irs,
163
        int directcall,         // 1: don't do virtual call
164
        Type tret,              // return type
165
        elem *ec,               // evaluates to function address
166
        Type ectype,            // original type of ec
167
        FuncDeclaration fd,     // if !=NULL, this is the function being called
168
        Type t,                 // TypeDelegate or TypeFunction for this function
169
        elem *ehidden,          // if !=null, this is the 'hidden' argument
170
        Expressions *arguments,
171
        elem *esel = null,      // selector for Objective-C methods (when not provided by fd)
172
        elem *ethis2 = null)    // multi-context array
173
{
174 1
    elem *ethis = null;
175 1
    elem *eside = null;
176 1
    elem *eresult = ehidden;
177

178
    version (none)
179
    {
180
        printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
181
            directcall, tret.toChars(), ec, fd);
182
        printf("ec: "); elem_print(ec);
183
        if (fd)
184
            printf("fd = '%s', vtblIndex = %d, isVirtual() = %d\n", fd.toChars(), fd.vtblIndex, fd.isVirtual());
185
        if (ehidden)
186
        {   printf("ehidden: "); elem_print(ehidden); }
187
    }
188

189 1
    t = t.toBasetype();
190 1
    TypeFunction tf = t.isTypeFunction();
191 1
    if (!tf)
192
    {
193 1
        assert(t.ty == Tdelegate);
194
        // A delegate consists of:
195
        //      { Object *this; Function *funcptr; }
196 1
        assert(!fd);
197 1
        tf = t.nextOf().isTypeFunction();
198 1
        assert(tf);
199 1
        ethis = ec;
200 1
        ec = el_same(&ethis);
201 1
        ethis = el_una(irs.params.is64bit ? OP128_64 : OP64_32, TYnptr, ethis); // get this
202 1
        ec = array_toPtr(t, ec);                // get funcptr
203 1
        ec = el_una(OPind, totym(tf), ec);
204
    }
205

206 1
    const ty = fd ? toSymbol(fd).Stype.Tty : ec.Ety;
207 1
    const left_to_right = tyrevfunc(ty);   // left-to-right parameter evaluation
208
                                           // (TYnpfunc, TYjfunc, TYfpfunc, TYf16func)
209 1
    elem* ep = null;
210 1
    const op = fd ? intrinsic_op(fd) : NotIntrinsic;
211 1
    if (arguments && arguments.dim)
212
    {
213 1
        if (op == OPvector)
214
        {
215 1
            Expression arg = (*arguments)[0];
216 1
            if (arg.op != TOK.int64)
217 1
                arg.error("simd operator must be an integer constant, not `%s`", arg.toChars());
218
        }
219

220
        /* Convert arguments[] to elems[] in left-to-right order
221
         */
222 1
        const n = arguments.dim;
223
        debug
224 1
            elem*[2] elems_array = void;
225
        else
226
            elem*[10] elems_array = void;
227
        import core.stdc.stdlib : malloc, free;
228 1
        auto pe = (n <= elems_array.length)
229 1
                  ? elems_array.ptr
230 1
                  : cast(elem**)Mem.check(malloc(arguments.dim * (elem*).sizeof));
231 1
        elem*[] elems = pe[0 .. n];
232

233
        /* Fill elems[] with arguments converted to elems
234
         */
235

236
        // j=1 if _arguments[] is first argument
237 1
        const int j = tf.isDstyleVariadic();
238

239 1
        foreach (const i, arg; *arguments)
240
        {
241 1
            elem *ea = toElem(arg, irs);
242

243
            //printf("\targ[%d]: %s\n", i, arg.toChars());
244

245 1
            if (i - j < tf.parameterList.length &&
246 1
                i >= j &&
247 1
                tf.parameterList[i - j].isReference())
248
            {
249
                /* `ref` and `out` parameters mean convert
250
                 * corresponding argument to a pointer
251
                 */
252 1
                elems[i] = addressElem(ea, arg.type.pointerTo());
253 1
                continue;
254
            }
255

256 1
            if (ISX64REF(irs, arg) && op == NotIntrinsic)
257
            {
258
                /* Copy to a temporary, and make the argument a pointer
259
                 * to that temporary.
260
                 */
261 1
                elems[i] = addressElem(ea, arg.type, true);
262 1
                continue;
263
            }
264

265 1
            if (config.exe == EX_WIN64 && tybasic(ea.Ety) == TYcfloat)
266
            {
267
                /* Treat a cfloat like it was a struct { float re,im; }
268
                 */
269 0
                ea.Ety = TYllong;
270
            }
271 1
            elems[i] = ea;
272
        }
273 1
        if (!left_to_right)
274
        {
275 1
            eside = fixArgumentEvaluationOrder(elems);
276
        }
277

278 1
        foreach (ref e; elems)
279
        {
280 1
            e = useOPstrpar(e);
281
        }
282

283 1
        if (!left_to_right)   // swap order if right-to-left
284 1
            reverse(elems);
285

286 1
        ep = el_params(cast(void**)elems.ptr, cast(int)n);
287

288 1
        if (elems.ptr != elems_array.ptr)
289 1
            free(elems.ptr);
290
    }
291

292 1
    objc.setupMethodSelector(fd, &esel);
293 1
    objc.setupEp(esel, &ep, left_to_right);
294

295 1
    const retmethod = retStyle(tf, fd && fd.needThis());
296 1
    if (retmethod == RET.stack)
297
    {
298 1
        if (!ehidden)
299
        {
300
            // Don't have one, so create one
301 1
            type *tc;
302

303 1
            Type tret2 = tf.next;
304 1
            if (tret2.toBasetype().ty == Tstruct ||
305 1
                tret2.toBasetype().ty == Tsarray)
306 1
                tc = Type_toCtype(tret2);
307
            else
308 0
                tc = type_fake(totym(tret2));
309 1
            Symbol *stmp = symbol_genauto(tc);
310 1
            ehidden = el_ptr(stmp);
311 1
            eresult = ehidden;
312
        }
313 1
        if (target.isPOSIX && tf.linkage != LINK.d)
314
        {
315
                // ehidden goes last on Linux/OSX C++
316
        }
317
        else
318
        {
319 1
            if (ep)
320
            {
321
                /* // BUG: implement
322
                if (left_to_right && type_mangle(tfunc) == mTYman_cpp)
323
                    ep = el_param(ehidden,ep);
324
                else
325
                */
326 1
                    ep = el_param(ep,ehidden);
327
            }
328
            else
329 1
                ep = ehidden;
330 1
            ehidden = null;
331
        }
332
    }
333

334 1
    if (fd && fd.isMemberLocal())
335
    {
336 1
        assert(op == NotIntrinsic);       // members should not be intrinsics
337

338 1
        AggregateDeclaration ad = fd.isThis();
339 1
        if (ad)
340
        {
341 1
            ethis = ec;
342 1
            if (ad.isStructDeclaration() && tybasic(ec.Ety) != TYnptr)
343
            {
344 1
                ethis = addressElem(ec, ectype);
345
            }
346 1
            if (ethis2)
347
            {
348 1
                ethis2 = setEthis2(loc, irs, fd, ethis2, &ethis, &eside);
349
            }
350 1
            if (el_sideeffect(ethis))
351
            {
352 1
                elem *ex = ethis;
353 1
                ethis = el_copytotmp(&ex);
354 1
                eside = el_combine(ex, eside);
355
            }
356
        }
357
        else
358
        {
359
            // Evaluate ec for side effects
360 1
            eside = el_combine(ec, eside);
361
        }
362 1
        Symbol *sfunc = toSymbol(fd);
363

364 1
        if (esel)
365
        {
366 0
            auto result = objc.setupMethodCall(fd, tf, directcall != 0, ec, ehidden, ethis);
367 0
            ec = result.ec;
368 0
            ethis = result.ethis;
369
        }
370 1
        else if (!fd.isVirtual() ||
371 1
            directcall ||               // BUG: fix
372 1
            fd.isFinalFunc()
373
           /* Future optimization: || (whole program analysis && not overridden)
374
            */
375
           )
376
        {
377
            // make static call
378 1
            ec = el_var(sfunc);
379
        }
380
        else
381
        {
382
            // make virtual call
383 1
            assert(ethis);
384 1
            elem *ev = el_same(&ethis);
385 1
            ev = el_una(OPind, TYnptr, ev);
386 1
            uint vindex = fd.vtblIndex;
387 1
            assert(cast(int)vindex >= 0);
388

389
            // Build *(ev + vindex * 4)
390 1
if (!irs.params.is64bit) assert(tysize(TYnptr) == 4);
391 1
            ec = el_bin(OPadd,TYnptr,ev,el_long(TYsize_t, vindex * tysize(TYnptr)));
392 1
            ec = el_una(OPind,TYnptr,ec);
393 1
            ec = el_una(OPind,tybasic(sfunc.Stype.Tty),ec);
394
        }
395
    }
396 1
    else if (fd && fd.isNested())
397
    {
398 1
        assert(!ethis);
399 1
        ethis = getEthis(loc, irs, fd, fd.toParentLocal());
400 1
        if (ethis2)
401 1
            ethis2 = setEthis2(loc, irs, fd, ethis2, &ethis, &eside);
402
    }
403

404 1
    ep = el_param(ep, ethis2 ? ethis2 : ethis);
405 1
    if (ehidden)
406 1
        ep = el_param(ep, ehidden);     // if ehidden goes last
407

408 1
    const tyret = totym(tret);
409

410
    // Look for intrinsic functions and construct result into e
411 1
    elem *e;
412 1
    if (ec.Eoper == OPvar && op != NotIntrinsic)
413
    {
414 1
        el_free(ec);
415 1
        if (op != OPtoPrec && OTbinary(op))
416
        {
417 1
            ep.Eoper = cast(ubyte)op;
418 1
            ep.Ety = tyret;
419 1
            e = ep;
420 1
            if (op == OPeq)
421
            {   /* This was a volatileStore(ptr, value) operation, rewrite as:
422
                 *   *ptr = value
423
                 */
424 0
                e.EV.E1 = el_una(OPind, e.EV.E2.Ety | mTYvolatile, e.EV.E1);
425
            }
426 1
            if (op == OPscale)
427
            {
428 1
                elem *et = e.EV.E1;
429 1
                e.EV.E1 = el_una(OPs32_d, TYdouble, e.EV.E2);
430 1
                e.EV.E1 = el_una(OPd_ld, TYldouble, e.EV.E1);
431 1
                e.EV.E2 = et;
432
            }
433 1
            else if (op == OPyl2x || op == OPyl2xp1)
434
            {
435 1
                elem *et = e.EV.E1;
436 1
                e.EV.E1 = e.EV.E2;
437 1
                e.EV.E2 = et;
438
            }
439
        }
440 1
        else if (op == OPvector)
441
        {
442 1
            e = ep;
443
            /* Recognize store operations as:
444
             *  (op OPparam (op1 OPparam op2))
445
             * Rewrite as:
446
             *  (op1 OPvecsto (op OPparam op2))
447
             * A separate operation is used for stores because it
448
             * has a side effect, and so takes a different path through
449
             * the optimizer.
450
             */
451 1
            if (e.Eoper == OPparam &&
452 1
                e.EV.E1.Eoper == OPconst &&
453 1
                isXMMstore(cast(uint)el_tolong(e.EV.E1)))
454
            {
455
                //printf("OPvecsto\n");
456 1
                elem *tmp = e.EV.E1;
457 1
                e.EV.E1 = e.EV.E2.EV.E1;
458 1
                e.EV.E2.EV.E1 = tmp;
459 1
                e.Eoper = OPvecsto;
460 1
                e.Ety = tyret;
461
            }
462
            else
463 1
                e = el_una(op,tyret,ep);
464
        }
465 1
        else if (op == OPind)
466 0
            e = el_una(op,mTYvolatile | tyret,ep);
467 1
        else if (op == OPva_start && irs.params.is64bit)
468
        {
469
            // (OPparam &va &arg)
470
            // call as (OPva_start &va)
471 1
            ep.Eoper = cast(ubyte)op;
472 1
            ep.Ety = tyret;
473 1
            e = ep;
474

475 1
            elem *earg = e.EV.E2;
476 1
            e.EV.E2 = null;
477 1
            e = el_combine(earg, e);
478
        }
479 1
        else if (op == OPtoPrec)
480
        {
481 1
            static int X(int fty, int tty) { return fty * TMAX + tty; }
482

483 1
            final switch (X(tybasic(ep.Ety), tybasic(tyret)))
484
            {
485 1
            case X(TYfloat, TYfloat):     // float -> float
486 1
            case X(TYdouble, TYdouble):   // double -> double
487 1
            case X(TYldouble, TYldouble): // real -> real
488 1
                e = ep;
489 1
                break;
490

491 1
            case X(TYfloat, TYdouble):    // float -> double
492 1
                e = el_una(OPf_d, tyret, ep);
493 1
                break;
494

495 1
            case X(TYfloat, TYldouble):   // float -> real
496 1
                e = el_una(OPf_d, TYdouble, ep);
497 1
                e = el_una(OPd_ld, tyret, e);
498 1
                break;
499

500 1
            case X(TYdouble, TYfloat):    // double -> float
501 1
                e = el_una(OPd_f, tyret, ep);
502 1
                break;
503

504 1
            case X(TYdouble, TYldouble):  // double -> real
505 1
                e = el_una(OPd_ld, tyret, ep);
506 1
                break;
507

508 1
            case X(TYldouble, TYfloat):   // real -> float
509 1
                e = el_una(OPld_d, TYdouble, ep);
510 1
                e = el_una(OPd_f, tyret, e);
511 1
                break;
512

513 1
            case X(TYldouble, TYdouble):  // real -> double
514 1
                e = el_una(OPld_d, tyret, ep);
515 1
                break;
516
            }
517
        }
518
        else
519 1
            e = el_una(op,tyret,ep);
520
    }
521
    else
522
    {
523
        /* Do not do "no side effect" calls if a hidden parameter is passed,
524
         * as the return value is stored through the hidden parameter, which
525
         * is a side effect.
526
         */
527
        //printf("1: fd = %p prity = %d, nothrow = %d, retmethod = %d, use-assert = %d\n",
528
        //       fd, (fd ? fd.isPure() : tf.purity), tf.isnothrow, retmethod, irs.params.useAssert);
529
        //printf("\tfd = %s, tf = %s\n", fd.toChars(), tf.toChars());
530
        /* assert() has 'implicit side effect' so disable this optimization.
531
         */
532 1
        int ns = ((fd ? callSideEffectLevel(fd)
533 1
                      : callSideEffectLevel(t)) == 2 &&
534 1
                  retmethod != RET.stack &&
535 1
                  irs.params.useAssert == CHECKENABLE.off && irs.params.optimize);
536 1
        if (ep)
537 1
            e = el_bin(ns ? OPcallns : OPcall, tyret, ec, ep);
538
        else
539 1
            e = el_una(ns ? OPucallns : OPucall, tyret, ec);
540

541 1
        if (tf.parameterList.varargs != VarArg.none)
542 1
            e.Eflags |= EFLAGS_variadic;
543
    }
544

545 1
    const isCPPCtor = fd && fd.linkage == LINK.cpp && fd.isCtorDeclaration();
546 1
    if (isCPPCtor && target.isPOSIX)
547
    {
548
        // CPP constructor returns void on Posix
549
        // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#return-value-ctor
550 1
        e.Ety = TYvoid;
551 1
        e = el_combine(e, el_same(&ethis));
552
    }
553 1
    else if (retmethod == RET.stack)
554
    {
555 1
        if (irs.params.isOSX && eresult)
556
            /* ABI quirk: hidden pointer is not returned in registers
557
             */
558 0
            e = el_combine(e, el_copytree(eresult));
559 1
        e.Ety = TYnptr;
560 1
        e = el_una(OPind, tyret, e);
561
    }
562

563 1
    if (tf.isref)
564
    {
565 1
        e.Ety = TYnptr;
566 1
        e = el_una(OPind, tyret, e);
567
    }
568

569 1
    if (tybasic(tyret) == TYstruct)
570
    {
571 1
        e.ET = Type_toCtype(tret);
572
    }
573 1
    e = el_combine(eside, e);
574 1
    return e;
575
}
576

577
/**********************************
578
 * D presumes left-to-right argument evaluation, but we're evaluating things
579
 * right-to-left here.
580
 * 1. determine if this matters
581
 * 2. fix it if it does
582
 * Params:
583
 *      arguments = function arguments, these will get rewritten in place
584
 * Returns:
585
 *      elem that evaluates the side effects
586
 */
587
private extern (D) elem *fixArgumentEvaluationOrder(elem*[] elems)
588
{
589
    /* It matters if all are true:
590
     * 1. at least one argument has side effects
591
     * 2. at least one other argument may depend on side effects
592
     */
593 1
    if (elems.length <= 1)
594 1
        return null;
595

596 1
    size_t ifirstside = 0;      // index-1 of first side effect
597 1
    size_t ifirstdep = 0;       // index-1 of first dependency on side effect
598 1
    foreach (i, e; elems)
599
    {
600 1
        switch (e.Eoper)
601
        {
602 1
            case OPconst:
603 1
            case OPrelconst:
604 1
            case OPstring:
605 1
                continue;
606

607 1
            default:
608 1
                break;
609
        }
610

611 1
        if (el_sideeffect(e))
612
        {
613 1
            if (!ifirstside)
614 1
                ifirstside = i + 1;
615 1
            else if (!ifirstdep)
616 1
                ifirstdep = i + 1;
617
        }
618
        else
619
        {
620 1
            if (!ifirstdep)
621 1
                ifirstdep = i + 1;
622
        }
623 1
        if (ifirstside && ifirstdep)
624 1
            break;
625
    }
626

627 1
    if (!ifirstdep || !ifirstside)
628 1
        return null;
629

630
    /* Now fix by appending side effects and dependencies to eside and replacing
631
     * argument with a temporary.
632
     * Rely on the optimizer removing some unneeded ones using flow analysis.
633
     */
634 1
    elem* eside = null;
635 1
    foreach (i, e; elems)
636
    {
637 1
        while (e.Eoper == OPcomma)
638
        {
639 1
            eside = el_combine(eside, e.EV.E1);
640 1
            e = e.EV.E2;
641 1
            elems[i] = e;
642
        }
643

644 1
        switch (e.Eoper)
645
        {
646 1
            case OPconst:
647 1
            case OPrelconst:
648 1
            case OPstring:
649 1
                continue;
650

651 1
            default:
652 1
                break;
653
        }
654

655 1
        elem *es = e;
656 1
        elems[i] = el_copytotmp(&es);
657 1
        eside = el_combine(eside, es);
658
    }
659

660 1
    return eside;
661
}
662

663
/*******************************************
664
 * Take address of an elem.
665
 */
666

667
elem *addressElem(elem *e, Type t, bool alwaysCopy = false)
668
{
669
    //printf("addressElem()\n");
670

671 1
    elem **pe;
672 1
    for (pe = &e; (*pe).Eoper == OPcomma; pe = &(*pe).EV.E2)
673
    {
674
    }
675

676
    // For conditional operator, both branches need conversion.
677 1
    if ((*pe).Eoper == OPcond)
678
    {
679 1
        elem *ec = (*pe).EV.E2;
680

681 1
        ec.EV.E1 = addressElem(ec.EV.E1, t, alwaysCopy);
682 1
        ec.EV.E2 = addressElem(ec.EV.E2, t, alwaysCopy);
683

684 1
        (*pe).Ejty = (*pe).Ety = cast(ubyte)ec.EV.E1.Ety;
685 1
        (*pe).ET = ec.EV.E1.ET;
686

687 1
        e.Ety = TYnptr;
688 1
        return e;
689
    }
690

691 1
    if (alwaysCopy || ((*pe).Eoper != OPvar && (*pe).Eoper != OPind))
692
    {
693 1
        elem *e2 = *pe;
694 1
        type *tx;
695

696
        // Convert to ((tmp=e2),tmp)
697 1
        TY ty;
698 1
        if (t && ((ty = t.toBasetype().ty) == Tstruct || ty == Tsarray))
699 1
            tx = Type_toCtype(t);
700 1
        else if (tybasic(e2.Ety) == TYstruct)
701
        {
702 1
            assert(t);                  // don't know of a case where this can be null
703 1
            tx = Type_toCtype(t);
704
        }
705
        else
706 1
            tx = type_fake(e2.Ety);
707 1
        Symbol *stmp = symbol_genauto(tx);
708

709 1
        elem *eeq = elAssign(el_var(stmp), e2, t, tx);
710 1
        *pe = el_bin(OPcomma,e2.Ety,eeq,el_var(stmp));
711
    }
712 1
    tym_t typ = TYnptr;
713 1
    if (e.Eoper == OPind && tybasic(e.EV.E1.Ety) == TYimmutPtr)
714 1
        typ = TYimmutPtr;
715 1
    e = el_una(OPaddr,typ,e);
716 1
    return e;
717
}
718

719
/***************************************
720
 * Return `true` if elem is a an lvalue.
721
 * Lvalue elems are OPvar and OPind.
722
 */
723

724
bool elemIsLvalue(elem* e)
725
{
726 1
    while (e.Eoper == OPcomma || e.Eoper == OPinfo)
727 1
        e = e.EV.E2;
728

729
    // For conditional operator, both branches need to be lvalues.
730 1
    if (e.Eoper == OPcond)
731
    {
732 1
        elem* ec = e.EV.E2;
733 1
        return elemIsLvalue(ec.EV.E1) && elemIsLvalue(ec.EV.E2);
734
    }
735

736 1
    return e.Eoper == OPvar || e.Eoper == OPind;
737
}
738

739
/*****************************************
740
 * Convert array to a pointer to the data.
741
 * Params:
742
 *      t = array type
743
 *      e = array to convert, it is "consumed" by the function
744
 * Returns:
745
 *      e rebuilt into a pointer to the data
746
 */
747

748
elem *array_toPtr(Type t, elem *e)
749
{
750
    //printf("array_toPtr()\n");
751
    //elem_print(e);
752 1
    t = t.toBasetype();
753 1
    switch (t.ty)
754
    {
755 1
        case Tpointer:
756 1
            break;
757

758 1
        case Tarray:
759 1
        case Tdelegate:
760 1
            if (e.Eoper == OPcomma)
761
            {
762 1
                e.Ety = TYnptr;
763 1
                e.EV.E2 = array_toPtr(t, e.EV.E2);
764
            }
765 1
            else if (e.Eoper == OPpair)
766
            {
767 1
                if (el_sideeffect(e.EV.E1))
768
                {
769 0
                    e.Eoper = OPcomma;
770 0
                    e.Ety = TYnptr;
771
                }
772
                else
773
                {
774 1
                    auto r = e;
775 1
                    e = e.EV.E2;
776 1
                    e.Ety = TYnptr;
777 1
                    r.EV.E2 = null;
778 1
                    el_free(r);
779
                }
780
            }
781
            else
782
            {
783
version (all)
784 1
                e = el_una(OPmsw, TYnptr, e);
785
else
786
{
787
                e = el_una(OPaddr, TYnptr, e);
788
                e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, 4));
789
                e = el_una(OPind, TYnptr, e);
790
}
791
            }
792 1
            break;
793

794 1
        case Tsarray:
795
            //e = el_una(OPaddr, TYnptr, e);
796 1
            e = addressElem(e, t);
797 1
            break;
798

799 0
        default:
800 0
            printf("%s\n", t.toChars());
801 0
            assert(0);
802
    }
803 1
    return e;
804
}
805

806
/*****************************************
807
 * Convert array to a dynamic array.
808
 */
809

810
elem *array_toDarray(Type t, elem *e)
811
{
812 1
    uint dim;
813 1
    elem *ef = null;
814 1
    elem *ex;
815

816
    //printf("array_toDarray(t = %s)\n", t.toChars());
817
    //elem_print(e);
818 1
    t = t.toBasetype();
819 1
    switch (t.ty)
820
    {
821 1
        case Tarray:
822 1
            break;
823

824 1
        case Tsarray:
825 1
            e = addressElem(e, t);
826 1
            dim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
827 1
            e = el_pair(TYdarray, el_long(TYsize_t, dim), e);
828 1
            break;
829

830 1
        default:
831
        L1:
832 1
            switch (e.Eoper)
833
            {
834 1
                case OPconst:
835
                {
836 1
                    size_t len = tysize(e.Ety);
837 1
                    elem *es = el_calloc();
838 1
                    es.Eoper = OPstring;
839

840
                    // freed in el_free
841 1
                    es.EV.Vstring = cast(char*)mem_malloc2(cast(uint)len);
842 1
                    memcpy(es.EV.Vstring, &e.EV, len);
843

844 1
                    es.EV.Vstrlen = len;
845 1
                    es.Ety = TYnptr;
846 1
                    e = es;
847 1
                    break;
848
                }
849

850 1
                case OPvar:
851 1
                    e = el_una(OPaddr, TYnptr, e);
852 1
                    break;
853

854 1
                case OPcomma:
855 1
                    ef = el_combine(ef, e.EV.E1);
856 1
                    ex = e;
857 1
                    e = e.EV.E2;
858 1
                    ex.EV.E1 = null;
859 1
                    ex.EV.E2 = null;
860 1
                    el_free(ex);
861 1
                    goto L1;
862

863 1
                case OPind:
864 1
                    ex = e;
865 1
                    e = e.EV.E1;
866 1
                    ex.EV.E1 = null;
867 1
                    ex.EV.E2 = null;
868 1
                    el_free(ex);
869 1
                    break;
870

871 1
                default:
872
                {
873
                    // Copy expression to a variable and take the
874
                    // address of that variable.
875 1
                    e = addressElem(e, t);
876 1
                    break;
877
                }
878
            }
879 1
            dim = 1;
880 1
            e = el_pair(TYdarray, el_long(TYsize_t, dim), e);
881 1
            break;
882
    }
883 1
    return el_combine(ef, e);
884
}
885

886
/************************************
887
 */
888

889
elem *sarray_toDarray(const ref Loc loc, Type tfrom, Type tto, elem *e)
890
{
891
    //printf("sarray_toDarray()\n");
892
    //elem_print(e);
893

894 1
    dinteger_t dim = (cast(TypeSArray)tfrom).dim.toInteger();
895

896 1
    if (tto)
897
    {
898 1
        uint fsize = cast(uint)tfrom.nextOf().size();
899 1
        uint tsize = cast(uint)tto.nextOf().size();
900

901 1
        if ((dim * fsize) % tsize != 0)
902
        {
903
            // have to change to Internal Compiler Error?
904 0
            error(loc, "cannot cast %s to %s since sizes don't line up", tfrom.toChars(), tto.toChars());
905
        }
906 1
        dim = (dim * fsize) / tsize;
907
    }
908 1
    elem *elen = el_long(TYsize_t, dim);
909 1
    e = addressElem(e, tfrom);
910 1
    e = el_pair(TYdarray, elen, e);
911 1
    return e;
912
}
913

914
/************************************
915
 */
916

917
elem *getTypeInfo(Loc loc, Type t, IRState *irs)
918
{
919 1
    assert(t.ty != Terror);
920 1
    genTypeInfo(loc, t, null);
921 1
    elem *e = el_ptr(toSymbol(t.vtinfo));
922 1
    return e;
923
}
924

925
/********************************************
926
 * Determine if t is a struct that has postblit.
927
 */
928
StructDeclaration needsPostblit(Type t)
929
{
930 1
    if (auto ts = t.baseElemOf().isTypeStruct())
931
    {
932 1
        StructDeclaration sd = ts.sym;
933 1
        if (sd.postblit)
934 1
            return sd;
935
    }
936 1
    return null;
937
}
938

939
/********************************************
940
 * Determine if t is a struct that has destructor.
941
 */
942
StructDeclaration needsDtor(Type t)
943
{
944 1
    if (auto ts = t.baseElemOf().isTypeStruct())
945
    {
946 1
        StructDeclaration sd = ts.sym;
947 1
        if (sd.dtor)
948 1
            return sd;
949
    }
950 1
    return null;
951
}
952

953
/*******************************************
954
 * Set an array pointed to by eptr to evalue:
955
 *      eptr[0..edim] = evalue;
956
 * Params:
957
 *      exp    = the expression for which this operation is performed
958
 *      eptr   = where to write the data to
959
 *      edim   = number of times to write evalue to eptr[]
960
 *      tb     = type of evalue
961
 *      evalue = value to write
962
 *      irs    = context
963
 *      op     = TOK.blit, TOK.assign, or TOK.construct
964
 * Returns:
965
 *      created IR code
966
 */
967
private elem *setArray(Expression exp, elem *eptr, elem *edim, Type tb, elem *evalue, IRState *irs, int op)
968
{
969 1
    assert(op == TOK.blit || op == TOK.assign || op == TOK.construct);
970 1
    const sz = cast(uint)tb.size();
971

972
Lagain:
973 1
    int r;
974 1
    switch (tb.ty)
975
    {
976 1
        case Tfloat80:
977 1
        case Timaginary80:
978 1
            r = RTLSYM_MEMSET80;
979 1
            break;
980 1
        case Tcomplex80:
981 1
            r = RTLSYM_MEMSET160;
982 1
            break;
983 1
        case Tcomplex64:
984 1
            r = RTLSYM_MEMSET128;
985 1
            break;
986 1
        case Tfloat32:
987 1
        case Timaginary32:
988 1
            if (!irs.params.is64bit)
989 0
                goto default;          // legacy binary compatibility
990 1
            r = RTLSYM_MEMSETFLOAT;
991 1
            break;
992 1
        case Tfloat64:
993 1
        case Timaginary64:
994 1
            if (!irs.params.is64bit)
995 0
                goto default;          // legacy binary compatibility
996 1
            r = RTLSYM_MEMSETDOUBLE;
997 1
            break;
998

999 1
        case Tstruct:
1000
        {
1001 1
            if (!irs.params.is64bit)
1002 0
                goto default;
1003

1004 1
            TypeStruct tc = cast(TypeStruct)tb;
1005 1
            StructDeclaration sd = tc.sym;
1006 1
            if (sd.numArgTypes() == 1)
1007
            {
1008 1
                tb = sd.argType(0);
1009 1
                goto Lagain;
1010
            }
1011 1
            goto default;
1012
        }
1013

1014 1
        case Tvector:
1015 1
            r = RTLSYM_MEMSETSIMD;
1016 1
            break;
1017

1018 1
        default:
1019 1
            switch (sz)
1020
            {
1021 1
                case 1:      r = RTLSYM_MEMSET8;    break;
1022 1
                case 2:      r = RTLSYM_MEMSET16;   break;
1023 1
                case 4:      r = RTLSYM_MEMSET32;   break;
1024 1
                case 8:      r = RTLSYM_MEMSET64;   break;
1025 1
                case 16:     r = irs.params.is64bit ? RTLSYM_MEMSET128ii : RTLSYM_MEMSET128; break;
1026 1
                default:     r = RTLSYM_MEMSETN;    break;
1027
            }
1028

1029
            /* Determine if we need to do postblit
1030
             */
1031 1
            if (op != TOK.blit)
1032
            {
1033 1
                if (needsPostblit(tb) || needsDtor(tb))
1034
                {
1035
                    /* Need to do postblit/destructor.
1036
                     *   void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
1037
                     */
1038 1
                    r = (op == TOK.construct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN;
1039 1
                    evalue = el_una(OPaddr, TYnptr, evalue);
1040
                    // This is a hack so we can call postblits on const/immutable objects.
1041 1
                    elem *eti = getTypeInfo(exp.loc, tb.unSharedOf().mutableOf(), irs);
1042 1
                    elem *e = el_params(eti, edim, evalue, eptr, null);
1043 1
                    e = el_bin(OPcall,TYnptr,el_var(getRtlsym(r)),e);
1044 1
                    return e;
1045
                }
1046
            }
1047

1048 1
            if (irs.params.is64bit && tybasic(evalue.Ety) == TYstruct && r != RTLSYM_MEMSETN)
1049
            {
1050
                /* If this struct is in-memory only, i.e. cannot necessarily be passed as
1051
                 * a gp register parameter.
1052
                 * The trouble is that memset() is expecting the argument to be in a gp
1053
                 * register, but the argument pusher may have other ideas on I64.
1054
                 * MEMSETN is inefficient, though.
1055
                 */
1056 1
                if (tybasic(evalue.ET.Tty) == TYstruct)
1057
                {
1058 1
                    type *t1 = evalue.ET.Ttag.Sstruct.Sarg1type;
1059 1
                    type *t2 = evalue.ET.Ttag.Sstruct.Sarg2type;
1060 1
                    if (!t1 && !t2)
1061
                    {
1062 1
                        if (config.exe != EX_WIN64 || sz > 8)
1063 1
                            r = RTLSYM_MEMSETN;
1064
                    }
1065 1
                    else if (config.exe != EX_WIN64 &&
1066 1
                             r == RTLSYM_MEMSET128ii &&
1067 1
                             tyfloating(t1.Tty) &&
1068 1
                             tyfloating(t2.Tty))
1069 1
                        r = RTLSYM_MEMSET128;
1070
                }
1071
            }
1072

1073 1
            if (r == RTLSYM_MEMSETN)
1074
            {
1075
                // void *_memsetn(void *p, void *value, int dim, int sizelem)
1076 1
                evalue = addressElem(evalue, tb);
1077 1
                elem *esz = el_long(TYsize_t, sz);
1078 1
                elem *e = el_params(esz, edim, evalue, eptr, null);
1079 1
                e = el_bin(OPcall,TYnptr,el_var(getRtlsym(r)),e);
1080 1
                return e;
1081
            }
1082 1
            break;
1083
    }
1084 1
    if (sz > 1 && sz <= 8 &&
1085 1
        evalue.Eoper == OPconst && el_allbits(evalue, 0))
1086
    {
1087 1
        r = RTLSYM_MEMSET8;
1088 1
        edim = el_bin(OPmul, TYsize_t, edim, el_long(TYsize_t, sz));
1089
    }
1090

1091 1
    if (config.exe == EX_WIN64 && sz > REGSIZE)
1092
    {
1093 0
        evalue = addressElem(evalue, tb);
1094
    }
1095
    // cast to the proper parameter type
1096 1
    else if (r != RTLSYM_MEMSETN)
1097
    {
1098 1
        tym_t tym;
1099 1
        switch (r)
1100
        {
1101 1
            case RTLSYM_MEMSET8:      tym = TYchar;     break;
1102 1
            case RTLSYM_MEMSET16:     tym = TYshort;    break;
1103 1
            case RTLSYM_MEMSET32:     tym = TYlong;     break;
1104 1
            case RTLSYM_MEMSET64:     tym = TYllong;    break;
1105 1
            case RTLSYM_MEMSET80:     tym = TYldouble;  break;
1106 1
            case RTLSYM_MEMSET160:    tym = TYcldouble; break;
1107 1
            case RTLSYM_MEMSET128:    tym = TYcdouble;  break;
1108 1
            case RTLSYM_MEMSET128ii:  tym = TYucent;    break;
1109 1
            case RTLSYM_MEMSETFLOAT:  tym = TYfloat;    break;
1110 1
            case RTLSYM_MEMSETDOUBLE: tym = TYdouble;   break;
1111 1
            case RTLSYM_MEMSETSIMD:   tym = TYfloat4;   break;
1112 0
            default:
1113 0
                assert(0);
1114
        }
1115 1
        tym = tym | (evalue.Ety & ~mTYbasic);
1116 1
        evalue = addressElem(evalue, tb);
1117 1
        evalue = el_una(OPind, tym, evalue);
1118
    }
1119

1120 1
    evalue = useOPstrpar(evalue);
1121

1122
    // Be careful about parameter side effect ordering
1123 1
    if (r == RTLSYM_MEMSET8)
1124
    {
1125 1
        elem *e = el_param(edim, evalue);
1126 1
        return el_bin(OPmemset,TYnptr,eptr,e);
1127
    }
1128
    else
1129
    {
1130 1
        elem *e = el_params(edim, evalue, eptr, null);
1131 1
        return el_bin(OPcall,TYnptr,el_var(getRtlsym(r)),e);
1132
    }
1133
}
1134

1135

1136
__gshared StringTable!(Symbol*) *stringTab;
1137

1138
/********************************
1139
 * Reset stringTab[] between object files being emitted, because the symbols are local.
1140
 */
1141
void clearStringTab()
1142
{
1143
    //printf("clearStringTab()\n");
1144 1
    if (stringTab)
1145 1
        stringTab.reset(1000);             // 1000 is arbitrary guess
1146
    else
1147
    {
1148 1
        stringTab = new StringTable!(Symbol*)();
1149 1
        stringTab._init(1000);
1150
    }
1151
}
1152

1153

1154
elem *toElem(Expression e, IRState *irs)
1155
{
1156
    extern (C++) class ToElemVisitor : Visitor
1157
    {
1158
        IRState *irs;
1159
        elem *result;
1160

1161 1
        this(IRState *irs)
1162
        {
1163 1
            this.irs = irs;
1164 1
            result = null;
1165
        }
1166

1167
        alias visit = Visitor.visit;
1168

1169
        /***************************************
1170
         */
1171

1172
        override void visit(Expression e)
1173
        {
1174 0
            printf("[%s] %s: %s\n", e.loc.toChars(), Token.toChars(e.op), e.toChars());
1175 0
            assert(0);
1176
        }
1177

1178
        /************************************
1179
         */
1180
        override void visit(SymbolExp se)
1181
        {
1182 1
            elem *e;
1183 1
            Type tb = (se.op == TOK.symbolOffset) ? se.var.type.toBasetype() : se.type.toBasetype();
1184 1
            int offset = (se.op == TOK.symbolOffset) ? cast(int)(cast(SymOffExp)se).offset : 0;
1185 1
            VarDeclaration v = se.var.isVarDeclaration();
1186

1187
            //printf("[%s] SymbolExp.toElem('%s') %p, %s\n", se.loc.toChars(), se.toChars(), se, se.type.toChars());
1188
            //printf("\tparent = '%s'\n", se.var.parent ? se.var.parent.toChars() : "null");
1189 1
            if (se.op == TOK.variable && se.var.needThis())
1190
            {
1191 0
                se.error("need `this` to access member `%s`", se.toChars());
1192 0
                result = el_long(TYsize_t, 0);
1193 0
                return;
1194
            }
1195

1196
            /* The magic variable __ctfe is always false at runtime
1197
             */
1198 1
            if (se.op == TOK.variable && v && v.ident == Id.ctfe)
1199
            {
1200 1
                result = el_long(totym(se.type), 0);
1201 1
                return;
1202
            }
1203

1204 1
            if (FuncLiteralDeclaration fld = se.var.isFuncLiteralDeclaration())
1205
            {
1206 1
                if (fld.tok == TOK.reserved)
1207
                {
1208
                    // change to non-nested
1209 1
                    fld.tok = TOK.function_;
1210 1
                    fld.vthis = null;
1211
                }
1212 1
                if (!fld.deferToObj)
1213
                {
1214 1
                    fld.deferToObj = true;
1215 1
                    irs.deferToObj.push(fld);
1216
                }
1217
            }
1218

1219 1
            Symbol *s = toSymbol(se.var);
1220 1
            FuncDeclaration fd = null;
1221 1
            if (se.var.toParent2())
1222 1
                fd = se.var.toParent2().isFuncDeclaration();
1223

1224 1
            const bool nrvo = fd && fd.nrvo_can && fd.nrvo_var == se.var;
1225 1
            if (nrvo)
1226 1
                s = fd.shidden;
1227

1228 1
            if (s.Sclass == SCauto || s.Sclass == SCparameter || s.Sclass == SCshadowreg)
1229
            {
1230 1
                if (fd && fd != irs.getFunc())
1231
                {
1232
                    // 'var' is a variable in an enclosing function.
1233 1
                    elem *ethis = getEthis(se.loc, irs, fd, null, se.originalScope);
1234 1
                    ethis = el_una(OPaddr, TYnptr, ethis);
1235

1236
                    /* https://issues.dlang.org/show_bug.cgi?id=9383
1237
                     * If 's' is a virtual function parameter
1238
                     * placed in closure, and actually accessed from in/out
1239
                     * contract, instead look at the original stack data.
1240
                     */
1241 1
                    bool forceStackAccess = false;
1242 1
                    if (fd.isVirtual() && (fd.fdrequire || fd.fdensure))
1243
                    {
1244 1
                        Dsymbol sx = irs.getFunc();
1245 1
                        while (sx != fd)
1246
                        {
1247 1
                            if (sx.ident == Id.require || sx.ident == Id.ensure)
1248
                            {
1249 0
                                forceStackAccess = true;
1250 0
                                break;
1251
                            }
1252 1
                            sx = sx.toParent2();
1253
                        }
1254
                    }
1255

1256 1
                    int soffset;
1257 1
                    if (v && v.offset && !forceStackAccess)
1258 1
                        soffset = v.offset;
1259
                    else
1260
                    {
1261 1
                        soffset = cast(int)s.Soffset;
1262
                        /* If fd is a non-static member function of a class or struct,
1263
                         * then ethis isn't the frame pointer.
1264
                         * ethis is the 'this' pointer to the class/struct instance.
1265
                         * We must offset it.
1266
                         */
1267 1
                        if (fd.vthis)
1268
                        {
1269 1
                            Symbol *vs = toSymbol(fd.vthis);
1270
                            //printf("vs = %s, offset = %x, %p\n", vs.Sident, (int)vs.Soffset, vs);
1271 1
                            soffset -= vs.Soffset;
1272
                        }
1273
                        //printf("\tSoffset = x%x, sthis.Soffset = x%x\n", s.Soffset, irs.sthis.Soffset);
1274
                    }
1275

1276 1
                    if (!nrvo)
1277 1
                        soffset += offset;
1278

1279 1
                    e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
1280 1
                    if (se.op == TOK.variable)
1281 1
                        e = el_una(OPind, TYnptr, e);
1282 1
                    if (ISREF(se.var) && !(ISX64REF(se.var) && v && v.offset && !forceStackAccess))
1283 1
                        e = el_una(OPind, s.Stype.Tty, e);
1284 1
                    else if (se.op == TOK.symbolOffset && nrvo)
1285
                    {
1286 1
                        e = el_una(OPind, TYnptr, e);
1287 1
                        e = el_bin(OPadd, e.Ety, e, el_long(TYsize_t, offset));
1288
                    }
1289 1
                    goto L1;
1290
                }
1291
            }
1292

1293
            /* If var is a member of a closure
1294
             */
1295 1
            if (v && v.offset)
1296
            {
1297 1
                assert(irs.sclosure);
1298 1
                e = el_var(irs.sclosure);
1299 1
                e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, v.offset));
1300 1
                if (se.op == TOK.variable)
1301
                {
1302 1
                    e = el_una(OPind, totym(se.type), e);
1303 1
                    if (tybasic(e.Ety) == TYstruct)
1304 1
                        e.ET = Type_toCtype(se.type);
1305 1
                    elem_setLoc(e, se.loc);
1306
                }
1307 1
                if (ISREF(se.var) && !ISX64REF(se.var))
1308
                {
1309 1
                    e.Ety = TYnptr;
1310 1
                    e = el_una(OPind, s.Stype.Tty, e);
1311
                }
1312 1
                else if (se.op == TOK.symbolOffset && nrvo)
1313
                {
1314 0
                    e = el_una(OPind, TYnptr, e);
1315 0
                    e = el_bin(OPadd, e.Ety, e, el_long(TYsize_t, offset));
1316
                }
1317 1
                else if (se.op == TOK.symbolOffset)
1318
                {
1319 1
                    e = el_bin(OPadd, e.Ety, e, el_long(TYsize_t, offset));
1320
                }
1321 1
                goto L1;
1322
            }
1323

1324 1
            if (s.Sclass == SCauto && s.Ssymnum == -1)
1325
            {
1326
                //printf("\tadding symbol %s\n", s.Sident);
1327 1
                symbol_add(s);
1328
            }
1329

1330 1
            if (se.var.isImportedSymbol())
1331
            {
1332 0
                assert(se.op == TOK.variable);
1333 0
                e = el_var(toImport(se.var));
1334 0
                e = el_una(OPind,s.Stype.Tty,e);
1335
            }
1336 1
            else if (ISREF(se.var))
1337
            {
1338
                // Out parameters are really references
1339 1
                e = el_var(s);
1340 1
                e.Ety = TYnptr;
1341 1
                if (se.op == TOK.variable)
1342 1
                    e = el_una(OPind, s.Stype.Tty, e);
1343 1
                else if (offset)
1344 0
                    e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset));
1345
            }
1346 1
            else if (se.op == TOK.variable)
1347 1
                e = el_var(s);
1348
            else
1349
            {
1350 1
                e = nrvo ? el_var(s) : el_ptr(s);
1351 1
                e = el_bin(OPadd, e.Ety, e, el_long(TYsize_t, offset));
1352
            }
1353
        L1:
1354 1
            if (se.op == TOK.variable)
1355
            {
1356 1
                if (nrvo)
1357
                {
1358 1
                    e.Ety = TYnptr;
1359 1
                    e = el_una(OPind, 0, e);
1360
                }
1361

1362 1
                tym_t tym;
1363 1
                if (se.var.storage_class & STC.lazy_)
1364 1
                    tym = TYdelegate;       // Tdelegate as C type
1365 1
                else if (tb.ty == Tfunction)
1366 1
                    tym = s.Stype.Tty;
1367
                else
1368 1
                    tym = totym(se.type);
1369

1370 1
                e.Ejty = cast(ubyte)(e.Ety = tym);
1371

1372 1
                if (tybasic(tym) == TYstruct)
1373
                {
1374 1
                    e.ET = Type_toCtype(se.type);
1375
                }
1376 1
                else if (tybasic(tym) == TYarray)
1377
                {
1378 0
                    e.Ejty = e.Ety = TYstruct;
1379 0
                    e.ET = Type_toCtype(se.type);
1380
                }
1381 1
                else if (tysimd(tym))
1382
                {
1383 1
                    e.ET = Type_toCtype(se.type);
1384
                }
1385
            }
1386 1
            elem_setLoc(e,se.loc);
1387 1
            result = e;
1388
        }
1389

1390
        /**************************************
1391
         */
1392

1393
        override void visit(FuncExp fe)
1394
        {
1395
            //printf("FuncExp.toElem() %s\n", fe.toChars());
1396 1
            FuncLiteralDeclaration fld = fe.fd;
1397

1398 1
            if (fld.tok == TOK.reserved && fe.type.ty == Tpointer)
1399
            {
1400
                // change to non-nested
1401 1
                fld.tok = TOK.function_;
1402 1
                fld.vthis = null;
1403
            }
1404 1
            if (!fld.deferToObj)
1405
            {
1406 1
                fld.deferToObj = true;
1407 1
                irs.deferToObj.push(fld);
1408
            }
1409

1410 1
            Symbol *s = toSymbol(fld);
1411 1
            elem *e = el_ptr(s);
1412 1
            if (fld.isNested())
1413
            {
1414 1
                elem *ethis;
1415
                // Delegate literals report isNested() even if they are in global scope,
1416
                // so we need to check that the parent is a function.
1417 1
                if (!fld.toParent2().isFuncDeclaration())
1418 1
                    ethis = el_long(TYnptr, 0);
1419
                else
1420 1
                    ethis = getEthis(fe.loc, irs, fld);
1421 1
                e = el_pair(TYdelegate, ethis, e);
1422
            }
1423 1
            elem_setLoc(e, fe.loc);
1424 1
            result = e;
1425
        }
1426

1427
        override void visit(DeclarationExp de)
1428
        {
1429
            //printf("DeclarationExp.toElem() %s\n", de.toChars());
1430 1
            result = Dsymbol_toElem(de.declaration);
1431
        }
1432

1433
        /***************************************
1434
         */
1435

1436
        override void visit(TypeidExp e)
1437
        {
1438
            //printf("TypeidExp.toElem() %s\n", e.toChars());
1439 1
            if (Type t = isType(e.obj))
1440
            {
1441 1
                result = getTypeInfo(e.loc, t, irs);
1442 1
                result = el_bin(OPadd, result.Ety, result, el_long(TYsize_t, t.vtinfo.offset));
1443 1
                return;
1444
            }
1445 1
            if (Expression ex = isExpression(e.obj))
1446
            {
1447 1
                auto tc = ex.type.toBasetype().isTypeClass();
1448 1
                assert(tc);
1449
                // generate **classptr to get the classinfo
1450 1
                result = toElem(ex, irs);
1451 1
                result = el_una(OPind,TYnptr,result);
1452 1
                result = el_una(OPind,TYnptr,result);
1453
                // Add extra indirection for interfaces
1454 1
                if (tc.sym.isInterfaceDeclaration())
1455 1
                    result = el_una(OPind,TYnptr,result);
1456 1
                return;
1457
            }
1458 0
            assert(0);
1459
        }
1460

1461
        /***************************************
1462
         */
1463

1464
        override void visit(ThisExp te)
1465
        {
1466
            //printf("ThisExp.toElem()\n");
1467 1
            assert(irs.sthis);
1468

1469 1
            elem *ethis;
1470 1
            if (te.var)
1471
            {
1472 1
                assert(te.var.parent);
1473 1
                FuncDeclaration fd = te.var.toParent2().isFuncDeclaration();
1474 1
                assert(fd);
1475 1
                ethis = getEthis(te.loc, irs, fd);
1476 1
                ethis = fixEthis2(ethis, fd);
1477
            }
1478
            else
1479
            {
1480 1
                ethis = el_var(irs.sthis);
1481 1
                ethis = fixEthis2(ethis, irs.getFunc());
1482
            }
1483

1484 1
            if (te.type.ty == Tstruct)
1485
            {
1486 1
                ethis = el_una(OPind, TYstruct, ethis);
1487 1
                ethis.ET = Type_toCtype(te.type);
1488
            }
1489 1
            elem_setLoc(ethis,te.loc);
1490 1
            result = ethis;
1491
        }
1492

1493
        /***************************************
1494
         */
1495

1496
        override void visit(IntegerExp ie)
1497
        {
1498 1
            elem *e = el_long(totym(ie.type), ie.getInteger());
1499 1
            elem_setLoc(e,ie.loc);
1500 1
            result = e;
1501
        }
1502

1503
        /***************************************
1504
         */
1505

1506
        override void visit(RealExp re)
1507
        {
1508
            //printf("RealExp.toElem(%p) %s\n", re, re.toChars());
1509 1
            elem *e = el_long(TYint, 0);
1510 1
            tym_t ty = totym(re.type.toBasetype());
1511 1
            switch (tybasic(ty))
1512
            {
1513 1
                case TYfloat:
1514 1
                case TYifloat:
1515 1
                    e.EV.Vfloat = cast(float) re.value;
1516 1
                    break;
1517

1518 1
                case TYdouble:
1519 1
                case TYidouble:
1520 1
                    e.EV.Vdouble = cast(double) re.value;
1521 1
                    break;
1522

1523 1
                case TYldouble:
1524 1
                case TYildouble:
1525 1
                    e.EV.Vldouble = re.value;
1526 1
                    break;
1527

1528 0
                default:
1529 0
                    printf("ty = %d, tym = %x, re=%s, re.type=%s, re.type.toBasetype=%s\n",
1530
                           re.type.ty, ty, re.toChars(), re.type.toChars(), re.type.toBasetype().toChars());
1531 0
                    assert(0);
1532
            }
1533 1
            e.Ety = ty;
1534 1
            result = e;
1535
        }
1536

1537
        /***************************************
1538
         */
1539

1540
        override void visit(ComplexExp ce)
1541
        {
1542

1543
            //printf("ComplexExp.toElem(%p) %s\n", ce, ce.toChars());
1544

1545 1
            elem *e = el_long(TYint, 0);
1546 1
            real_t re = ce.value.re;
1547 1
            real_t im = ce.value.im;
1548

1549 1
            tym_t ty = totym(ce.type);
1550 1
            switch (tybasic(ty))
1551
            {
1552 1
                case TYcfloat:
1553
                    union UF { float f; uint i; }
1554 1
                    e.EV.Vcfloat.re = cast(float) re;
1555 1
                    if (CTFloat.isSNaN(re))
1556
                    {
1557 0
                        UF u;
1558 0
                        u.f = e.EV.Vcfloat.re;
1559 0
                        u.i &= 0xFFBFFFFFL;
1560 0
                        e.EV.Vcfloat.re = u.f;
1561
                    }
1562 1
                    e.EV.Vcfloat.im = cast(float) im;
1563 1
                    if (CTFloat.isSNaN(im))
1564
                    {
1565 0
                        UF u;
1566 0
                        u.f = e.EV.Vcfloat.im;
1567 0
                        u.i &= 0xFFBFFFFFL;
1568 0
                        e.EV.Vcfloat.im = u.f;
1569
                    }
1570 1
                    break;
1571

1572 1
                case TYcdouble:
1573
                    union UD { double d; ulong i; }
1574 1
                    e.EV.Vcdouble.re = cast(double) re;
1575 1
                    if (CTFloat.isSNaN(re))
1576
                    {
1577 0
                        UD u;
1578 0
                        u.d = e.EV.Vcdouble.re;
1579 0
                        u.i &= 0xFFF7FFFFFFFFFFFFUL;
1580 0
                        e.EV.Vcdouble.re = u.d;
1581
                    }
1582 1
                    e.EV.Vcdouble.im = cast(double) im;
1583 1
                    if (CTFloat.isSNaN(re))
1584
                    {
1585 0
                        UD u;
1586 0
                        u.d = e.EV.Vcdouble.im;
1587 0
                        u.i &= 0xFFF7FFFFFFFFFFFFUL;
1588 0
                        e.EV.Vcdouble.im = u.d;
1589
                    }
1590 1
                    break;
1591

1592 1
                case TYcldouble:
1593 1
                    e.EV.Vcldouble.re = re;
1594 1
                    e.EV.Vcldouble.im = im;
1595 1
                    break;
1596

1597 0
                default:
1598 0
                    assert(0);
1599
            }
1600 1
            e.Ety = ty;
1601 1
            result = e;
1602
        }
1603

1604
        /***************************************
1605
         */
1606

1607
        override void visit(NullExp ne)
1608
        {
1609 1
            result = el_long(totym(ne.type), 0);
1610
        }
1611

1612
        /***************************************
1613
         */
1614

1615
        override void visit(StringExp se)
1616
        {
1617
            //printf("StringExp.toElem() %s, type = %s\n", se.toChars(), se.type.toChars());
1618

1619 1
            elem *e;
1620 1
            Type tb = se.type.toBasetype();
1621 1
            if (tb.ty == Tarray)
1622
            {
1623 1
                Symbol *si = toStringSymbol(se);
1624 1
                e = el_pair(TYdarray, el_long(TYsize_t, se.numberOfCodeUnits()), el_ptr(si));
1625
            }
1626 1
            else if (tb.ty == Tsarray)
1627
            {
1628 1
                Symbol *si = toStringSymbol(se);
1629 1
                e = el_var(si);
1630 1
                e.Ejty = e.Ety = TYstruct;
1631 1
                e.ET = si.Stype;
1632 1
                e.ET.Tcount++;
1633
            }
1634 1
            else if (tb.ty == Tpointer)
1635
            {
1636 1
                e = el_calloc();
1637 1
                e.Eoper = OPstring;
1638
                // freed in el_free
1639 1
                uint len = cast(uint)((se.numberOfCodeUnits() + 1) * se.sz);
1640 1
                e.EV.Vstring = cast(char *)mem_malloc2(cast(uint)len);
1641 1
                se.writeTo(e.EV.Vstring, true);
1642 1
                e.EV.Vstrlen = len;
1643 1
                e.Ety = TYnptr;
1644
            }
1645
            else
1646
            {
1647 0
                printf("type is %s\n", se.type.toChars());
1648 0
                assert(0);
1649
            }
1650 1
            elem_setLoc(e,se.loc);
1651 1
            result = e;
1652
        }
1653

1654
        override void visit(NewExp ne)
1655
        {
1656
            //printf("NewExp.toElem() %s\n", ne.toChars());
1657 1
            Type t = ne.type.toBasetype();
1658
            //printf("\ttype = %s\n", t.toChars());
1659
            //if (ne.member)
1660
                //printf("\tmember = %s\n", ne.member.toChars());
1661 1
            elem *e;
1662 1
            Type ectype;
1663 1
            if (t.ty == Tclass)
1664
            {
1665 1
                auto tclass = ne.newtype.toBasetype().isTypeClass();
1666 1
                assert(tclass);
1667 1
                ClassDeclaration cd = tclass.sym;
1668

1669
                /* Things to do:
1670
                 * 1) ex: call allocator
1671
                 * 2) ey: set vthis for nested classes
1672
                 * 2) ew: set vthis2 for nested classes
1673
                 * 3) ez: call constructor
1674
                 */
1675

1676 1
                elem *ex = null;
1677 1
                elem *ey = null;
1678 1
                elem *ew = null;
1679 1
                elem *ezprefix = null;
1680 1
                elem *ez = null;
1681

1682 1
                if (ne.allocator || ne.onstack)
1683
                {
1684 1
                    if (ne.onstack)
1685
                    {
1686
                        /* Create an instance of the class on the stack,
1687
                         * and call it stmp.
1688
                         * Set ex to be the &stmp.
1689
                         */
1690 1
                        .type *tc = type_struct_class(tclass.sym.toChars(),
1691
                                tclass.sym.alignsize, tclass.sym.structsize,
1692
                                null, null,
1693
                                false, false, true, false);
1694 1
                        tc.Tcount--;
1695 1
                        Symbol *stmp = symbol_genauto(tc);
1696 1
                        ex = el_ptr(stmp);
1697
                    }
1698
                    else
1699
                    {
1700 0
                        ex = el_var(toSymbol(ne.allocator));
1701 0
                        ex = callfunc(ne.loc, irs, 1, ne.type, ex, ne.allocator.type,
1702
                                ne.allocator, ne.allocator.type, null, ne.newargs);
1703
                    }
1704

1705 1
                    Symbol *si = toInitializer(tclass.sym);
1706 1
                    elem *ei = el_var(si);
1707

1708 1
                    if (cd.isNested())
1709
                    {
1710 1
                        ey = el_same(&ex);
1711 1
                        ez = el_copytree(ey);
1712 1
                        if (cd.vthis2)
1713 0
                            ew = el_copytree(ey);
1714
                    }
1715 1
                    else if (ne.member)
1716 1
                        ez = el_same(&ex);
1717

1718 1
                    ex = el_una(OPind, TYstruct, ex);
1719 1
                    ex = elAssign(ex, ei, null, Type_toCtype(tclass).Tnext);
1720 1
                    ex = el_una(OPaddr, TYnptr, ex);
1721 1
                    ectype = tclass;
1722
                }
1723
                else
1724
                {
1725 1
                    Symbol *csym = toSymbol(cd);
1726 1
                    const rtl = global.params.ehnogc && ne.thrownew ? RTLSYM_NEWTHROW : RTLSYM_NEWCLASS;
1727 1
                    ex = el_bin(OPcall,TYnptr,el_var(getRtlsym(rtl)),el_ptr(csym));
1728 1
                    toTraceGC(irs, ex, ne.loc);
1729 1
                    ectype = null;
1730

1731 1
                    if (cd.isNested())
1732
                    {
1733 1
                        ey = el_same(&ex);
1734 1
                        ez = el_copytree(ey);
1735 1
                        if (cd.vthis2)
1736 1
                            ew = el_copytree(ey);
1737
                    }
1738 1
                    else if (ne.member)
1739 1
                        ez = el_same(&ex);
1740
                    //elem_print(ex);
1741
                    //elem_print(ey);
1742
                    //elem_print(ez);
1743
                }
1744

1745 1
                if (ne.thisexp)
1746
                {
1747 1
                    ClassDeclaration cdthis = ne.thisexp.type.isClassHandle();
1748 1
                    assert(cdthis);
1749
                    //printf("cd = %s\n", cd.toChars());
1750
                    //printf("cdthis = %s\n", cdthis.toChars());
1751 1
                    assert(cd.isNested());
1752 1
                    int offset = 0;
1753 1
                    Dsymbol cdp = cd.toParentLocal();     // class we're nested in
1754

1755
                    //printf("member = %p\n", member);
1756
                    //printf("cdp = %s\n", cdp.toChars());
1757
                    //printf("cdthis = %s\n", cdthis.toChars());
1758 1
                    if (cdp != cdthis)
1759
                    {
1760 1
                        int i = cdp.isClassDeclaration().isBaseOf(cdthis, &offset);
1761 1
                        assert(i);
1762
                    }
1763 1
                    elem *ethis = toElem(ne.thisexp, irs);
1764 1
                    if (offset)
1765 0
                        ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, offset));
1766

1767 1
                    if (!cd.vthis)
1768
                    {
1769 0
                        ne.error("forward reference to `%s`", cd.toChars());
1770
                    }
1771
                    else
1772
                    {
1773 1
                        ey = el_bin(OPadd, TYnptr, ey, el_long(TYsize_t, cd.vthis.offset));
1774 1
                        ey = el_una(OPind, TYnptr, ey);
1775 1
                        ey = el_bin(OPeq, TYnptr, ey, ethis);
1776
                    }
1777
                    //printf("ex: "); elem_print(ex);
1778
                    //printf("ey: "); elem_print(ey);
1779
                    //printf("ez: "); elem_print(ez);
1780
                }
1781 1
                else if (cd.isNested())
1782
                {
1783
                    /* Initialize cd.vthis:
1784
                     *  *(ey + cd.vthis.offset) = this;
1785
                     */
1786 1
                    ey = setEthis(ne.loc, irs, ey, cd);
1787
                }
1788

1789 1
                if (cd.vthis2)
1790
                {
1791
                    /* Initialize cd.vthis2:
1792
                     *  *(ew + cd.vthis2.offset) = this;
1793
                     */
1794 1
                    assert(ew);
1795 1
                    ew = setEthis(ne.loc, irs, ew, cd, true);
1796
                }
1797

1798 1
                if (ne.member)
1799
                {
1800 1
                    if (ne.argprefix)
1801 1
                        ezprefix = toElem(ne.argprefix, irs);
1802
                    // Call constructor
1803 1
                    ez = callfunc(ne.loc, irs, 1, ne.type, ez, ectype, ne.member, ne.member.type, null, ne.arguments);
1804
                }
1805

1806 1
                e = el_combine(ex, ey);
1807 1
                e = el_combine(e, ew);
1808 1
                e = el_combine(e, ezprefix);
1809 1
                e = el_combine(e, ez);
1810
            }
1811 1
            else if (t.ty == Tpointer && t.nextOf().toBasetype().ty == Tstruct)
1812
            {
1813 1
                t = ne.newtype.toBasetype();
1814 1
                TypeStruct tclass = t.isTypeStruct();
1815 1
                StructDeclaration sd = tclass.sym;
1816

1817
                /* Things to do:
1818
                 * 1) ex: call allocator
1819
                 * 2) ey: set vthis for nested structs
1820
                 * 2) ew: set vthis2 for nested structs
1821
                 * 3) ez: call constructor
1822
                 */
1823

1824 1
                elem *ex = null;
1825 1
                elem *ey = null;
1826 1
                elem *ew = null;
1827 1
                elem *ezprefix = null;
1828 1
                elem *ez = null;
1829

1830 1
                if (ne.allocator)
1831
                {
1832

1833 0
                    ex = el_var(toSymbol(ne.allocator));
1834 0
                    ex = callfunc(ne.loc, irs, 1, ne.type, ex, ne.allocator.type,
1835
                                ne.allocator, ne.allocator.type, null, ne.newargs);
1836

1837 0
                    ectype = tclass;
1838
                }
1839
                else
1840
                {
1841
                    // call _d_newitemT(ti)
1842 1
                    e = getTypeInfo(ne.loc, ne.newtype, irs);
1843

1844 1
                    int rtl = t.isZeroInit(Loc.initial) ? RTLSYM_NEWITEMT : RTLSYM_NEWITEMIT;
1845 1
                    ex = el_bin(OPcall,TYnptr,el_var(getRtlsym(rtl)),e);
1846 1
                    toTraceGC(irs, ex, ne.loc);
1847

1848 1
                    ectype = null;
1849
                }
1850

1851 1
                elem *ev = el_same(&ex);
1852

1853 1
                if (ne.argprefix)
1854 0
                        ezprefix = toElem(ne.argprefix, irs);
1855 1
                if (ne.member)
1856
                {
1857 1
                    if (sd.isNested())
1858
                    {
1859 1
                        ey = el_copytree(ev);
1860

1861
                        /* Initialize sd.vthis:
1862
                         *  *(ey + sd.vthis.offset) = this;
1863
                         */
1864 1
                        ey = setEthis(ne.loc, irs, ey, sd);
1865 1
                        if (sd.vthis2)
1866
                        {
1867
                            /* Initialize sd.vthis2:
1868
                             *  *(ew + sd.vthis2.offset) = this1;
1869
                             */
1870 0
                            ew = el_copytree(ev);
1871 0
                            ew = setEthis(ne.loc, irs, ew, sd, true);
1872
                        }
1873
                    }
1874

1875
                    // Call constructor
1876 1
                    ez = callfunc(ne.loc, irs, 1, ne.type, ev, ectype, ne.member, ne.member.type, null, ne.arguments);
1877
                    /* Structs return a ref, which gets automatically dereferenced.
1878
                     * But we want a pointer to the instance.
1879
                     */
1880 1
                    ez = el_una(OPaddr, TYnptr, ez);
1881
                }
1882
                else
1883
                {
1884 1
                    StructLiteralExp sle = StructLiteralExp.create(ne.loc, sd, ne.arguments, t);
1885 1
                    ez = toElemStructLit(sle, irs, TOK.construct, ev.EV.Vsym, false);
1886
                }
1887
                //elem_print(ex);
1888
                //elem_print(ey);
1889
                //elem_print(ez);
1890

1891 1
                e = el_combine(ex, ey);
1892 1
                e = el_combine(e, ew);
1893 1
                e = el_combine(e, ezprefix);
1894 1
                e = el_combine(e, ez);
1895
            }
1896 1
            else if (auto tda = t.isTypeDArray())
1897
            {
1898 1
                elem *ezprefix = ne.argprefix ? toElem(ne.argprefix, irs) : null;
1899

1900 1
                assert(ne.arguments && ne.arguments.dim >= 1);
1901 1
                if (ne.arguments.dim == 1)
1902
                {
1903
                    // Single dimension array allocations
1904 1
                    Expression arg = (*ne.arguments)[0]; // gives array length
1905 1
                    e = toElem(arg, irs);
1906

1907
                    // call _d_newT(ti, arg)
1908 1
                    e = el_param(e, getTypeInfo(ne.loc, ne.type, irs));
1909 1
                    int rtl = tda.next.isZeroInit(Loc.initial) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1910 1
                    e = el_bin(OPcall,TYdarray,el_var(getRtlsym(rtl)),e);
1911 1
                    toTraceGC(irs, e, ne.loc);
1912
                }
1913
                else
1914
                {
1915
                    // Multidimensional array allocations
1916 1
                    foreach (i; 0 .. ne.arguments.dim)
1917
                    {
1918 1
                        assert(t.ty == Tarray);
1919 1
                        t = t.nextOf();
1920 1
                        assert(t);
1921
                    }
1922

1923
                    // Allocate array of dimensions on the stack
1924 1
                    Symbol *sdata = null;
1925 1
                    elem *earray = ExpressionsToStaticArray(ne.loc, ne.arguments, &sdata);
1926

1927 1
                    e = el_pair(TYdarray, el_long(TYsize_t, ne.arguments.dim), el_ptr(sdata));
1928 1
                    if (config.exe == EX_WIN64)
1929 0
                        e = addressElem(e, Type.tsize_t.arrayOf());
1930 1
                    e = el_param(e, getTypeInfo(ne.loc, ne.type, irs));
1931 1
                    int rtl = t.isZeroInit(Loc.initial) ? RTLSYM_NEWARRAYMTX : RTLSYM_NEWARRAYMITX;
1932 1
                    e = el_bin(OPcall,TYdarray,el_var(getRtlsym(rtl)),e);
1933 1
                    toTraceGC(irs, e, ne.loc);
1934

1935 1
                    e = el_combine(earray, e);
1936
                }
1937 1
                e = el_combine(ezprefix, e);
1938
            }
1939 1
            else if (auto tp = t.isTypePointer())
1940
            {
1941 1
                elem *ezprefix = ne.argprefix ? toElem(ne.argprefix, irs) : null;
1942

1943
                // call _d_newitemT(ti)
1944 1
                e = getTypeInfo(ne.loc, ne.newtype, irs);
1945

1946 1
                int rtl = tp.next.isZeroInit(Loc.initial) ? RTLSYM_NEWITEMT : RTLSYM_NEWITEMIT;
1947 1
                e = el_bin(OPcall,TYnptr,el_var(getRtlsym(rtl)),e);
1948 1
                toTraceGC(irs, e, ne.loc);
1949

1950 1
                if (ne.arguments && ne.arguments.dim == 1)
1951
                {
1952
                    /* ezprefix, ts=_d_newitemT(ti), *ts=arguments[0], ts
1953
                     */
1954 1
                    elem *e2 = toElem((*ne.arguments)[0], irs);
1955

1956 1
                    Symbol *ts = symbol_genauto(Type_toCtype(tp));
1957 1
                    elem *eeq1 = el_bin(OPeq, TYnptr, el_var(ts), e);
1958

1959 1
                    elem *ederef = el_una(OPind, e2.Ety, el_var(ts));
1960 1
                    elem *eeq2 = el_bin(OPeq, e2.Ety, ederef, e2);
1961

1962 1
                    e = el_combine(eeq1, eeq2);
1963 1
                    e = el_combine(e, el_var(ts));
1964
                    //elem_print(e);
1965
                }
1966 1
                e = el_combine(ezprefix, e);
1967
            }
1968
            else
1969
            {
1970 0
                ne.error("Internal Compiler Error: cannot new type `%s`\n", t.toChars());
1971 0
                assert(0);
1972
            }
1973

1974 1
            elem_setLoc(e,ne.loc);
1975 1
            result = e;
1976
        }
1977

1978
        //////////////////////////// Unary ///////////////////////////////
1979

1980
        /***************************************
1981
         */
1982

1983
        override void visit(NegExp ne)
1984
        {
1985 1
            elem *e = toElem(ne.e1, irs);
1986 1
            Type tb1 = ne.e1.type.toBasetype();
1987

1988 1
            assert(tb1.ty != Tarray && tb1.ty != Tsarray);
1989

1990 1
            switch (tb1.ty)
1991
            {
1992 1
                case Tvector:
1993
                {
1994
                    // rewrite (-e) as (0-e)
1995 1
                    elem *ez = el_calloc();
1996 1
                    ez.Eoper = OPconst;
1997 1
                    ez.Ety = e.Ety;
1998 1
                    ez.EV.Vcent.lsw = 0;
1999 1
                    ez.EV.Vcent.msw = 0;
2000 1
                    e = el_bin(OPmin, totym(ne.type), ez, e);
2001 1
                    break;
2002
                }
2003

2004 1
                default:
2005 1
                    e = el_una(OPneg, totym(ne.type), e);
2006 1
                    break;
2007
            }
2008

2009 1
            elem_setLoc(e,ne.loc);
2010 1
            result = e;
2011
        }
2012

2013
        /***************************************
2014
         */
2015

2016
        override void visit(ComExp ce)
2017
        {
2018 1
            elem *e1 = toElem(ce.e1, irs);
2019 1
            Type tb1 = ce.e1.type.toBasetype();
2020 1
            tym_t ty = totym(ce.type);
2021

2022 1
            assert(tb1.ty != Tarray && tb1.ty != Tsarray);
2023

2024 1
            elem *e;
2025 1
            switch (tb1.ty)
2026
            {
2027 0
                case Tbool:
2028 0
                    e = el_bin(OPxor, ty, e1, el_long(ty, 1));
2029 0
                    break;
2030

2031 1
                case Tvector:
2032
                {
2033
                    // rewrite (~e) as (e^~0)
2034 1
                    elem *ec = el_calloc();
2035 1
                    ec.Eoper = OPconst;
2036 1
                    ec.Ety = e1.Ety;
2037 1
                    ec.EV.Vcent.lsw = ~0L;
2038 1
                    ec.EV.Vcent.msw = ~0L;
2039 1
                    e = el_bin(OPxor, ty, e1, ec);
2040 1
                    break;
2041
                }
2042

2043 1
                default:
2044 1
                    e = el_una(OPcom,ty,e1);
2045 1
                    break;
2046
            }
2047

2048 1
            elem_setLoc(e,ce.loc);
2049 1
            result = e;
2050
        }
2051

2052
        /***************************************
2053
         */
2054

2055
        override void visit(NotExp ne)
2056
        {
2057 1
            elem *e = el_una(OPnot, totym(ne.type), toElem(ne.e1, irs));
2058 1
            elem_setLoc(e,ne.loc);
2059 1
            result = e;
2060
        }
2061

2062

2063
        /***************************************
2064
         */
2065

2066
        override void visit(HaltExp he)
2067
        {
2068 1
            result = genHalt(he.loc);
2069
        }
2070

2071
        /********************************************
2072
         */
2073

2074
        override void visit(AssertExp ae)
2075
        {
2076
            // https://dlang.org/spec/expression.html#assert_expressions
2077
            //printf("AssertExp.toElem() %s\n", toChars());
2078 1
            elem *e;
2079 1
            if (irs.params.useAssert == CHECKENABLE.on)
2080
            {
2081 1
                if (irs.params.checkAction == CHECKACTION.C)
2082
                {
2083 1
                    auto econd = toElem(ae.e1, irs);
2084 1
                    auto ea = callCAssert(irs, ae.e1.loc, ae.e1, ae.msg, null);
2085 1
                    auto eo = el_bin(OPoror, TYvoid, econd, ea);
2086 1
                    elem_setLoc(eo, ae.loc);
2087 1
                    result = eo;
2088 1
                    return;
2089
                }
2090

2091 1
                if (irs.params.checkAction == CHECKACTION.halt)
2092
                {
2093
                    /* Generate:
2094
                     *  ae.e1 || halt
2095
                     */
2096 0
                    auto econd = toElem(ae.e1, irs);
2097 0
                    auto ea = genHalt(ae.loc);
2098 0
                    auto eo = el_bin(OPoror, TYvoid, econd, ea);
2099 0
                    elem_setLoc(eo, ae.loc);
2100 0
                    result = eo;
2101 0
                    return;
2102
                }
2103

2104 1
                e = toElem(ae.e1, irs);
2105 1
                Symbol *ts = null;
2106 1
                elem *einv = null;
2107 1
                Type t1 = ae.e1.type.toBasetype();
2108

2109 1
                FuncDeclaration inv;
2110

2111
                // If e1 is a class object, call the class invariant on it
2112 1
                if (irs.params.useInvariants == CHECKENABLE.on && t1.ty == Tclass &&
2113 1
                    !(cast(TypeClass)t1).sym.isInterfaceDeclaration() &&
2114 1
                    !(cast(TypeClass)t1).sym.isCPPclass())
2115
                {
2116 1
                    ts = symbol_genauto(Type_toCtype(t1));
2117 1
                    einv = el_bin(OPcall, TYvoid, el_var(getRtlsym(RTLSYM_DINVARIANT)), el_var(ts));
2118
                }
2119 1
                else if (irs.params.useInvariants == CHECKENABLE.on &&
2120 1
                    t1.ty == Tpointer &&
2121 1
                    t1.nextOf().ty == Tstruct &&
2122 1
                    (inv = (cast(TypeStruct)t1.nextOf()).sym.inv) !is null)
2123
                {
2124
                    // If e1 is a struct object, call the struct invariant on it
2125 1
                    ts = symbol_genauto(Type_toCtype(t1));
2126 1
                    einv = callfunc(ae.loc, irs, 1, inv.type.nextOf(), el_var(ts), ae.e1.type, inv, inv.type, null, null);
2127
                }
2128

2129
                // Construct: (e1 || ModuleAssert(line))
2130 1
                Module m = cast(Module)irs.blx._module;
2131 1
                char *mname = cast(char*)m.srcfile.toChars();
2132

2133
                //printf("filename = '%s'\n", ae.loc.filename);
2134
                //printf("module = '%s'\n", m.srcfile.toChars());
2135

2136
                /* Determine if we are in a unittest
2137
                 */
2138 1
                FuncDeclaration fd = irs.getFunc();
2139 1
                UnitTestDeclaration ud = fd ? fd.isUnitTestDeclaration() : null;
2140

2141
                /* If the source file name has changed, probably due
2142
                 * to a #line directive.
2143
                 */
2144 1
                elem *ea;
2145 1
                if (ae.loc.filename && (ae.msg || strcmp(ae.loc.filename, mname) != 0))
2146
                {
2147 1
                    const(char)* id = ae.loc.filename;
2148 1
                    size_t len = strlen(id);
2149 1
                    Symbol *si = toStringSymbol(id, len, 1);
2150 1
                    elem *efilename = el_pair(TYdarray, el_long(TYsize_t, len), el_ptr(si));
2151 1
                    if (config.exe == EX_WIN64)
2152 0
                        efilename = addressElem(efilename, Type.tstring, true);
2153

2154 1
                    if (ae.msg)
2155
                    {
2156
                        /* https://issues.dlang.org/show_bug.cgi?id=8360
2157
                         * If the condition is evalated to true,
2158
                         * msg is not evaluated at all. so should use
2159
                         * toElemDtor(msg, irs) instead of toElem(msg, irs).
2160
                         */
2161 1
                        elem *emsg = toElemDtor(ae.msg, irs);
2162 1
                        emsg = array_toDarray(ae.msg.type, emsg);
2163 1
                        if (config.exe == EX_WIN64)
2164 0
                            emsg = addressElem(emsg, Type.tvoid.arrayOf(), false);
2165

2166 1
                        ea = el_var(getRtlsym(ud ? RTLSYM_DUNITTEST_MSG : RTLSYM_DASSERT_MSG));
2167 1
                        ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, ae.loc.linnum), efilename, emsg, null));
2168
                    }
2169
                    else
2170
                    {
2171 1
                        ea = el_var(getRtlsym(ud ? RTLSYM_DUNITTEST : RTLSYM_DASSERT));
2172 1
                        ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, ae.loc.linnum), efilename));
2173
                    }
2174
                }
2175
                else
2176
                {
2177 1
                    auto eassert = el_var(getRtlsym(ud ? RTLSYM_DUNITTESTP : RTLSYM_DASSERTP));
2178 1
                    auto efile = toEfilenamePtr(m);
2179 1
                    auto eline = el_long(TYint, ae.loc.linnum);
2180 1
                    ea = el_bin(OPcall, TYvoid, eassert, el_param(eline, efile));
2181
                }
2182 1
                if (einv)
2183
                {
2184
                    // tmp = e, e || assert, e.inv
2185 1
                    elem *eassign = el_bin(OPeq, e.Ety, el_var(ts), e);
2186 1
                    e = el_combine(eassign, el_bin(OPoror, TYvoid, el_var(ts), ea));
2187 1
                    e = el_combine(e, einv);
2188
                }
2189
                else
2190 1
                    e = el_bin(OPoror,TYvoid,e,ea);
2191
            }
2192
            else
2193
            {
2194
                // BUG: should replace assert(0); with a HLT instruction
2195 1
                e = el_long(TYint, 0);
2196
            }
2197 1
            elem_setLoc(e,ae.loc);
2198 1
            result = e;
2199
        }
2200

2201
        override void visit(PostExp pe)
2202
        {
2203
            //printf("PostExp.toElem() '%s'\n", pe.toChars());
2204 1
            elem *e = toElem(pe.e1, irs);
2205 1
            elem *einc = toElem(pe.e2, irs);
2206 1
            e = el_bin((pe.op == TOK.plusPlus) ? OPpostinc : OPpostdec,
2207
                        e.Ety,e,einc);
2208 1
            elem_setLoc(e,pe.loc);
2209 1
            result = e;
2210
        }
2211

2212
        //////////////////////////// Binary ///////////////////////////////
2213

2214
        /********************************************
2215
         */
2216
        elem *toElemBin(BinExp be, int op)
2217
        {
2218
            //printf("toElemBin() '%s'\n", be.toChars());
2219

2220 1
            Type tb1 = be.e1.type.toBasetype();
2221 1
            Type tb2 = be.e2.type.toBasetype();
2222

2223 1
            assert(!((tb1.ty == Tarray || tb1.ty == Tsarray ||
2224 1
                      tb2.ty == Tarray || tb2.ty == Tsarray) &&
2225 0
                     tb2.ty != Tvoid &&
2226 0
                     op != OPeq && op != OPandand && op != OPoror));
2227

2228 1
            tym_t tym = totym(be.type);
2229

2230 1
            elem *el = toElem(be.e1, irs);
2231 1
            elem *er = toElem(be.e2, irs);
2232 1
            elem *e = el_bin(op,tym,el,er);
2233

2234 1
            elem_setLoc(e,be.loc);
2235 1
            return e;
2236
        }
2237

2238
        elem *toElemBinAssign(BinAssignExp be, int op)
2239
        {
2240
            //printf("toElemBinAssign() '%s'\n", be.toChars());
2241

2242 1
            Type tb1 = be.e1.type.toBasetype();
2243 1
            Type tb2 = be.e2.type.toBasetype();
2244

2245 1
            assert(!((tb1.ty == Tarray || tb1.ty == Tsarray ||
2246 1
                      tb2.ty == Tarray || tb2.ty == Tsarray) &&
2247 0
                     tb2.ty != Tvoid &&
2248 0
                     op != OPeq && op != OPandand && op != OPoror));
2249

2250 1
            tym_t tym = totym(be.type);
2251

2252 1
            elem *el;
2253 1
            elem *ev;
2254 1
            if (be.e1.op == TOK.cast_)
2255
            {
2256 1
                int depth = 0;
2257 1
                Expression e1 = be.e1;
2258 1
                while (e1.op == TOK.cast_)
2259
                {
2260 1
                    ++depth;
2261 1
                    e1 = (cast(CastExp)e1).e1;
2262
                }
2263 1
                assert(depth > 0);
2264

2265 1
                el = toElem(e1, irs);
2266 1
                el = addressElem(el, e1.type.pointerTo());
2267 1
                ev = el_same(&el);
2268

2269 1
                el = el_una(OPind, totym(e1.type), el);
2270

2271 1
                ev = el_una(OPind, tym, ev);
2272

2273 1
                foreach (d; 0 .. depth)
2274
                {
2275 1
                    e1 = be.e1;
2276 1
                    foreach (i; 1 .. depth - d)
2277 1
                        e1 = (cast(CastExp)e1).e1;
2278

2279 1
                    el = toElemCast(cast(CastExp)e1, el, true);
2280
                }
2281
            }
2282
            else
2283
            {
2284 1
                el = toElem(be.e1, irs);
2285 1
                el = addressElem(el, be.e1.type.pointerTo());
2286 1
                ev = el_same(&el);
2287

2288 1
                el = el_una(OPind, tym, el);
2289 1
                ev = el_una(OPind, tym, ev);
2290
            }
2291 1
            elem *er = toElem(be.e2, irs);
2292 1
            elem *e = el_bin(op, tym, el, er);
2293 1
            e = el_combine(e, ev);
2294

2295 1
            elem_setLoc(e,be.loc);
2296 1
            return e;
2297
        }
2298

2299
        /***************************************
2300
         */
2301

2302
        override void visit(AddExp e)
2303
        {
2304 1
            result = toElemBin(e, OPadd);
2305
        }
2306

2307
        /***************************************
2308
         */
2309

2310
        override void visit(MinExp e)
2311
        {
2312 1
            result = toElemBin(e, OPmin);
2313
        }
2314

2315
        /*****************************************
2316
         * Evaluate elem and convert to dynamic array suitable for a function argument.
2317
         */
2318
        elem *eval_Darray(Expression e)
2319
        {
2320 1
            elem *ex = toElem(e, irs);
2321 1
            ex = array_toDarray(e.type, ex);
2322 1
            if (config.exe == EX_WIN64)
2323
            {
2324 0
                ex = addressElem(ex, Type.tvoid.arrayOf(), false);
2325
            }
2326 1
            return ex;
2327
        }
2328

2329
        /***************************************
2330
         * http://dlang.org/spec/expression.html#cat_expressions
2331
         */
2332

2333
        override void visit(CatExp ce)
2334
        {
2335
            /* Do this check during code gen rather than semantic() because concatenation is
2336
             * allowed in CTFE, and cannot distinguish that in semantic().
2337
             */
2338 1
            if (irs.params.betterC)
2339
            {
2340 1
                error(ce.loc, "array concatenation of expression `%s` requires the GC which is not available with -betterC", ce.toChars());
2341 1
                result = el_long(TYint, 0);
2342 1
                return;
2343
            }
2344

2345 1
            Type tb1 = ce.e1.type.toBasetype();
2346 1
            Type tb2 = ce.e2.type.toBasetype();
2347

2348 1
            Type ta = (tb1.ty == Tarray || tb1.ty == Tsarray) ? tb1 : tb2;
2349

2350 1
            elem *e;
2351 1
            if (ce.e1.op == TOK.concatenate)
2352
            {
2353 1
                CatExp ex = ce;
2354

2355
                // Flatten ((a ~ b) ~ c) to [a, b, c]
2356 1
                Elems elems;
2357 1
                elems.shift(array_toDarray(ex.e2.type, toElem(ex.e2, irs)));
2358
                do
2359
                {
2360 1
                    ex = cast(CatExp)ex.e1;
2361 1
                    elems.shift(array_toDarray(ex.e2.type, toElem(ex.e2, irs)));
2362 1
                } while (ex.e1.op == TOK.concatenate);
2363 1
                elems.shift(array_toDarray(ex.e1.type, toElem(ex.e1, irs)));
2364

2365
                // We can't use ExpressionsToStaticArray because each exp needs
2366
                // to have array_toDarray called on it first, as some might be
2367
                // single elements instead of arrays.
2368 1
                Symbol *sdata;
2369 1
                elem *earr = ElemsToStaticArray(ce.loc, ce.type, &elems, &sdata);
2370

2371 1
                elem *ep = el_pair(TYdarray, el_long(TYsize_t, elems.dim), el_ptr(sdata));
2372 1
                if (config.exe == EX_WIN64)
2373 0
                    ep = addressElem(ep, Type.tvoid.arrayOf());
2374 1
                ep = el_param(ep, getTypeInfo(ce.loc, ta, irs));
2375 1
                e = el_bin(OPcall, TYdarray, el_var(getRtlsym(RTLSYM_ARRAYCATNTX)), ep);
2376 1
                toTraceGC(irs, e, ce.loc);
2377 1
                e = el_combine(earr, e);
2378
            }
2379
            else
2380
            {
2381 1
                elem *e1 = eval_Darray(ce.e1);
2382 1
                elem *e2 = eval_Darray(ce.e2);
2383 1
                elem *ep = el_params(e2, e1, getTypeInfo(ce.loc, ta, irs), null);
2384 1
                e = el_bin(OPcall, TYdarray, el_var(getRtlsym(RTLSYM_ARRAYCATT)), ep);
2385 1
                toTraceGC(irs, e, ce.loc);
2386
            }
2387 1
            elem_setLoc(e,ce.loc);
2388 1
            result = e;
2389
        }
2390

2391
        /***************************************
2392
         */
2393

2394
        override void visit(MulExp e)
2395
        {
2396 1
            result = toElemBin(e, OPmul);
2397
        }
2398

2399
        /************************************
2400
         */
2401

2402
        override void visit(DivExp e)
2403
        {
2404 1
            result = toElemBin(e, OPdiv);
2405
        }
2406

2407
        /***************************************
2408
         */
2409

2410
        override void visit(ModExp e)
2411
        {
2412 1
            result = toElemBin(e, OPmod);
2413
        }
2414

2415
        /***************************************
2416
         */
2417

2418
        override void visit(CmpExp ce)
2419
        {
2420
            //printf("CmpExp.toElem() %s\n", ce.toChars());
2421

2422 1
            OPER eop;
2423 1
            Type t1 = ce.e1.type.toBasetype();
2424 1
            Type t2 = ce.e2.type.toBasetype();
2425

2426 1
            switch (ce.op)
2427
            {
2428 1
                case TOK.lessThan:     eop = OPlt;     break;
2429 1
                case TOK.greaterThan:     eop = OPgt;     break;
2430 1
                case TOK.lessOrEqual:     eop = OPle;     break;
2431 1
                case TOK.greaterOrEqual:     eop = OPge;     break;
2432 0
                case TOK.equal:  eop = OPeqeq;   break;
2433 0
                case TOK.notEqual: eop = OPne;   break;
2434

2435 0
                default:
2436 0
                    printf("%s\n", ce.toChars());
2437 0
                    assert(0);
2438
            }
2439 1
            if (!t1.isfloating())
2440
            {
2441
                // Convert from floating point compare to equivalent
2442
                // integral compare
2443 1
                eop = cast(OPER)rel_integral(eop);
2444
            }
2445 1
            elem *e;
2446 1
            if (cast(int)eop > 1 && t1.ty == Tclass && t2.ty == Tclass)
2447
            {
2448
                // Should have already been lowered
2449 0
                assert(0);
2450
            }
2451 1
            else if (cast(int)eop > 1 &&
2452 1
                (t1.ty == Tarray || t1.ty == Tsarray) &&
2453 0
                (t2.ty == Tarray || t2.ty == Tsarray))
2454
            {
2455
                // This codepath was replaced by lowering during semantic
2456
                // to object.__cmp in druntime.
2457 0
                assert(0);
2458
            }
2459
            else
2460
            {
2461 1
                if (cast(int)eop <= 1)
2462
                {
2463
                    /* The result is determinate, create:
2464
                     *   (e1 , e2) , eop
2465
                     */
2466 0
                    e = toElemBin(ce,OPcomma);
2467 0
                    e = el_bin(OPcomma,e.Ety,e,el_long(e.Ety,cast(int)eop));
2468
                }
2469
                else
2470 1
                    e = toElemBin(ce,eop);
2471
            }
2472 1
            result = e;
2473
        }
2474

2475
        override void visit(EqualExp ee)
2476
        {
2477
            //printf("EqualExp.toElem() %s\n", ee.toChars());
2478

2479 1
            Type t1 = ee.e1.type.toBasetype();
2480 1
            Type t2 = ee.e2.type.toBasetype();
2481

2482 1
            OPER eop;
2483 1
            switch (ee.op)
2484
            {
2485 1
                case TOK.equal:          eop = OPeqeq;   break;
2486 1
                case TOK.notEqual:       eop = OPne;     break;
2487 0
                default:
2488 0
                    printf("%s\n", ee.toChars());
2489 0
                    assert(0);
2490
            }
2491

2492
            //printf("EqualExp.toElem()\n");
2493 1
            elem *e;
2494 1
            if (t1.ty == Tstruct)
2495
            {
2496
                // Rewritten to IdentityExp or memberwise-compare
2497 0
                assert(0);
2498
            }
2499 1
            else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
2500 1
                     (t2.ty == Tarray || t2.ty == Tsarray))
2501
            {
2502 1
                Type telement  = t1.nextOf().toBasetype();
2503 1
                Type telement2 = t2.nextOf().toBasetype();
2504

2505 1
                if ((telement.isintegral() || telement.ty == Tvoid) && telement.ty == telement2.ty)
2506
                {
2507
                    // Optimize comparisons of arrays of basic types
2508
                    // For arrays of integers/characters, and void[],
2509
                    // replace druntime call with:
2510
                    // For a==b: a.length==b.length && (a.length == 0 || memcmp(a.ptr, b.ptr, size)==0)
2511
                    // For a!=b: a.length!=b.length || (a.length != 0 || memcmp(a.ptr, b.ptr, size)!=0)
2512
                    // size is a.length*sizeof(a[0]) for dynamic arrays, or sizeof(a) for static arrays.
2513

2514 1
                    elem* earr1 = toElem(ee.e1, irs);
2515 1
                    elem* earr2 = toElem(ee.e2, irs);
2516 1
                    elem* eptr1, eptr2; // Pointer to data, to pass to memcmp
2517 1
                    elem* elen1, elen2; // Length, for comparison
2518 1
                    elem* esiz1, esiz2; // Data size, to pass to memcmp
2519 1
                    d_uns64 sz = telement.size(); // Size of one element
2520

2521 1
                    if (t1.ty == Tarray)
2522
                    {
2523 1
                        elen1 = el_una(irs.params.is64bit ? OP128_64 : OP64_32, TYsize_t, el_same(&earr1));
2524 1
                        esiz1 = el_bin(OPmul, TYsize_t, el_same(&elen1), el_long(TYsize_t, sz));
2525 1
                        eptr1 = array_toPtr(t1, el_same(&earr1));
2526
                    }
2527
                    else
2528
                    {
2529 1
                        elen1 = el_long(TYsize_t, (cast(TypeSArray)t1).dim.toInteger());
2530 1
                        esiz1 = el_long(TYsize_t, t1.size());
2531 1
                        earr1 = addressElem(earr1, t1);
2532 1
                        eptr1 = el_same(&earr1);
2533
                    }
2534

2535 1
                    if (t2.ty == Tarray)
2536
                    {
2537 1
                        elen2 = el_una(irs.params.is64bit ? OP128_64 : OP64_32, TYsize_t, el_same(&earr2));
2538 1
                        esiz2 = el_bin(OPmul, TYsize_t, el_same(&elen2), el_long(TYsize_t, sz));
2539 1
                        eptr2 = array_toPtr(t2, el_same(&earr2));
2540
                    }
2541
                    else
2542
                    {
2543 1
                        elen2 = el_long(TYsize_t, (cast(TypeSArray)t2).dim.toInteger());
2544 1
                        esiz2 = el_long(TYsize_t, t2.size());
2545 1
                        earr2 = addressElem(earr2, t2);
2546 1
                        eptr2 = el_same(&earr2);
2547
                    }
2548

2549 1
                    elem *esize = t2.ty == Tsarray ? esiz2 : esiz1;
2550

2551 1
                    e = el_param(eptr1, eptr2);
2552 1
                    e = el_bin(OPmemcmp, TYint, e, esize);
2553 1
                    e = el_bin(eop, TYint, e, el_long(TYint, 0));
2554

2555 1
                    elem *elen = t2.ty == Tsarray ? elen2 : elen1;
2556 1
                    elem *esizecheck = el_bin(eop, TYint, el_same(&elen), el_long(TYsize_t, 0));
2557 1
                    e = el_bin(ee.op == TOK.equal ? OPoror : OPandand, TYint, esizecheck, e);
2558

2559 1
                    if (t1.ty == Tsarray && t2.ty == Tsarray)
2560 1
                        assert(t1.size() == t2.size());
2561
                    else
2562
                    {
2563 1
                        elem *elencmp = el_bin(eop, TYint, elen1, elen2);
2564 1
                        e = el_bin(ee.op == TOK.equal ? OPandand : OPoror, TYint, elencmp, e);
2565
                    }
2566

2567
                    // Ensure left-to-right order of evaluation
2568 1
                    e = el_combine(earr2, e);
2569 1
                    e = el_combine(earr1, e);
2570 1
                    elem_setLoc(e, ee.loc);
2571 1
                    result = e;
2572 1
                    return;
2573
                }
2574

2575 1
                elem *ea1 = eval_Darray(ee.e1);
2576 1
                elem *ea2 = eval_Darray(ee.e2);
2577

2578 1
                elem *ep = el_params(getTypeInfo(ee.loc, telement.arrayOf(), irs),
2579
                        ea2, ea1, null);
2580 1
                int rtlfunc = RTLSYM_ARRAYEQ2;
2581 1
                e = el_bin(OPcall, TYint, el_var(getRtlsym(rtlfunc)), ep);
2582 1
                if (ee.op == TOK.notEqual)
2583 1
                    e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
2584 1
                elem_setLoc(e,ee.loc);
2585
            }
2586 1
            else if (t1.ty == Taarray && t2.ty == Taarray)
2587
            {
2588 1
                TypeAArray taa = cast(TypeAArray)t1;
2589 1
                Symbol *s = aaGetSymbol(taa, "Equal", 0);
2590 1
                elem *ti = getTypeInfo(ee.loc, taa, irs);
2591 1
                elem *ea1 = toElem(ee.e1, irs);
2592 1
                elem *ea2 = toElem(ee.e2, irs);
2593
                // aaEqual(ti, e1, e2)
2594 1
                elem *ep = el_params(ea2, ea1, ti, null);
2595 1
                e = el_bin(OPcall, TYnptr, el_var(s), ep);
2596 1
                if (ee.op == TOK.notEqual)
2597 1
                    e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
2598 1
                elem_setLoc(e, ee.loc);
2599 1
                result = e;
2600 1
                return;
2601
            }
2602
            else
2603 1
                e = toElemBin(ee, eop);
2604 1
            result = e;
2605
        }
2606

2607
        override void visit(IdentityExp ie)
2608
        {
2609 1
            Type t1 = ie.e1.type.toBasetype();
2610 1
            Type t2 = ie.e2.type.toBasetype();
2611

2612 1
            OPER eop;
2613 1
            switch (ie.op)
2614
            {
2615 1
                case TOK.identity:       eop = OPeqeq;   break;
2616 1
                case TOK.notIdentity:    eop = OPne;     break;
2617 0
                default:
2618 0
                    printf("%s\n", ie.toChars());
2619 0
                    assert(0);
2620
            }
2621

2622
            //printf("IdentityExp.toElem() %s\n", ie.toChars());
2623

2624
            /* Fix Issue 18746 : https://issues.dlang.org/show_bug.cgi?id=18746
2625
             * Before skipping the comparison for empty structs
2626
             * it is necessary to check whether the expressions involved
2627
             * have any sideeffects
2628
             */
2629

2630 1
            const canSkipCompare = isTrivialExp(ie.e1) && isTrivialExp(ie.e2);
2631 1
            elem *e;
2632 1
            if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.fields.dim == 0 && canSkipCompare)
2633
            {
2634
                // we can skip the compare if the structs are empty
2635 1
                e = el_long(TYbool, ie.op == TOK.identity);
2636
            }
2637 1
            else if (t1.ty == Tstruct || t1.isfloating())
2638
            {
2639
                // Do bit compare of struct's
2640 1
                elem *es1 = toElem(ie.e1, irs);
2641 1
                es1 = addressElem(es1, ie.e1.type);
2642 1
                elem *es2 = toElem(ie.e2, irs);
2643 1
                es2 = addressElem(es2, ie.e2.type);
2644 1
                e = el_param(es1, es2);
2645 1
                elem *ecount = el_long(TYsize_t, t1.size());
2646 1
                e = el_bin(OPmemcmp, TYint, e, ecount);
2647 1
                e = el_bin(eop, TYint, e, el_long(TYint, 0));
2648 1
                elem_setLoc(e, ie.loc);
2649
            }
2650 1
            else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
2651 1
                     (t2.ty == Tarray || t2.ty == Tsarray))
2652
            {
2653

2654 1
                elem *ea1 = toElem(ie.e1, irs);
2655 1
                ea1 = array_toDarray(t1, ea1);
2656 1
                elem *ea2 = toElem(ie.e2, irs);
2657 1
                ea2 = array_toDarray(t2, ea2);
2658

2659 1
                e = el_bin(eop, totym(ie.type), ea1, ea2);
2660 1
                elem_setLoc(e, ie.loc);
2661
            }
2662
            else
2663 1
                e = toElemBin(ie, eop);
2664

2665 1
            result = e;
2666
        }
2667

2668
        /***************************************
2669
         */
2670

2671
        override void visit(InExp ie)
2672
        {
2673 1
            elem *key = toElem(ie.e1, irs);
2674 1
            elem *aa = toElem(ie.e2, irs);
2675 1
            TypeAArray taa = cast(TypeAArray)ie.e2.type.toBasetype();
2676

2677
            // aaInX(aa, keyti, key);
2678 1
            key = addressElem(key, ie.e1.type);
2679 1
            Symbol *s = aaGetSymbol(taa, "InX", 0);
2680 1
            elem *keyti = getTypeInfo(ie.loc, taa.index, irs);
2681 1
            elem *ep = el_params(key, keyti, aa, null);
2682 1
            elem *e = el_bin(OPcall, totym(ie.type), el_var(s), ep);
2683

2684 1
            elem_setLoc(e, ie.loc);
2685 1
            result = e;
2686
        }
2687

2688
        /***************************************
2689
         */
2690

2691
        override void visit(RemoveExp re)
2692
        {
2693 1
            auto taa = re.e1.type.toBasetype().isTypeAArray();
2694 1
            assert(taa);
2695 1
            elem *ea = toElem(re.e1, irs);
2696 1
            elem *ekey = toElem(re.e2, irs);
2697

2698 1
            ekey = addressElem(ekey, re.e2.type);
2699 1
            Symbol *s = aaGetSymbol(taa, "DelX", 0);
2700 1
            elem *keyti = getTypeInfo(re.loc, taa.index, irs);
2701 1
            elem *ep = el_params(ekey, keyti, ea, null);
2702 1
            elem *e = el_bin(OPcall, TYnptr, el_var(s), ep);
2703

2704 1
            elem_setLoc(e, re.loc);
2705 1
            result = e;
2706
        }
2707

2708
        /***************************************
2709
         */
2710

2711
        override void visit(AssignExp ae)
2712
        {
2713
            version (none)
2714
            {
2715
                if (ae.op == TOK.blit)      printf("BlitExp.toElem('%s')\n", ae.toChars());
2716
                if (ae.op == TOK.assign)    printf("AssignExp.toElem('%s')\n", ae.toChars());
2717
                if (ae.op == TOK.construct) printf("ConstructExp.toElem('%s')\n", ae.toChars());
2718
            }
2719

2720
            void setResult(elem* e)
2721
            {
2722 1
                elem_setLoc(e, ae.loc);
2723 1
                result = e;
2724
            }
2725

2726 1
            Type t1b = ae.e1.type.toBasetype();
2727

2728
            // Look for array.length = n
2729 1
            if (auto ale = ae.e1.isArrayLengthExp())
2730
            {
2731 0
                assert(0, "This case should have been rewritten to `_d_arraysetlengthT` in the semantic phase");
2732
            }
2733

2734
            // Look for array[]=n
2735 1
            if (auto are = ae.e1.isSliceExp())
2736
            {
2737 1
                Type t1 = t1b;
2738 1
                Type ta = are.e1.type.toBasetype();
2739

2740
                // which we do if the 'next' types match
2741 1
                if (ae.memset == MemorySet.blockAssign)
2742
                {
2743
                    // Do a memset for array[]=v
2744
                    //printf("Lpair %s\n", ae.toChars());
2745 1
                    Type tb = ta.nextOf().toBasetype();
2746 1
                    uint sz = cast(uint)tb.size();
2747

2748 1
                    elem *n1 = toElem(are.e1, irs);
2749 1
                    elem *elwr = are.lwr ? toElem(are.lwr, irs) : null;
2750 1
                    elem *eupr = are.upr ? toElem(are.upr, irs) : null;
2751