root/trunk/src/e2ir.c

Revision 856, 144.1 kB (checked in by walter, 1 year ago)

use new non-varargs functions

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include        <stdio.h>
11 #include        <string.h>
12 #include        <time.h>
13 #include        <complex.h>
14
15 #include        "port.h"
16
17 #include        "lexer.h"
18 #include        "expression.h"
19 #include        "mtype.h"
20 #include        "dsymbol.h"
21 #include        "declaration.h"
22 #include        "enum.h"
23 #include        "aggregate.h"
24 #include        "attrib.h"
25 #include        "module.h"
26 #include        "init.h"
27 #include        "template.h"
28
29 #include        "mem.h" // for tk/mem_malloc
30
31 #include        "cc.h"
32 #include        "el.h"
33 #include        "oper.h"
34 #include        "global.h"
35 #include        "code.h"
36 #include        "type.h"
37 #include        "dt.h"
38 #include        "irstate.h"
39 #include        "id.h"
40 #include        "type.h"
41 #include        "toir.h"
42
43 static char __file__[] = __FILE__;      /* for tassert.h                */
44 #include        "tassert.h"
45
46
47 elem *addressElem(elem *e, Type *t);
48 elem *array_toPtr(Type *t, elem *e);
49 elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result);
50 elem *bit_read(elem *eb, elem *ei, int result);
51 elem *exp2_copytotemp(elem *e);
52
53 #define el_setLoc(e,loc)        ((e)->Esrcpos.Sfilename = (char *)(loc).filename, \
54                                  (e)->Esrcpos.Slinnum = (loc).linnum)
55
56 /* If variable var of type typ is a reference
57  */
58 #if SARRAYVALUE
59 #define ISREF(var, tb) (var->isOut() || var->isRef())
60 #else
61 #define ISREF(var, tb) ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
62 #endif
63
64 /************************************
65  * Call a function.
66  */
67
68 elem *callfunc(Loc loc,
69         IRState *irs,
70         int directcall,         // 1: don't do virtual call
71         Type *tret,             // return type
72         elem *ec,               // evaluates to function address
73         Type *ectype,           // original type of ec
74         FuncDeclaration *fd,    // if !=NULL, this is the function being called
75         Type *t,                // TypeDelegate or TypeFunction for this function
76         elem *ehidden,          // if !=NULL, this is the 'hidden' argument
77         Array *arguments)
78 {
79     elem *ep;
80     elem *e;
81     elem *ethis = NULL;
82     elem *eside = NULL;
83     int i;
84     tym_t ty;
85     tym_t tyret;
86     enum RET retmethod;
87     int reverse;
88     TypeFunction *tf;
89     int op;
90
91 #if 0
92     printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
93         directcall, tret->toChars(), ec, fd);
94     printf("ec: "); elem_print(ec);
95     if (fd)
96         printf("fd = '%s'\n", fd->toChars());
97 #endif
98
99     t = t->toBasetype();
100     if (t->ty == Tdelegate)
101     {
102         // A delegate consists of:
103         //      { Object *this; Function *funcptr; }
104         assert(!fd);
105         assert(t->nextOf()->ty == Tfunction);
106         tf = (TypeFunction *)(t->nextOf());
107         ethis = ec;
108         ec = el_same(&ethis);
109         ethis = el_una(I64 ? OP128_64 : OP64_32, TYnptr, ethis); // get this
110         ec = array_toPtr(t, ec);                // get funcptr
111         ec = el_una(OPind, tf->totym(), ec);
112     }
113     else
114     {   assert(t->ty == Tfunction);
115         tf = (TypeFunction *)(t);
116     }
117     retmethod = tf->retStyle();
118     ty = ec->Ety;
119     if (fd)
120         ty = fd->toSymbol()->Stype->Tty;
121     reverse = tyrevfunc(ty);
122     ep = NULL;
123     if (arguments)
124     {
125         // j=1 if _arguments[] is first argument
126         int j = (tf->linkage == LINKd && tf->varargs == 1);
127
128         for (i = 0; i < arguments->dim ; i++)
129         {   Expression *arg = (Expression *)arguments->data[i];
130             elem *ea;
131
132             //printf("\targ[%d]: %s\n", i, arg->toChars());
133
134             size_t nparams = Parameter::dim(tf->parameters);
135             if (i - j < nparams && i >= j)
136             {
137                 Parameter *p = Parameter::getNth(tf->parameters, i - j);
138
139                 if (p->storageClass & (STCout | STCref))
140                 {
141                     // Convert argument to a pointer,
142                     // use AddrExp::toElem()
143                     Expression *ae = arg->addressOf(NULL);
144                     ea = ae->toElem(irs);
145                     goto L1;
146                 }
147             }
148             ea = arg->toElem(irs);
149         L1:
150             if (tybasic(ea->Ety) == TYstruct || tybasic(ea->Ety) == TYarray)
151             {
152                 ea = el_una(OPstrpar, TYstruct, ea);
153                 ea->ET = ea->E1->ET;
154             }
155             if (reverse)
156                 ep = el_param(ep,ea);
157             else
158                 ep = el_param(ea,ep);
159         }
160     }
161
162     if (retmethod == RETstack)
163     {
164         if (!ehidden)
165         {   // Don't have one, so create one
166             type *t;
167
168             Type *tret = tf->next;
169             if (tret->toBasetype()->ty == Tstruct ||
170                 tret->toBasetype()->ty == Tsarray)
171                 t = tret->toCtype();
172             else
173                 t = type_fake(tret->totym());
174             Symbol *stmp = symbol_genauto(t);
175             ehidden = el_ptr(stmp);
176         }
177         if ((global.params.isLinux ||
178              global.params.isOSX ||
179              global.params.isFreeBSD ||
180              global.params.isSolaris) && tf->linkage != LINKd)
181             ;   // ehidden goes last on Linux/OSX C++
182         else
183         {
184             if (ep)
185             {
186 #if 0 // BUG: implement
187                 if (reverse && type_mangle(tfunc) == mTYman_cpp)
188                     ep = el_param(ehidden,ep);
189                 else
190 #endif
191                     ep = el_param(ep,ehidden);
192             }
193             else
194                 ep = ehidden;
195             ehidden = NULL;
196         }
197     }
198
199     if (fd && fd->isMember2())
200     {
201         InterfaceDeclaration *intd;
202         Symbol *sfunc;
203         AggregateDeclaration *ad;
204
205         ad = fd->isThis();
206         if (ad)
207         {
208             ethis = ec;
209             if (ad->isStructDeclaration() && tybasic(ec->Ety) != TYnptr)
210             {
211                 ethis = addressElem(ec, ectype);
212             }
213         }
214         else
215         {
216             // Evaluate ec for side effects
217             eside = ec;
218         }
219         sfunc = fd->toSymbol();
220
221         if (!fd->isVirtual() ||
222             directcall ||               // BUG: fix
223             fd->isFinal()
224            /* Future optimization: || (whole program analysis && not overridden)
225             */
226            )
227         {
228             // make static call
229             ec = el_var(sfunc);
230         }
231         else
232         {
233             // make virtual call
234             elem *ev;
235             unsigned vindex;
236
237             assert(ethis);
238             ev = el_same(&ethis);
239             ev = el_una(OPind, TYnptr, ev);
240             vindex = fd->vtblIndex;
241
242             // Build *(ev + vindex * 4)
243 if (I32) assert(tysize[TYnptr] == 4);
244             ec = el_bin(OPadd,TYnptr,ev,el_long(TYsize_t, vindex * tysize[TYnptr]));
245             ec = el_una(OPind,TYnptr,ec);
246             ec = el_una(OPind,tybasic(sfunc->Stype->Tty),ec);
247         }
248     }
249     else if (fd && fd->isNested())
250     {
251         assert(!ethis);
252         ethis = getEthis(0, irs, fd);
253
254     }
255
256     ep = el_param(ep, ethis);
257     if (ehidden)
258         ep = el_param(ep, ehidden);     // if ehidden goes last
259
260     tyret = tret->totym();
261
262     // Look for intrinsic functions
263     if (ec->Eoper == OPvar && (op = intrinsic_op(ec->EV.sp.Vsym->Sident)) != -1)
264     {
265         el_free(ec);
266         if (OTbinary(op))
267         {
268             ep->Eoper = op;
269             ep->Ety = tyret;
270             e = ep;
271             if (op == OPscale)
272             {
273                 elem *et = e->E1;
274                 e->E1 = el_una(OPs32_d, TYdouble, e->E2);
275                 e->E1 = el_una(OPd_ld, TYldouble, e->E1);
276                 e->E2 = et;
277             }
278             else if (op == OPyl2x || op == OPyl2xp1)
279             {
280                 elem *et = e->E1;
281                 e->E1 = e->E2;
282                 e->E2 = et;
283             }
284         }
285         else
286             e = el_una(op,tyret,ep);
287     }
288     else if (ep)
289     {   /* Do not do "no side effect" calls if a hidden parameter is passed,
290          * as the return value is stored through the hidden parameter, which
291          * is a side effect.
292          */
293         e = el_bin(((fd ? fd->isPure() : tf->purity) == PUREstrong &&
294                    tf->isnothrow && (retmethod != RETstack)) ?
295                    OPcallns : OPcall,tyret,ec,ep);
296         if (tf->varargs)
297             e->Eflags |= EFLAGS_variadic;
298     }
299     else
300     {   e = el_una(((fd ? fd->isPure() : tf->purity) == PUREstrong &&
301                 tf->isnothrow && (retmethod != RETstack)) ?
302                 OPucallns : OPucall,tyret,ec);
303         if (tf->varargs)
304             e->Eflags |= EFLAGS_variadic;
305     }
306
307     if (retmethod == RETstack)
308     {
309         e->Ety = TYnptr;
310         e = el_una(OPind, tyret, e);
311     }
312
313 #if DMDV2
314     if (tf->isref)
315     {
316         e->Ety = TYnptr;
317         e = el_una(OPind, tyret, e);
318     }
319 #endif
320
321     if (tybasic(tyret) == TYstruct)
322     {
323         e->ET = tret->toCtype();
324     }
325     e = el_combine(eside, e);
326     return e;
327 }
328
329 /*******************************************
330  * Take address of an elem.
331  */
332
333 elem *addressElem(elem *e, Type *t)
334 {
335     elem **pe;
336
337     //printf("addressElem()\n");
338
339     for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2)
340         ;
341     if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind)
342     {   Symbol *stmp;
343         elem *eeq;
344         elem *e = *pe;
345         type *tx;
346
347         // Convert to ((tmp=e),tmp)
348         TY ty;
349         if (t && ((ty = t->toBasetype()->ty) == Tstruct || ty == Tsarray))
350             tx = t->toCtype();
351         else
352             tx = type_fake(e->Ety);
353         stmp = symbol_genauto(tx);
354         eeq = el_bin(OPeq,e->Ety,el_var(stmp),e);
355         if (tybasic(e->Ety) == TYstruct)
356         {
357             eeq->Eoper = OPstreq;
358             eeq->ET = e->ET;
359         }
360         else if (tybasic(e->Ety) == TYarray)
361         {
362             eeq->Eoper = OPstreq;
363             eeq->Ejty = eeq->Ety = TYstruct;
364             eeq->ET = t->toCtype();
365         }
366         *pe = el_bin(OPcomma,e->Ety,eeq,el_var(stmp));
367     }
368     e = el_una(OPaddr,TYnptr,e);
369     return e;
370 }
371
372 /*****************************************
373  * Convert array to a pointer to the data.
374  */
375
376 elem *array_toPtr(Type *t, elem *e)
377 {
378     //printf("array_toPtr()\n");
379     //elem_print(e);
380     t = t->toBasetype();
381     switch (t->ty)
382     {
383         case Tpointer:
384             break;
385
386         case Tarray:
387         case Tdelegate:
388             if (e->Eoper == OPcomma)
389             {
390                 e->Ety = TYnptr;
391                 e->E2 = array_toPtr(t, e->E2);
392             }
393             else if (e->Eoper == OPpair)
394             {
395                 e->Eoper = OPcomma;
396                 e->Ety = TYnptr;
397             }
398             else
399             {
400 #if 1
401                 e = el_una(OPmsw, TYnptr, e);
402 #else
403                 e = el_una(OPaddr, TYnptr, e);
404                 e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, 4));
405                 e = el_una(OPind, TYnptr, e);
406 #endif
407             }
408             break;
409
410         case Tsarray:
411             e = el_una(OPaddr, TYnptr, e);
412             break;
413
414         default:
415             t->print();
416             assert(0);
417     }
418     return e;
419 }
420
421 /*****************************************
422  * Convert array to a dynamic array.
423  */
424
425 elem *array_toDarray(Type *t, elem *e)
426 {
427     unsigned dim;
428     elem *ef = NULL;
429     elem *ex;
430
431     //printf("array_toDarray(t = %s)\n", t->toChars());
432     //elem_print(e);
433     t = t->toBasetype();
434     switch (t->ty)
435     {
436         case Tarray:
437             break;
438
439         case Tsarray:
440             e = addressElem(e, t);
441             dim = ((TypeSArray *)t)->dim->toInteger();
442             e = el_pair(TYdarray, el_long(TYsize_t, dim), e);
443             break;
444
445         default:
446         L1:
447             switch (e->Eoper)
448             {
449                 case OPconst:
450                 {
451                     size_t len = tysize[tybasic(e->Ety)];
452                     elem *es = el_calloc();
453                     es->Eoper = OPstring;
454
455                     // Match MEM_PH_FREE for OPstring in ztc\el.c
456                     es->EV.ss.Vstring = (char *)mem_malloc(len);
457                     memcpy(es->EV.ss.Vstring, &e->EV, len);
458
459                     es->EV.ss.Vstrlen = len;
460                     es->Ety = TYnptr;
461                     e = es;
462                     break;
463                 }
464
465                 case OPvar:
466                     e = el_una(OPaddr, TYnptr, e);
467                     break;
468
469                 case OPcomma:
470                     ef = el_combine(ef, e->E1);
471                     ex = e;
472                     e = e->E2;
473                     ex->E1 = NULL;
474                     ex->E2 = NULL;
475                     el_free(ex);
476                     goto L1;
477
478                 case OPind:
479                     ex = e;
480                     e = e->E1;
481                     ex->E1 = NULL;
482                     ex->E2 = NULL;
483                     el_free(ex);
484                     break;
485
486                 default:
487                 {
488                     // Copy expression to a variable and take the
489                     // address of that variable.
490                     Symbol *stmp;
491                     tym_t ty = tybasic(e->Ety);
492
493                     if (ty == TYstruct)
494                     {   unsigned sz = type_size(e->ET);
495                         if (sz == 4)
496                             ty = TYint;
497                         else if (sz == 8)
498                             ty = TYllong;
499                     }
500                     e->Ety = ty;
501                     stmp = symbol_genauto(type_fake(ty));
502                     e = el_bin(OPeq, e->Ety, el_var(stmp), e);
503                     e = el_bin(OPcomma, TYnptr, e, el_una(OPaddr, TYnptr, el_var(stmp)));
504                     break;
505                 }
506             }
507             dim = 1;
508             e = el_pair(TYdarray, el_long(TYsize_t, dim), e);
509             break;
510     }
511     return el_combine(ef, e);
512 }
513
514 /*****************************************
515  * Evaluate elem and convert to dynamic array.
516  */
517
518 elem *eval_Darray(IRState *irs, Expression *e)
519 {
520     elem *ex;
521
522     ex = e->toElem(irs);
523     return array_toDarray(e->type, ex);
524 }
525
526 /************************************
527  */
528
529 elem *sarray_toDarray(Loc loc, Type *tfrom, Type *tto, elem *e)
530 {
531     //printf("sarray_toDarray()\n");
532     //elem_print(e);
533
534     unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger();
535
536     if (tto)
537     {
538         unsigned fsize = tfrom->nextOf()->size();
539         unsigned tsize = tto->nextOf()->size();
540
541         if ((dim * fsize) % tsize != 0)
542         {
543           Lerr:
544             error(loc, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars());
545         }
546         dim = (dim * fsize) / tsize;
547     }
548   L1:
549     elem *elen = el_long(TYsize_t, dim);
550     e = addressElem(e, tfrom);
551     e = el_pair(TYdarray, elen, e);
552     return e;
553 }
554
555 /********************************************
556  * Determine if t is an array of structs that need a postblit.
557  */
558
559 StructDeclaration *needsPostblit(Type *t)
560 {
561     t = t->toBasetype();
562     while (t->ty == Tsarray)
563         t = t->nextOf()->toBasetype();
564     if (t->ty == Tstruct)
565     {   StructDeclaration *sd = ((TypeStruct *)t)->sym;
566         if (sd->postblit)
567             return sd;
568     }
569     return NULL;
570 }
571
572 /*******************************************
573  * Set an array pointed to by eptr to evalue:
574  *      eptr[0..edim] = evalue;
575  * Input:
576  *      eptr    where to write the data to
577  *      evalue  value to write
578  *      edim    number of times to write evalue to eptr[]
579  *      tb      type of evalue
580  */
581
582 elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue, IRState *irs, int op)
583 {   int r;
584     elem *e;
585     int sz = tb->size();
586
587     switch (tb->ty)
588     {
589         case Tfloat80:
590         case Timaginary80:
591             r = RTLSYM_MEMSET80;
592             break;
593         case Tcomplex80:
594             r = RTLSYM_MEMSET160;
595             break;
596         case Tcomplex64:
597             r = RTLSYM_MEMSET128;
598             break;
599         case Tfloat32:
600         case Timaginary32:
601             if (I32)
602                 goto Ldefault;          // legacy binary compatibility
603             r = RTLSYM_MEMSETFLOAT;
604             break;
605         case Tfloat64:
606         case Timaginary64:
607             if (I32)
608                 goto Ldefault;          // legacy binary compatibility
609             r = RTLSYM_MEMSETDOUBLE;
610             break;
611
612         default:
613         Ldefault:
614             switch (sz)
615             {
616                 case 1:      r = RTLSYM_MEMSET8;    break;
617                 case 2:      r = RTLSYM_MEMSET16;   break;
618                 case 4:      r = RTLSYM_MEMSET32;   break;
619                 case 8:      r = RTLSYM_MEMSET64;   break;
620                 case 16:     r = RTLSYM_MEMSET128;  break;
621                 default:     r = RTLSYM_MEMSETN;    break;
622             }
623
624             /* Determine if we need to do postblit
625              */
626             if (op != TOKblit)
627             {
628                 StructDeclaration *sd = needsPostblit(tb);
629                 if (sd)
630                 {   /* Need to do postblit.
631                      *   void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
632                      */
633                     r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN;
634                     evalue = el_una(OPaddr, TYnptr, evalue);
635                     Expression *ti = tb->getTypeInfo(NULL);
636                     elem *eti = ti->toElem(irs);
637                     e = el_params(eti, edim, evalue, eptr, NULL);
638                     e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
639                     return e;
640                 }
641             }
642
643             if (r == RTLSYM_MEMSETN)
644             {
645                 // void *_memsetn(void *p, void *value, int dim, int sizelem)
646                 evalue = el_una(OPaddr, TYnptr, evalue);
647                 elem *esz = el_long(TYsize_t, sz);
648                 e = el_params(esz, edim, evalue, eptr, NULL);
649                 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
650                 return e;
651             }
652             break;
653     }
654     if (sz > 1 && sz <= 8 &&
655         evalue->Eoper == OPconst && el_allbits(evalue, 0))
656     {
657         r = RTLSYM_MEMSET8;
658         edim = el_bin(OPmul, TYsize_t, edim, el_long(TYsize_t, sz));
659     }
660
661     if (tybasic(evalue->Ety) == TYstruct || tybasic(evalue->Ety) == TYarray)
662     {
663         evalue = el_una(OPstrpar, TYstruct, evalue);
664         evalue->ET = evalue->E1->ET;
665     }
666
667     // Be careful about parameter side effect ordering
668     if (r == RTLSYM_MEMSET8)
669     {
670         e = el_param(edim, evalue);
671         e = el_bin(OPmemset,TYnptr,eptr,e);
672     }
673     else
674     {
675         e = el_params(edim, evalue, eptr, NULL);
676         e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
677     }
678     return e;
679 }
680
681 /***************************************
682  */
683
684 elem *Expression::toElem(IRState *irs)
685 {
686     print();
687     assert(0);
688     return NULL;
689 }
690
691 /************************************
692  */
693 #if DMDV2
694 elem *SymbolExp::toElem(IRState *irs)
695 {   Symbol *s;
696     elem *e;
697     tym_t tym;
698     Type *tb = (op == TOKsymoff) ? var->type->toBasetype() : type->toBasetype();
699     int offset = (op == TOKsymoff) ? ((SymOffExp*)this)->offset : 0;
700     FuncDeclaration *fd;
701     VarDeclaration *v = var->isVarDeclaration();
702
703     //printf("SymbolExp::toElem('%s') %p\n", toChars(), this);
704     //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
705     if (op == TOKvar && var->needThis())
706     {
707         error("need 'this' to access member %s", toChars());
708         return el_long(TYsize_t, 0);
709     }
710
711     /* The magic variable __ctfe is always false at runtime
712      */
713     if (op == TOKvar && v && v->ident == Id::ctfe)
714         return el_long(type->totym(), 0);
715
716     s = var->toSymbol();
717     fd = NULL;
718     if (var->toParent2())
719         fd = var->toParent2()->isFuncDeclaration();
720
721     int nrvo = 0;
722     if (fd && fd->nrvo_can && fd->nrvo_var == var)
723     {
724         s = fd->shidden;
725         nrvo = 1;
726     }
727
728     if (s->Sclass == SCauto || s->Sclass == SCparameter)
729     {
730         if (fd && fd != irs->getFunc())
731         {   // 'var' is a variable in an enclosing function.
732             elem *ethis;
733             int soffset;
734
735             ethis = getEthis(loc, irs, fd);
736             ethis = el_una(OPaddr, TYnptr, ethis);
737
738             if (v && v->offset)
739                 soffset = v->offset;
740             else
741             {
742                 soffset = s->Soffset;
743                 /* If fd is a non-static member function of a class or struct,
744                  * then ethis isn't the frame pointer.
745                  * ethis is the 'this' pointer to the class/struct instance.
746                  * We must offset it.
747                  */
748                 if (fd->vthis)
749                 {
750                     soffset -= fd->vthis->toSymbol()->Soffset;
751                 }
752                 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
753             }
754
755             if (!nrvo)
756                 soffset += offset;
757
758             e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
759             if (op == TOKvar)
760                 e = el_una(OPind, TYnptr, e);
761             if (ISREF(var, tb))
762                 e = el_una(OPind, s->ty(), e);
763             else if (op == TOKsymoff && nrvo)
764             {   e = el_una(OPind, TYnptr, e);
765                 e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
766             }
767             goto L1;
768         }
769     }
770
771     /* If var is a member of a closure
772      */
773     if (v && v->offset)
774     {   assert(irs->sclosure);
775         e = el_var(irs->sclosure);
776         e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, v->offset));
777         if (op == TOKvar)
778         {   e = el_una(OPind, type->totym(), e);
779             if (tybasic(e->Ety) == TYstruct)
780                 e->ET = type->toCtype();
781             el_setLoc(e, loc);
782         }
783         if (ISREF(var, tb))
784         {   e->Ety = TYnptr;
785             e = el_una(OPind, s->ty(), e);
786         }
787         else if (op == TOKsymoff && nrvo)
788         {   e = el_una(OPind, TYnptr, e);
789             e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
790         }
791         else if (op == TOKsymoff)
792         {
793             e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
794         }
795         goto L1;
796     }
797
798     if (s->Sclass == SCauto && s->Ssymnum == -1)
799     {
800         //printf("\tadding symbol %s\n", s->Sident);
801         symbol_add(s);
802     }
803
804     if (var->isImportedSymbol())
805     {
806         assert(op == TOKvar);
807         e = el_var(var->toImport());
808         e = el_una(OPind,s->ty(),e);
809     }
810     else if (ISREF(var, tb))
811     {   // Static arrays are really passed as pointers to the array
812         // Out parameters are really references
813         e = el_var(s);
814         e->Ety = TYnptr;
815         if (op == TOKvar)
816             e = el_una(OPind, s->ty(), e);
817         else if (offset)
818             e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset));
819     }
820     else if (op == TOKvar)
821         e = el_var(s);
822     else
823     {   e = nrvo ? el_var(s) : el_ptr(s);
824         e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
825     }
826 L1:
827     if (op == TOKvar)
828     {
829         if (nrvo)
830         {
831             e->Ety = TYnptr;
832             e = el_una(OPind, 0, e);
833         }
834         if (tb->ty == Tfunction)
835         {
836             tym = s->Stype->Tty;
837         }
838         else
839             tym = type->totym();
840         e->Ejty = e->Ety = tym;
841         if (tybasic(tym) == TYstruct)
842         {
843             e->ET = type->toCtype();
844         }
845         else if (tybasic(tym) == TYarray)
846         {
847             e->Ejty = e->Ety = TYstruct;
848             e->ET = type->toCtype();
849         }
850     }
851     el_setLoc(e,loc);
852     return e;
853 }
854 #endif
855
856 #if DMDV1
857 elem *VarExp::toElem(IRState *irs)
858 {   Symbol *s;
859     elem *e;
860     tym_t tym;
861     Type *tb = type->toBasetype();
862     FuncDeclaration *fd;
863     VarDeclaration *v = var->isVarDeclaration();
864
865     //printf("VarExp::toElem('%s') %p\n", toChars(), this);
866     //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
867     if (var->needThis())
868     {
869         error("need 'this' to access member %s", toChars());
870         return el_long(TYsize_t, 0);
871     }
872     s = var->toSymbol();
873     fd = NULL;
874     if (var->toParent2())
875         fd = var->toParent2()->isFuncDeclaration();
876
877     int nrvo = 0;
878     if (fd && fd->nrvo_can && fd->nrvo_var == var)
879     {
880         s = fd->shidden;
881         nrvo = 1;
882     }
883
884     if (s->Sclass == SCauto || s->Sclass == SCparameter)
885     {
886         if (fd && fd != irs->getFunc())
887         {   // 'var' is a variable in an enclosing function.
888             elem *ethis;
889             int soffset;
890
891             ethis = getEthis(loc, irs, fd);
892             ethis = el_una(OPaddr, TYnptr, ethis);
893
894             if (v && v->offset)
895                 soffset = v->offset;
896             else
897             {
898                 soffset = s->Soffset;
899                 /* If fd is a non-static member function of a class or struct,
900                  * then ethis isn't the frame pointer.
901                  * ethis is the 'this' pointer to the class/struct instance.
902                  * We must offset it.
903                  */
904                 if (fd->vthis)
905                 {
906                     soffset -= fd->vthis->toSymbol()->Soffset;
907                 }
908                 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
909             }
910
911             ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
912             e = el_una(OPind, 0, ethis);
913             if (ISREF(var, tb))
914                 goto L2;
915             goto L1;
916         }
917     }
918
919     /* If var is a member of a closure
920      */
921     if (v && v->offset)
922     {   assert(irs->sclosure);
923         e = el_var(irs->sclosure);
924         e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, v->offset));
925         e = el_una(OPind, type->totym(), e);
926         if (tybasic(e->Ety) == TYstruct)
927             e->ET = type->toCtype();
928         el_setLoc(e, loc);
929
930         if (ISREF(var, tb))
931             goto L2;
932         goto L1;
933     }
934
935     if (s->Sclass == SCauto && s->Ssymnum == -1)
936     {
937         //printf("\tadding symbol\n");
938         symbol_add(s);
939     }
940
941     if (var->isImportedSymbol())
942     {
943         e = el_var(var->toImport());
944         e = el_una(OPind,s->ty(),e);
945     }
946     else if (ISREF(var, tb))
947     {   // Static arrays are really passed as pointers to the array
948         // Out parameters are really references
949         e = el_var(s);
950 L2:
951         e->Ety = TYnptr;
952         e = el_una(OPind, s->ty(), e);
953     }
954     else
955         e = el_var(s);
956 L1:
957     if (nrvo)
958     {
959         e->Ety = TYnptr;
960         e = el_una(OPind, 0, e);
961     }
962     if (tb->ty == Tfunction)
963     {
964         tym = s->Stype->Tty;
965     }
966     else
967         tym = type->totym();
968     e->Ejty = e->Ety = tym;
969     if (tybasic(tym) == TYstruct)
970     {
971         e->ET = type->toCtype();
972     }
973     else if (tybasic(tym) == TYarray)
974     {
975         e->Ejty = e->Ety = TYstruct;
976         e->ET = type->toCtype();
977     }
978     el_setLoc(e,loc);
979     return e;
980 }
981 #endif
982
983 #if 0
984 elem *SymOffExp::toElem(IRState *irs)
985 {   Symbol *s;
986     elem *e;
987     Type *tb = var->type->toBasetype();
988     VarDeclaration *v = var->isVarDeclaration();
989     FuncDeclaration *fd = NULL;
990     if (var->toParent2())
991         fd = var->toParent2()->isFuncDeclaration();
992
993     //printf("SymOffExp::toElem(): %s\n", toChars());
994     s = var->toSymbol();
995
996     int nrvo = 0;
997     if (fd && fd->nrvo_can && fd->nrvo_var == var)
998     {   s = fd->shidden;
999         nrvo = 1;
1000     }
1001
1002     if (s->Sclass == SCauto && s->Ssymnum == -1)
1003         symbol_add(s);
1004     assert(!var->isImportedSymbol());
1005
1006     // This code closely parallels that in VarExp::toElem()
1007     if (s->Sclass == SCauto || s->Sclass == SCparameter)
1008     {
1009         if (fd && fd != irs->getFunc())
1010         {   // 'var' is a variable in an enclosing function.
1011             elem *ethis;
1012             int soffset;
1013
1014             ethis = getEthis(loc, irs, fd);
1015             ethis = el_una(OPaddr, TYnptr, ethis);
1016
1017             if (v && v->offset)
1018                 soffset = v->offset;
1019             else
1020             {
1021                 soffset = s->Soffset;
1022                 /* If fd is a non-static member function of a class or struct,
1023                  * then ethis isn't the frame pointer.
1024                  * ethis is the 'this' pointer to the class/struct instance.
1025                  * We must offset it.
1026                  */
1027                 if (fd->vthis)
1028                 {
1029                     soffset -= fd->vthis->toSymbol()->Soffset;
1030                 }
1031                 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
1032             }
1033
1034             if (!nrvo)
1035                 soffset += offset;
1036             e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
1037             if (ISREF(var, tb))
1038                 e = el_una(OPind, s->ty(), e);
1039             else if (nrvo)
1040             {   e = el_una(OPind, TYnptr, e);
1041                 e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
1042             }
1043             goto L1;
1044         }
1045     }
1046
1047     /* If var is a member of a closure
1048      */
1049     if (v && v->offset)
1050     {   assert(irs->sclosure);
1051         e = el_var(irs->sclosure);
1052         e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, v->offset));
1053         if (ISREF(var, tb))
1054             e = el_una(OPind, s->ty(), e);
1055         else if (nrvo)
1056         {   e = el_una(OPind, TYnptr, e);
1057             e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
1058         }
1059         goto L1;
1060     }
1061
1062     if (ISREF(var, tb))
1063     {   // Static arrays are really passed as pointers to the array
1064         // Out parameters are really references
1065         e = el_var(s);
1066         e->Ety = TYnptr;
1067         if (offset)
1068             e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset));
1069     }
1070     else
1071     {   e = nrvo ? el_var(s) : el_ptr(s);
1072         e = el_bin(OPadd, e->Ety, e, el_long(TYsize_t, offset));
1073     }
1074
1075 L1:
1076     el_setLoc(e,loc);
1077     return e;
1078 }
1079 #endif
1080
1081 /**************************************
1082  */
1083
1084 elem *FuncExp::toElem(IRState *irs)
1085 {
1086     elem *e;
1087     Symbol *s;
1088
1089     //printf("FuncExp::toElem() %s\n", toChars());
1090     s = fd->toSymbol();
1091     e = el_ptr(s);
1092     if (fd->isNested())
1093     {
1094         elem *ethis = getEthis(loc, irs, fd);
1095         e = el_pair(TYdelegate, ethis, e);
1096     }
1097
1098     irs->deferToObj->push(fd);
1099     el_setLoc(e,loc);
1100     return e;
1101 }
1102
1103 /**************************************
1104  */
1105
1106 elem *Dsymbol_toElem(Dsymbol *s, IRState *irs)
1107 {
1108     elem *e = NULL;
1109     Symbol *sp;
1110     AttribDeclaration *ad;
1111     VarDeclaration *vd;
1112     ClassDeclaration *cd;
1113     StructDeclaration *sd;
1114     FuncDeclaration *fd;
1115     TemplateMixin *tm;
1116     TupleDeclaration *td;
1117     TypedefDeclaration *tyd;
1118
1119     //printf("Dsymbol_toElem() %s\n", s->toChars());
1120     ad = s->isAttribDeclaration();
1121     if (ad)
1122     {
1123         Array *decl = ad->include(NULL, NULL);
1124         if (decl && decl->dim)
1125         {
1126             for (size_t i = 0; i < decl->dim; i++)
1127             {
1128                 s = (Dsymbol *)decl->data[i];
1129                 e = el_combine(e, Dsymbol_toElem(s, irs));
1130             }
1131         }
1132     }
1133     else if ((vd = s->isVarDeclaration()) != NULL)
1134     {
1135         s = s->toAlias();
1136         if (s != vd)
1137             return Dsymbol_toElem(s, irs);
1138         if (vd->storage_class & STCmanifest)
1139             return NULL;
1140         else if (vd->isStatic() || vd->storage_class & (STCextern | STCtls | STCgshared))
1141             vd->toObjFile(0);
1142         else
1143         {
1144             sp = s->toSymbol();
1145             symbol_add(sp);
1146             //printf("\tadding symbol '%s'\n", sp->Sident);
1147             if (vd->init)
1148             {
1149                 ExpInitializer *ie;
1150
1151                 ie = vd->init->isExpInitializer();
1152                 if (ie)
1153                     e = ie->exp->toElem(irs);
1154             }
1155         }
1156     }
1157     else if ((cd = s->isClassDeclaration()) != NULL)
1158     {
1159         irs->deferToObj->push(s);
1160     }
1161     else if ((sd = s->isStructDeclaration()) != NULL)
1162     {
1163         irs->deferToObj->push(sd);
1164     }
1165     else if ((fd = s->isFuncDeclaration()) != NULL)
1166     {
1167         //printf("function %s\n", fd->toChars());
1168         irs->deferToObj->push(fd);
1169     }
1170     else if ((tm = s->isTemplateMixin()) != NULL)
1171     {
1172         //printf("%s\n", tm->toChars());
1173         if (tm->members)
1174         {
1175             for (size_t i = 0; i < tm->members->dim; i++)
1176             {
1177                 Dsymbol *sm = (Dsymbol *)tm->members->data[i];
1178                 e = el_combine(e, Dsymbol_toElem(sm, irs));
1179             }
1180         }
1181     }
1182     else if ((td = s->isTupleDeclaration()) != NULL)
1183     {
1184         for (size_t i = 0; i < td->objects->dim; i++)
1185         {   Object *o = (Object *)td->objects->data[i];
1186             if (o->dyncast() == DYNCAST_EXPRESSION)
1187             {   Expression *eo = (Expression *)o;
1188                 if (eo->op == TOKdsymbol)
1189                 {   DsymbolExp *se = (DsymbolExp *)eo;
1190                     e = el_combine(e, Dsymbol_toElem(se->s, irs));
1191                 }
1192             }
1193         }
1194     }
1195     else if ((tyd = s->isTypedefDeclaration()) != NULL)
1196     {
1197         irs->deferToObj->push(tyd);
1198     }
1199     return e;
1200 }
1201
1202 elem *DeclarationExp::toElem(IRState *irs)
1203 {
1204     //printf("DeclarationExp::toElem() %s\n", toChars());
1205     elem *e = Dsymbol_toElem(declaration, irs);
1206     return e;
1207 }
1208
1209 /***************************************
1210  */
1211
1212 elem *ThisExp::toElem(IRState *irs)
1213 {   elem *ethis;
1214     FuncDeclaration *fd;
1215
1216     //printf("ThisExp::toElem()\n");
1217     assert(irs->sthis);
1218
1219     if (var)
1220     {
1221         assert(var->parent);
1222         fd = var->toParent2()->isFuncDeclaration();
1223         assert(fd);
1224         ethis = getEthis(loc, irs, fd);
1225     }
1226     else
1227         ethis = el_var(irs->sthis);
1228
1229 #if STRUCTTHISREF
1230     if (type->ty == Tstruct)
1231     {   ethis = el_una(OPind, TYstruct, ethis);
1232         ethis->ET = type->toCtype();
1233     }
1234 #endif
1235     el_setLoc(ethis,loc);
1236     return ethis;
1237 }
1238
1239 /***************************************
1240  */
1241
1242 elem *IntegerExp::toElem(IRState *irs)
1243 {   elem *e;
1244
1245     e = el_long(type->totym(), value);
1246     el_setLoc(e,loc);
1247     return e;
1248 }
1249
1250 /***************************************
1251  */
1252
1253 elem *RealExp::toElem(IRState *irs)
1254 {   union eve c;
1255     tym_t ty;
1256
1257     //printf("RealExp::toElem(%p) %s\n", this, toChars());
1258     memset(&c, 0, sizeof(c));
1259     ty = type->toBasetype()->totym();
1260     switch (tybasic(ty))
1261     {
1262         case TYfloat:
1263         case TYifloat:
1264             /* This assignment involves a conversion, which
1265              * unfortunately also converts SNAN to QNAN.
1266              */
1267             c.Vfloat = value;
1268             if (Port::isSignallingNan(value))
1269                 // Put SNAN back
1270                 c.Vuns &= 0xFFBFFFFFL;
1271             break;
1272
1273         case TYdouble:
1274         case TYidouble:
1275             /* This assignment involves a conversion, which
1276              * unfortunately also converts SNAN to QNAN.
1277              */
1278             c.Vdouble = value;
1279             if (Port::isSignallingNan(value))
1280                 // Put SNAN back
1281                 c.Vullong &= 0xFFF7FFFFFFFFFFFFULL;
1282             break;
1283
1284         case TYldouble:
1285         case TYildouble:
1286             c.Vldouble = value;
1287             break;
1288
1289         default:
1290             print();
1291             type->print();
1292             type->toBasetype()->print();
1293             printf("ty = %d, tym = %x\n", type->ty, ty);
1294             assert(0);
1295     }
1296     return el_const(ty, &c);
1297 }
1298
1299
1300 /***************************************
1301  */
1302
1303 elem *ComplexExp::toElem(IRState *irs)
1304 {   union eve c;
1305     tym_t ty;
1306     real_t re;
1307     real_t im;
1308
1309     //printf("ComplexExp::toElem(%p) %s\n", this, toChars());
1310
1311     memset(&c, 0, sizeof(c));
1312     re = creall(value);
1313     im = cimagl(value);
1314
1315     ty = type->totym();
1316     switch (tybasic(ty))
1317     {
1318         case TYcfloat:
1319             c.Vcfloat.re = (float) re;
1320             if (Port::isSignallingNan(re))
1321             {   union { float f; unsigned i; } u;
1322                 u.f = c.Vcfloat.re;
1323                 u.i &= 0xFFBFFFFFL;
1324                 c.Vcfloat.re = u.f;
1325             }
1326             c.Vcfloat.im = (float) im;
1327             if (Port::isSignallingNan(im))
1328             {   union { float f; unsigned i; } u;
1329                 u.f = c.Vcfloat.im;
1330                 u.i &= 0xFFBFFFFFL;
1331                 c.Vcfloat.im = u.f;
1332             }
1333             break;
1334
1335         case TYcdouble:
1336             c.Vcdouble.re = (double) re;
1337             if (Port::isSignallingNan(re))
1338             {   union { double d; unsigned long long i; } u;
1339                 u.d = c.Vcdouble.re;
1340                 u.i &= 0xFFF7FFFFFFFFFFFFULL;
1341                 c.Vcdouble.re = u.d;
1342             }
1343             c.Vcdouble.im = (double) im;
1344             if (Port::isSignallingNan(re))
1345             {   union { double d; unsigned long long i; } u;
1346                 u.d = c.Vcdouble.im;
1347                 u.i &= 0xFFF7FFFFFFFFFFFFULL;
1348                 c.Vcdouble.im = u.d;
1349             }
1350             break;
1351
1352         case TYcldouble:
1353 #if 1
1354             c.Vcldouble.re = re;
1355             c.Vcldouble.im = im;
1356 #else
1357 {unsigned short *p = (unsigned short *)&c.Vcldouble;
1358 for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
1359 printf("\n");}
1360             c.Vcldouble.im = im;
1361 {unsigned short *p = (unsigned short *)&c.Vcldouble;
1362 for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
1363 printf("\n");}
1364             c.Vcldouble.re = re;
1365 {unsigned short *p = (unsigned short *)&c.Vcldouble;
1366 for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
1367 printf("\n");}
1368 #endif
1369             break;
1370
1371         default:
1372             assert(0);
1373     }
1374     return el_const(ty, &c);
1375 }
1376
1377 /***************************************
1378  */
1379
1380 elem *NullExp::toElem(IRState *irs)
1381 {
1382     return el_long(type->totym(), 0);
1383 }
1384
1385 /***************************************
1386  */
1387
1388 struct StringTab
1389 {
1390     Module *m;          // module we're generating code for
1391     Symbol *si;
1392     void *string;
1393     size_t sz;
1394     size_t len;
1395 };
1396
1397 #define STSIZE 16
1398 StringTab stringTab[STSIZE];
1399 size_t stidx;
1400
1401 static Symbol *assertexp_sfilename = NULL;
1402 static const char *assertexp_name = NULL;
1403 static Module *assertexp_mn = NULL;
1404
1405 void clearStringTab()
1406 {
1407     //printf("clearStringTab()\n");
1408     memset(stringTab, 0, sizeof(stringTab));
1409     stidx = 0;
1410
1411     assertexp_sfilename = NULL;
1412     assertexp_name = NULL;
1413     assertexp_mn = NULL;
1414 }
1415
1416 elem *StringExp::toElem(IRState *irs)
1417 {
1418     elem *e;
1419     Type *tb= type->toBasetype();
1420
1421
1422 #if 0
1423     printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars());
1424 #endif
1425
1426     if (tb->ty == Tarray)
1427     {
1428         Symbol *si;
1429         dt_t *dt;
1430         StringTab *st;
1431
1432 #if 0
1433         printf("irs->m = %p\n", irs->m);
1434         printf(" m   = %s\n", irs->m->toChars());
1435         printf(" len = %d\n", len);
1436         printf(" sz  = %d\n", sz);
1437 #endif
1438         for (size_t i = 0; i < STSIZE; i++)
1439         {
1440             st = &stringTab[(stidx + i) % STSIZE];
1441             //if (!st->m) continue;
1442             //printf(" st.m   = %s\n", st->m->toChars());
1443             //printf(" st.len = %d\n", st->len);
1444             //printf(" st.sz  = %d\n", st->sz);
1445             if (st->m == irs->m &&
1446                 st->si &&
1447                 st->len == len &&
1448                 st->sz == sz &&
1449                 memcmp(st->string, string, sz * len) == 0)
1450             {
1451                 //printf("use cached value\n");
1452                 si = st->si;    // use cached value
1453                 goto L1;
1454             }
1455         }
1456
1457         stidx = (stidx + 1) % STSIZE;
1458         st = &stringTab[stidx];
1459
1460         dt = NULL;
1461         toDt(&dt);
1462
1463         si = symbol_generate(SCstatic,type_fake(TYdarray));
1464         si->Sdt = dt;
1465         si->Sfl = FLdata;
1466 #if ELFOBJ // Burton
1467         si->Sseg = CDATA;
1468 #endif
1469 #if MACHOBJ
1470         si->Sseg = DATA;
1471 #endif
1472         outdata(si);
1473
1474         st->m = irs->m;
1475         st->si = si;
1476         st->string = string;
1477         st->len = len;
1478         st->sz = sz;
1479     L1:
1480         e = el_var(si);
1481     }
1482     else if (tb->ty == Tsarray)
1483     {
1484         dt_t *dt = NULL;
1485
1486         toDt(&dt);
1487         dtnzeros(&dt, sz);              // leave terminating 0
1488
1489         ::type *t = type_allocn(TYarray, tschar);
1490         t->Tdim = sz * len;
1491         Symbol *si = symbol_generate(SCstatic, t);
1492         si->Sdt = dt;
1493         si->Sfl = FLdata;
1494
1495 #if ELFOBJ || MACHOBJ // Burton
1496         si->Sseg = CDATA;
1497 #endif
1498         outdata(si);
1499
1500         e = el_var(si);
1501         e->ET = t;
1502         t->Tcount++;
1503     }
1504     else if (tb->ty == Tpointer)
1505     {
1506         e = el_calloc();
1507         e->Eoper = OPstring;
1508 #if 1
1509         // Match MEM_PH_FREE for OPstring in ztc\el.c
1510         e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz);
1511         memcpy(e->EV.ss.Vstring, string, (len + 1) * sz);
1512 #else
1513         e->EV.ss.Vstring = (char *)string;
1514 #endif
1515         e->EV.ss.Vstrlen = (len + 1) * sz;
1516         e->Ety = TYnptr;
1517     }
1518     else
1519     {
1520         printf("type is %s\n", type->toChars());
1521         assert(0);
1522     }
1523     el_setLoc(e,loc);
1524     return e;
1525 }
1526
1527 elem *NewExp::toElem(IRState *irs)
1528 {   elem *e;
1529     Type *t;
1530     Type *ectype;
1531
1532     //printf("NewExp::toElem() %s\n", toChars());
1533     t = type->toBasetype();
1534     //printf("\ttype = %s\n", t->toChars());
1535     //if (member)
1536         //printf("\tmember = %s\n", member->toChars());
1537     if (t->ty == Tclass)
1538     {
1539         Symbol *csym;
1540
1541         t = newtype->toBasetype();
1542         assert(t->ty == Tclass);
1543         TypeClass *tclass = (TypeClass *)(t);
1544         ClassDeclaration *cd = tclass->sym;
1545
1546         /* Things to do:
1547          * 1) ex: call allocator
1548          * 2) ey: set vthis for nested classes
1549          * 3) ez: call constructor
1550          */
1551
1552         elem *ex = NULL;
1553         elem *ey = NULL;
1554         elem *ez = NULL;
1555
1556         if (allocator || onstack)
1557         {   elem *ei;
1558             Symbol *si;
1559
1560             if (onstack)
1561             {
1562                 /* Create an instance of the class on the stack,
1563                  * and call it stmp.
1564                  * Set ex to be the &stmp.
1565                  */
1566                 Symbol *s = symbol_calloc(tclass->sym->toChars());
1567                 s->Sclass = SCstruct;
1568                 s->Sstruct = struct_calloc();
1569                 s->Sstruct->Sflags |= 0;
1570                 s->Sstruct->Salignsize = tclass->sym->alignsize;
1571                 s->Sstruct->Sstructalign = tclass->sym->structalign;
1572                 s->Sstruct->Sstructsize = tclass->sym->structsize;
1573
1574                 ::type *tc = type_alloc(TYstruct);
1575                 tc->Ttag = (Classsym *)s;                // structure tag name
1576                 tc->Tcount++;
1577                 s->Stype = tc;
1578
1579                 Symbol *stmp = symbol_genauto(tc);
1580                 ex = el_ptr(stmp);
1581             }
1582             else
1583             {
1584                 ex = el_var(allocator->toSymbol());
1585                 ex = callfunc(loc, irs, 1, type, ex, allocator->type,
1586                         allocator, allocator->type, NULL, newargs);
1587             }
1588
1589             si = tclass->sym->toInitializer();
1590             ei = el_var(si);
1591
1592             if (cd->isNested())
1593             {
1594                 ey = el_same(&ex);
1595                 ez = el_copytree(ey);
1596             }
1597             else if (member)
1598                 ez = el_same(&ex);
1599
1600             ex = el_una(OPind, TYstruct, ex);
1601             ex = el_bin(OPstreq, TYnptr, ex, ei);
1602             ex->ET = tclass->toCtype()->Tnext;
1603             ex = el_una(OPaddr, TYnptr, ex);
1604             ectype = tclass;
1605         }
1606         else
1607         {
1608             csym = cd->toSymbol();
1609             ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym));
1610             ectype = NULL;
1611
1612             if (cd->isNested())
1613             {
1614                 ey = el_same(&ex);
1615                 ez = el_copytree(ey);
1616             }
1617             else if (member)
1618                 ez = el_same(&ex);
1619 //elem_print(ex);
1620 //elem_print(ey);
1621 //elem_print(ez);
1622         }
1623
1624         if (thisexp)
1625         {   ClassDeclaration *cdthis = thisexp->type->isClassHandle();
1626             assert(cdthis);
1627             //printf("cd = %s\n", cd->toChars());
1628             //printf("cdthis = %s\n", cdthis->toChars());
1629             assert(cd->isNested());
1630             int offset = 0;
1631             Dsymbol *cdp = cd->toParent2();     // class we're nested in
1632             elem *ethis;
1633
1634 //printf("member = %p\n", member);
1635 //printf("cdp = %s\n", cdp->toChars());
1636 //printf("cdthis = %s\n", cdthis->toChars());
1637             if (cdp != cdthis)
1638             {   int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset);
1639                 assert(i);
1640             }
1641             ethis = thisexp->toElem(irs);
1642             if (offset)
1643                 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, offset));
1644
1645             if (!cd->vthis)
1646             {
1647                 error("forward reference to %s", cd->toChars());
1648             }
1649             else
1650             {
1651                 ey = el_bin(OPadd, TYnptr, ey, el_long(TYsize_t, cd->vthis->offset));
1652                 ey = el_una(OPind, TYnptr, ey);
1653                 ey = el_bin(OPeq, TYnptr, ey, ethis);
1654             }
1655 //printf("ex: "); elem_print(ex);
1656 //printf("ey: "); elem_print(ey);
1657 //printf("ez: "); elem_print(ez);
1658         }
1659         else if (cd->isNested())
1660         {   /* Initialize cd->vthis:
1661              *  *(ey + cd.vthis.offset) = this;
1662              */
1663             ey = setEthis(loc, irs, ey, cd);
1664         }
1665
1666         if (member)
1667             // Call constructor
1668             ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
1669
1670         e = el_combine(ex, ey);
1671         e = el_combine(e, ez);
1672     }
1673 #if DMDV2
1674     else if (t->ty == Tpointer && t->nextOf()->toBasetype()->ty == Tstruct)
1675     {
1676         Symbol *csym;
1677
1678         t = newtype->toBasetype();
1679         assert(t->ty == Tstruct);
1680         TypeStruct *tclass = (TypeStruct *)(t);
1681         StructDeclaration *cd = tclass->sym;
1682
1683         /* Things to do:
1684          * 1) ex: call allocator
1685          * 2) ey: set vthis for nested classes
1686          * 3) ez: call constructor
1687          */
1688
1689         elem *ex = NULL;
1690         elem *ey = NULL;
1691         elem *ez = NULL;
1692
1693         if (allocator)
1694         {   elem *ei;
1695             Symbol *si;
1696
1697             ex = el_var(allocator->toSymbol());
1698             ex = callfunc(loc, irs, 1, type, ex, allocator->type,
1699                         allocator, allocator->type, NULL, newargs);
1700
1701             si = tclass->sym->toInitializer();
1702             ei = el_var(si);
1703
1704             if (cd->isNested())
1705             {
1706                 ey = el_same(&ex);
1707                 ez = el_copytree(ey);
1708             }
1709             else if (member)
1710                 ez = el_same(&ex);
1711
1712             if (!member)
1713             {   /* Statically intialize with default initializer
1714                  */
1715                 ex = el_una(OPind, TYstruct, ex);
1716                 ex = el_bin(OPstreq, TYnptr, ex, ei);
1717                 ex->ET = tclass->toCtype();
1718                 ex = el_una(OPaddr, TYnptr, ex);
1719             }
1720             ectype = tclass;
1721         }
1722         else
1723         {
1724             d_uns64 elemsize = cd->size(loc);
1725
1726             // call _d_newarrayT(ti, 1)
1727             e = el_long(TYsize_t, 1);
1728             e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1729
1730             int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1731             e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1732
1733             // The new functions return an array, so convert to a pointer
1734             // ex -> (unsigned)(e >> 32)
1735             e = el_bin(OPshr, TYdarray, e, el_long(TYint, PTRSIZE * 8));
1736             ex = el_una(OP64_32, TYnptr, e);
1737
1738             ectype = NULL;
1739
1740             if (cd->isNested())
1741             {
1742                 ey = el_same(&ex);
1743                 ez = el_copytree(ey);
1744             }
1745             else if (member)
1746                 ez = el_same(&ex);
1747 //elem_print(ex);
1748 //elem_print(ey);
1749 //elem_print(ez);
1750         }
1751
1752         if (cd->isNested())
1753         {   /* Initialize cd->vthis:
1754              *  *(ey + cd.vthis.offset) = this;
1755              */
1756             ey = setEthis(loc, irs, ey, cd);
1757         }
1758
1759         if (member)
1760         {   // Call constructor
1761             ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
1762 #if STRUCTTHISREF
1763             /* Structs return a ref, which gets automatically dereferenced.
1764              * But we want a pointer to the instance.
1765              */
1766             ez = el_una(OPaddr, TYnptr, ez);
1767 #endif
1768         }
1769
1770         e = el_combine(ex, ey);
1771         e = el_combine(e, ez);
1772     }
1773 #endif
1774     else if (t->ty == Tarray)
1775     {
1776         TypeDArray *tda = (TypeDArray *)(t);
1777
1778         assert(arguments && arguments->dim >= 1);
1779         if (arguments->dim == 1)
1780         {   // Single dimension array allocations
1781             Expression *arg = (Expression *)arguments->data[0]; // gives array length
1782             e = arg->toElem(irs);
1783             d_uns64 elemsize = tda->next->size();
1784
1785             // call _d_newT(ti, arg)
1786             e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1787             int rtl = tda->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1788             e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1789         }
1790         else
1791         {   // Multidimensional array allocations
1792             e = el_long(TYsize_t, arguments->dim);
1793             for (size_t i = 0; i < arguments->dim; i++)
1794             {
1795                 Expression *arg = (Expression *)arguments->data[i];     // gives array length
1796                 e = el_param(arg->toElem(irs), e);
1797                 assert(t->ty == Tarray);
1798                 t = t->nextOf();
1799                 assert(t);
1800             }
1801
1802             e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1803
1804             int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
1805             e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1806             e->Eflags |= EFLAGS_variadic;
1807         }
1808     }
1809     else if (t->ty == Tpointer)
1810     {
1811         TypePointer *tp = (TypePointer *)t;
1812         d_uns64 elemsize = tp->next->size();
1813         Expression *di = tp->next->defaultInit();
1814         d_uns64 disize = di->type->size();
1815
1816         // call _d_newarrayT(ti, 1)
1817         e = el_long(TYsize_t, 1);
1818         e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1819
1820         int rtl = tp->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1821         e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1822
1823         // The new functions return an array, so convert to a pointer
1824         // e -> (unsigned)(e >> 32)
1825         e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
1826         e = el_una(I64 ? OP128_64 : OP64_32, t->totym(), e);
1827     }
1828     else
1829     {
1830         assert(0);
1831     }
1832
1833     el_setLoc(e,loc);
1834     return e;
1835 }
1836
1837 //////////////////////////// Unary ///////////////////////////////
1838
1839 /***************************************
1840  */
1841
1842 elem *NegExp::toElem(IRState *irs)
1843 {
1844     elem *e = el_una(OPneg, type->totym(), e1->toElem(irs));
1845
1846     Type *tb1 = e1->type->toBasetype();
1847     if (tb1->ty == Tarray || tb1->ty == Tsarray)
1848     {
1849         error("Array operation %s not implemented", toChars());
1850         e = el_long(type->totym(), 0);  // error recovery
1851     }
1852
1853     el_setLoc(e,loc);
1854     return e;
1855 }
1856
1857 /***************************************
1858  */
1859
1860 elem *ComExp::toElem(IRState *irs)
1861 {   elem *e;
1862
1863     elem *e1 = this->e1->toElem(irs);
1864     tym_t ty = type->totym();
1865     if (this->e1->type->toBasetype()->ty == Tbool)
1866         e = el_bin(OPxor, ty, e1, el_long(ty, 1));
1867     else
1868         e = el_una(OPcom,ty,e1);
1869     el_setLoc(e,loc);
1870     return e;
1871 }
1872
1873 /***************************************
1874  */
1875
1876 elem *NotExp::toElem(IRState *irs)
1877 {
1878     elem *e = el_una(OPnot, type->totym(), e1->toElem(irs));
1879     el_setLoc(e,loc);
1880     return e;
1881 }
1882
1883
1884 /***************************************
1885  */
1886
1887 elem *HaltExp::toElem(IRState *irs)
1888 {   elem *e;
1889
1890     e = el_calloc();
1891     e->Ety = TYvoid;
1892     e->Eoper = OPhalt;
1893     el_setLoc(e,loc);
1894     return e;
1895 }
1896
1897 /********************************************
1898  */
1899
1900 elem *AssertExp::toElem(IRState *irs)
1901 {   elem *e;
1902     elem *ea;
1903     Type *t1 = e1->type->toBasetype();
1904
1905     //printf("AssertExp::toElem() %s\n", toChars());
1906     if (global.params.useAssert)
1907     {
1908         e = e1->toElem(irs);
1909
1910         InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1;
1911
1912         // If e1 is a class object, call the class invariant on it
1913         if (global.params.useInvariants && t1->ty == Tclass &&
1914             !((TypeClass *)t1)->sym->isInterfaceDeclaration())
1915         {
1916 #if TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
1917             e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
1918 #else
1919             e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
1920 #endif
1921         }
1922         // If e1 is a struct object, call the struct invariant on it
1923         else if (global.params.useInvariants &&
1924             t1->ty == Tpointer &&
1925             t1->nextOf()->ty == Tstruct &&
1926             (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL)
1927         {
1928             e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL);
1929         }
1930         else
1931         {
1932             // Construct: (e1 || ModuleAssert(line))
1933             Module *m = irs->blx->module;
1934             char *mname = m->srcfile->toChars();
1935
1936             //printf("filename = '%s'\n", loc.filename);
1937             //printf("module = '%s'\n", m->srcfile->toChars());
1938
1939             /* Determine if we are in a unittest
1940              */
1941             FuncDeclaration *fd = irs->getFunc();
1942             UnitTestDeclaration *ud = fd ? fd->isUnitTestDeclaration() : NULL;
1943
1944             /* If the source file name has changed, probably due
1945              * to a #line directive.
1946              */
1947             if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
1948             {   elem *efilename;
1949
1950                 /* Cache values.
1951                  */
1952                 //static Symbol *assertexp_sfilename = NULL;
1953                 //static char *assertexp_name = NULL;
1954                 //static Module *assertexp_mn = NULL;
1955
1956                 if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m)
1957                 {
1958                     dt_t *dt = NULL;
1959                     const char *id;
1960                     int len;
1961
1962                     id = loc.filename;
1963                     len = strlen(id);
1964                     dtsize_t(&dt, len);
1965                     dtabytes(&dt,TYnptr, 0, len + 1, id);
1966
1967                     assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
1968                     assertexp_sfilename->Sdt = dt;
1969                     assertexp_sfilename->Sfl = FLdata;
1970 #if ELFOBJ
1971                     assertexp_sfilename->Sseg = CDATA;
1972 #endif
1973 #if MACHOBJ
1974                     assertexp_sfilename->Sseg = DATA;
1975 #endif
1976                     outdata(assertexp_sfilename);
1977
1978                     assertexp_mn = m;
1979                     assertexp_name = id;
1980                 }
1981
1982                 efilename = el_var(assertexp_sfilename);
1983
1984                 if (msg)
1985                 {   elem *emsg = msg->toElem(irs);
1986                     ea = el_var(rtlsym[ud ? RTLSYM_DUNITTEST_MSG : RTLSYM_DASSERT_MSG]);
1987                     ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
1988                 }
1989                 else
1990                 {
1991                     ea = el_var(rtlsym[ud ? RTLSYM_DUNITTEST : RTLSYM_DASSERT]);
1992                     ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
1993                 }
1994             }
1995             else
1996             {
1997                 Symbol *sassert = ud ? m->toModuleUnittest() : m->toModuleAssert();
1998                 ea = el_bin(OPcall,TYvoid,el_var(sassert),
1999                     el_long(TYint, loc.linnum));
2000             }
2001             e = el_bin(OPoror,TYvoid,e,ea);
2002         }
2003     }
2004     else
2005     {   // BUG: should replace assert(0); with a HLT instruction
2006         e = el_long(TYint, 0);
2007     }
2008     el_setLoc(e,loc);
2009     return e;
2010 }
2011
2012 elem *PostExp::toElem(IRState *irs)
2013 {
2014     elem *e = e1->toElem(irs);
2015     elem *einc = e2->toElem(irs);
2016     e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
2017                 e->Ety,e,einc);
2018     el_setLoc(e,loc);
2019     return e;
2020 }
2021
2022 //////////////////////////// Binary ///////////////////////////////
2023
2024 /********************************************
2025  */
2026
2027 elem *BinExp::toElemBin(IRState *irs,int op)
2028 {
2029     //printf("toElemBin() '%s'\n", toChars());
2030
2031     Type *tb1 = e1->type->toBasetype();
2032     Type *tb2 = e2->type->toBasetype();
2033
2034     if ((tb1->ty == Tarray || tb1->ty == Tsarray ||
2035          tb2->ty == Tarray || tb2->ty == Tsarray) &&
2036         tb2->ty != Tvoid &&
2037         op != OPeq && op != OPandand && op != OPoror
2038        )
2039     {
2040         error("Array operation %s not implemented", toChars());
2041         return el_long(type->totym(), 0);  // error recovery
2042     }
2043
2044     tym_t tym = type->totym();
2045
2046     elem *el = e1->toElem(irs);
2047     elem *er = e2->toElem(irs);
2048     elem *e = el_bin(op,tym,el,er);
2049
2050     el_setLoc(e,loc);
2051     return e;
2052 }
2053
2054 /***************************************
2055  */
2056
2057 elem *AddExp::toElem(IRState *irs)
2058 {
2059     elem *e = toElemBin(irs,OPadd);
2060     return e;
2061 }
2062
2063 /***************************************
2064  */
2065
2066 elem *MinExp::toElem(IRState *irs)
2067 {
2068     elem *e = toElemBin(irs,OPmin);
2069     return e;
2070 }
2071
2072 /***************************************
2073  */
2074
2075 elem *CatExp::toElem(IRState *irs)
2076 {   elem *e;
2077
2078 #if 0
2079     printf("CatExp::toElem()\n");
2080     print();
2081 #endif
2082
2083     Type *tb1 = e1->type->toBasetype();
2084     Type *tb2 = e2->type->toBasetype();
2085     Type *tn;
2086
2087 #if 0
2088     if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
2089         (tb2->ty == Tarray || tb2->ty == Tsarray)
2090        )
2091 #endif
2092
2093     Type *ta = tb1->nextOf() ? e1->type : e2->type;
2094     tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf();
2095     {
2096         if (e1->op == TOKcat)
2097         {
2098             elem *ep;
2099             CatExp *ce = this;
2100             int n = 2;
2101
2102             ep = eval_Darray(irs, ce->e2);
2103             do
2104             {
2105                 n++;
2106                 ce = (CatExp *)ce->e1;
2107                 ep = el_param(ep, eval_Darray(irs, ce->e2));
2108             } while (ce->e1->op == TOKcat);
2109             ep = el_param(ep, eval_Darray(irs, ce->e1));
2110 #if 1
2111             ep = el_params(
2112                            ep,
2113                            el_long(TYsize_t, n),
2114                            ta->getTypeInfo(NULL)->toElem(irs),
2115                            NULL);
2116             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep);
2117             e->Eflags |= EFLAGS_variadic;
2118 #else
2119             ep = el_params(
2120                            ep,
2121                            el_long(TYsize_t, n),
2122                            el_long(TYsize_t, tn->size()),
2123                            NULL);
2124             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep);
2125             e->Eflags |= EFLAGS_variadic;
2126 #endif
2127         }
2128         else
2129         {
2130             elem *e1;
2131             elem *e2;
2132             elem *ep;
2133
2134             e1 = eval_Darray(irs, this->e1);
2135             e2 = eval_Darray(irs, this->e2);
2136 #if 1
2137             ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL);
2138             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep);
2139 #else
2140             ep = el_params(el_long(TYsize_t, tn->size()), e2, e1, NULL);
2141             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep);
2142 #endif
2143         }
2144         el_setLoc(e,loc);
2145     }
2146 #if 0
2147     else if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
2148              e2->type->equals(tb1->next))
2149     {
2150         error("array cat with element not implemented");
2151         e = el_long(TYint, 0);
2152     }
2153     else
2154         assert(0);
2155 #endif
2156     return e;
2157 }
2158
2159 /***************************************
2160  */
2161
2162 elem *MulExp::toElem(IRState *irs)
2163 {
2164     return toElemBin(irs,OPmul);
2165 }
2166
2167 /************************************
2168  */
2169
2170 elem *DivExp::toElem(IRState *irs)
2171 {
2172     return toElemBin(irs,OPdiv);
2173 }
2174
2175 /***************************************
2176  */
2177
2178 elem *ModExp::toElem(IRState *irs)
2179 {
2180     elem *e;
2181     elem *e1;
2182     elem *e2;
2183     tym_t tym;
2184
2185     tym = type->totym();
2186
2187     e1 = this->e1->toElem(irs);
2188     e2 = this->e2->toElem(irs);
2189
2190 #if 0 // Now inlined
2191     if (this->e1->type->isfloating())
2192     {   elem *ep;
2193
2194         switch (this->e1->type->ty)
2195         {
2196             case Tfloat32:
2197             case Timaginary32:
2198                 e1 = el_una(OPf_d, TYdouble, e1);
2199                 e2 = el_una(OPf_d, TYdouble, e2);
2200             case Tfloat64:
2201             case Timaginary64:
2202                 e1 = el_una(OPd_ld, TYldouble, e1);
2203                 e2 = el_una(OPd_ld, TYldouble, e2);
2204                 break;
2205             case Tfloat80:
2206             case Timaginary80:
2207                 break;
2208             default:
2209                 assert(0);
2210                 break;
2211         }
2212         ep = el_param(e2,e1);
2213         e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep);
2214     }
2215     else
2216 #endif
2217         e = el_bin(OPmod,tym,e1,e2);
2218     el_setLoc(e,loc);
2219     return e;
2220 }
2221
2222 /***************************************
2223  */
2224
2225 elem *CmpExp::toElem(IRState *irs)
2226 {
2227     elem *e;
2228     enum OPER eop;
2229     Type *t1 = e1->type->toBasetype();
2230     Type *t2 = e2->type->toBasetype();
2231
2232     switch (op)
2233     {
2234         case TOKlt:     eop = OPlt;     break;
2235         case TOKgt:     eop = OPgt;     break;
2236         case TOKle:     eop = OPle;     break;
2237         case TOKge:     eop = OPge;     break;
2238         case TOKequal:  eop = OPeqeq;   break;
2239         case TOKnotequal: eop = OPne;   break;
2240
2241         // NCEG floating point compares
2242         case TOKunord:  eop = OPunord;  break;
2243         case TOKlg:     eop = OPlg;     break;
2244         case TOKleg:    eop = OPleg;    break;
2245         case TOKule:    eop = OPule;    break;
2246         case TOKul:     eop = OPul;     break;
2247         case TOKuge:    eop = OPuge;    break;
2248         case TOKug:     eop = OPug;     break;
2249         case TOKue:     eop = OPue;     break;
2250         default:
2251             dump(0);
2252             assert(0);
2253     }
2254     if (!t1->isfloating())
2255     {
2256         // Convert from floating point compare to equivalent
2257         // integral compare
2258         eop = (enum OPER)rel_integral(eop);
2259     }
2260     if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass)
2261     {
2262 #if 1
2263         assert(0);
2264 #else
2265         elem *ec1;
2266         elem *ec2;
2267
2268         ec1 = e1->toElem(irs);
2269         ec2 = e2->toElem(irs);
2270         e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2));
2271         e = el_bin(eop, TYint, e, el_long(TYint, 0));
2272 #endif
2273     }
2274     else if ((int)eop > 1 &&
2275              (t1->ty == Tarray || t1->ty == Tsarray) &&
2276              (t2->ty == Tarray || t2->ty == Tsarray))
2277     {
2278         elem *ea1;
2279         elem *ea2;
2280         elem *ep;
2281         Type *telement = t1->nextOf()->toBasetype();
2282         int rtlfunc;
2283
2284         ea1 = e1->toElem(irs);
2285         ea1 = array_toDarray(t1, ea1);
2286         ea2 = e2->toElem(irs);
2287         ea2 = array_toDarray(t2, ea2);
2288
2289 #if DMDV2
2290         ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs),
2291                 ea2, ea1, NULL);
2292         rtlfunc = RTLSYM_ARRAYCMP2;
2293 #else
2294         ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
2295         rtlfunc = RTLSYM_ARRAYCMP;
2296 #endif
2297         e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
2298         e = el_bin(eop, TYint, e, el_long(TYint, 0));
2299         el_setLoc(e,loc);
2300     }
2301     else
2302     {
2303         if ((int)eop <= 1)
2304         {
2305             /* The result is determinate, create:
2306              *   (e1 , e2) , eop
2307              */
2308             e = toElemBin(irs,OPcomma);
2309             e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop));
2310         }
2311         else
2312             e = toElemBin(irs,eop);
2313     }
2314     return e;
2315 }
2316
2317 elem *EqualExp::toElem(IRState *irs)
2318 {
2319     //printf("EqualExp::toElem() %s\n", toChars());
2320
2321     elem *e;
2322     enum OPER eop;
2323     Type *t1 = e1->type->toBasetype();
2324     Type *t2 = e2->type->toBasetype();
2325
2326     switch (op)
2327     {
2328         case TOKequal:          eop = OPeqeq;   break;
2329         case TOKnotequal:       eop = OPne;     break;
2330         default:
2331             dump(0);
2332             assert(0);
2333     }
2334
2335     //printf("EqualExp::toElem()\n");
2336     if (t1->ty == Tstruct)
2337     {   // Do bit compare of struct's
2338
2339         elem *es1 = e1->toElem(irs);
2340         elem *es2 = e2->toElem(irs);
2341         es1 = addressElem(es1, t1);
2342         es2 = addressElem(es2, t2);
2343         e = el_param(es1, es2);
2344         elem *ecount = el_long(TYsize_t, t1->size());
2345         e = el_bin(OPmemcmp, TYint, e, ecount);
2346         e = el_bin(eop, TYint, e, el_long(TYint, 0));
2347         el_setLoc(e,loc);
2348     }
2349 #if 0
2350     else if (t1->ty == Tclass && t2->ty == Tclass)
2351     {
2352         elem *ec1 = e1->toElem(irs);
2353         elem *ec2 = e2->toElem(irs);
2354         e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
2355     }
2356 #endif
2357     else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
2358              (t2->ty == Tarray || t2->ty == Tsarray))
2359     {
2360         Type *telement = t1->nextOf()->toBasetype();
2361
2362         elem *ea1 = e1->toElem(irs);
2363         ea1 = array_toDarray(t1, ea1);
2364         elem *ea2 = e2->toElem(irs);
2365         ea2 = array_toDarray(t2, ea2);
2366
2367 #if DMDV2
2368         elem *ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs),
2369                 ea2, ea1, NULL);
2370         int rtlfunc = RTLSYM_ARRAYEQ2;
2371 #else
2372         elem *ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
2373         int rtlfunc = RTLSYM_ARRAYEQ;
2374 #endif
2375         e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
2376         if (op == TOKnotequal)
2377             e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
2378         el_setLoc(e,loc);
2379     }
2380     else if (t1->ty == Taarray && t2->ty == Taarray)
2381     {   TypeAArray *taa = (TypeAArray *)t1;
2382         Symbol *s = taa->aaGetSymbol("Equal", 0);
2383         elem *ti = taa->getTypeInfo(NULL)->toElem(irs);
2384         elem *ea1 = e1->toElem(irs);
2385         elem *ea2 = e2->toElem(irs);
2386         // aaEqual(ti, e1, e2)
2387         elem *ep = el_params(ea2, ea1, ti, NULL);
2388         e = el_bin(OPcall, TYnptr, el_var(s), ep);
2389         if (op == TOKnotequal)
2390             e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
2391         el_setLoc(e,loc);
2392         return e;
2393     }
2394     else
2395         e = toElemBin(irs, eop);
2396     return e;
2397 }
2398
2399 elem *IdentityExp::toElem(IRState *irs)
2400 {
2401     elem *e;
2402     enum OPER eop;
2403     Type *t1 = e1->type->toBasetype();
2404     Type *t2 = e2->type->toBasetype();
2405
2406     switch (op)
2407     {
2408         case TOKidentity:       eop = OPeqeq;   break;
2409         case TOKnotidentity:    eop = OPne;     break;
2410         default:
2411             dump(0);
2412             assert(0);
2413     }
2414
2415     //printf("IdentityExp::toElem() %s\n", toChars());
2416
2417     if (t1->ty == Tstruct)
2418     {   // Do bit compare of struct's
2419         elem *es1;
2420         elem *es2;
2421         elem *ecount;
2422
2423         es1 = e1->toElem(irs);
2424         es1 = addressElem(es1, e1->type);
2425         //es1 = el_una(OPaddr, TYnptr, es1);
2426         es2 = e2->toElem(irs);
2427         es2 = addressElem(es2, e2->type);
2428         //es2 = el_una(OPaddr, TYnptr, es2);
2429         e = el_param(es1, es2);
2430         ecount = el_long(TYsize_t, t1->size());
2431         e = el_bin(OPmemcmp, TYint, e, ecount);
2432         e = el_bin(eop, TYint, e, el_long(TYint, 0));
2433         el_setLoc(e,loc);
2434     }
2435     else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
2436              (t2->ty == Tarray || t2->ty == Tsarray))
2437     {
2438         elem *ea1;
2439         elem *ea2;
2440
2441         ea1 = e1->toElem(irs);
2442         ea1 = array_toDarray(t1, ea1);
2443         ea2 = e2->toElem(irs);
2444         ea2 = array_toDarray(t2, ea2);
2445
2446         e = el_bin(eop, type->totym(), ea1, ea2);
2447         el_setLoc(e,loc);
2448     }
2449     else
2450         e = toElemBin(irs, eop);
2451
2452     return e;
2453 }
2454
2455
2456 /***************************************
2457  */
2458
2459 elem *InExp::toElem(IRState *irs)
2460 {   elem *e;
2461     elem *key = e1->toElem(irs);
2462     elem *aa = e2->toElem(irs);
2463     elem *ep;
2464     elem *keyti;
2465     TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
2466
2467
2468     // set to:
2469     Symbol *s;
2470     if (I64)
2471     {
2472         // aaInX(aa, keyti, key);
2473         key = addressElem(key, e1->type);
2474         s = taa->aaGetSymbol("InX", 0);
2475     }
2476     else
2477     {
2478         //  aaIn(aa, keyti, key);
2479         if (tybasic(key->Ety) == TYstruct)
2480         {
2481             key = el_una(OPstrpar, TYstruct, key);
2482             key->ET = key->E1->ET;
2483         }
2484         else if (tybasic(key->Ety) == TYarray && taa->index->ty == Tsarray)
2485         {   // e2->elem() turns string literals into a TYarray, so the
2486             // length is lost. Restore it.
2487             key = el_una(OPstrpar, TYstruct, key);
2488             assert(e1->type->size() == taa->index->size());
2489             key->ET = taa->index->toCtype();
2490         }
2491
2492         s = taa->aaGetSymbol("In", 0);
2493     }
2494     keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
2495     ep = el_params(key, keyti, aa, NULL);
2496     e = el_bin(OPcall, type->totym(), el_var(s), ep);
2497
2498     el_setLoc(e,loc);
2499     return e;
2500 }
2501
2502 /***************************************
2503  */
2504
2505 elem *RemoveExp::toElem(IRState *irs)
2506 {   elem *e;
2507     Type *tb = e1->type->toBasetype();
2508     assert(tb->ty == Taarray);
2509     TypeAArray *taa = (TypeAArray *)tb;
2510     elem *ea = e1->toElem(irs);
2511     elem *ekey = e2->toElem(irs);
2512     elem *ep;
2513     elem *keyti;
2514
2515     Symbol *s;
2516     if (I64)
2517     {
2518         ekey = addressElem(ekey, e1->type);
2519         s = taa->aaGetSymbol("DelX", 0);
2520     }
2521     else
2522     {
2523         if (tybasic(ekey->Ety) == TYstruct || tybasic(ekey->Ety) == TYarray)
2524         {
2525             ekey = el_una(OPstrpar, TYstruct, ekey);
2526             ekey->ET = ekey->E1->ET;
2527         }
2528
2529         s = taa->aaGetSymbol("Del", 0);
2530     }
2531     keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
2532     ep = el_params(ekey, keyti, ea, NULL);
2533     e = el_bin(OPcall, TYnptr, el_var(s), ep);
2534
2535     el_setLoc(e,loc);
2536     return e;
2537 }
2538
2539 /***************************************
2540  */
2541
2542 elem *AssignExp::toElem(IRState *irs)
2543 {
2544     //printf("AssignExp::toElem('%s')\n", toChars());
2545     Type *t1b = e1->type->toBasetype();
2546
2547     // Look for array.length = n
2548     if (e1->op == TOKarraylength)
2549     {
2550         // Generate:
2551         //      _d_arraysetlength(e2, sizeelem, &ale->e1);
2552
2553         ArrayLengthExp *ale = (ArrayLengthExp *)e1;
2554
2555         elem *p1 = e2->toElem(irs);
2556         elem *p3 = ale->e1->toElem(irs);
2557         p3 = addressElem(p3, NULL);
2558         Type *t1 = ale->e1->type->toBasetype();
2559
2560         // call _d_arraysetlengthT(ti, e2, &ale->e1);
2561         elem *p2 = t1->getTypeInfo(NULL)->toElem(irs);
2562         elem *ep = el_params(p3, p1, p2, NULL); // c function
2563         int r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
2564
2565         elem *e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
2566         el_setLoc(e, loc);
2567         return e;
2568     }
2569
2570     elem *e;
2571     IndexExp *ae;
2572
2573     // Look for array[]=n
2574     if (e1->op == TOKslice)
2575     {
2576         SliceExp *are = (SliceExp *)(e1);
2577         Type *t1 = t1b;
2578         Type *t2 = e2->type->toBasetype();
2579
2580         // which we do if the 'next' types match
2581         if (ismemset)
2582         {   // Do a memset for array[]=v
2583             //printf("Lpair %s\n", toChars());
2584             SliceExp *are = (SliceExp *)e1;
2585             elem *evalue;
2586             elem *enbytes;
2587             elem *elength;
2588             elem *einit;
2589             dinteger_t value;
2590             Type *ta = are->e1->type->toBasetype();
2591             Type *tb = ta->nextOf()->toBasetype();
2592             int sz = tb->size();
2593             tym_t tym = type->totym();
2594
2595             elem *n1 = are->e1->toElem(irs);
2596             elem *elwr = are->lwr ? are->lwr->toElem(irs) : NULL;
2597             elem *eupr = are->upr ? are->upr->toElem(irs) : NULL;
2598
2599             elem *n1x = n1;
2600
2601             // Look for array[]=n
2602             if (ta->ty == Tsarray)
2603             {
2604                 TypeSArray *ts = (TypeSArray *) ta;
2605                 n1 = array_toPtr(ta, n1);
2606                 enbytes = ts->dim->toElem(irs);
2607                 n1x = n1;
2608                 n1 = el_same(&n1x);
2609                 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2610             }
2611             else if (ta->ty == Tarray)
2612             {
2613                 n1 = el_same(&n1x);
2614                 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2615                 enbytes = el_copytree(n1);
2616                 n1 = array_toPtr(ta, n1);
2617                 enbytes = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, enbytes);
2618             }
2619             else if (ta->ty == Tpointer)
2620             {
2621                 n1 = el_same(&n1x);
2622                 enbytes = el_long(TYsize_t, -1);   // largest possible index
2623                 einit = NULL;
2624             }
2625
2626             // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr
2627             elem *elwrx = elwr;
2628             if (elwr) elwr = el_same(&elwrx);
2629             elem *euprx = eupr;
2630             if (eupr) eupr = el_same(&euprx);
2631
2632 #if 0
2633             printf("sz = %d\n", sz);
2634             printf("n1x\n");
2635             elem_print(n1x);
2636             printf("einit\n");
2637             elem_print(einit);
2638             printf("elwrx\n");
2639             elem_print(elwrx);
2640             printf("euprx\n");
2641             elem_print(euprx);
2642             printf("n1\n");
2643             elem_print(n1);
2644             printf("elwr\n");
2645             elem_print(elwr);
2646             printf("eupr\n");
2647             elem_print(eupr);
2648             printf("enbytes\n");
2649             elem_print(enbytes);
2650 #endif
2651             einit = el_combine(n1x, einit);
2652             einit = el_combine(einit, elwrx);
2653             einit = el_combine(einit, euprx);
2654
2655             evalue = this->e2->toElem(irs);
2656
2657 #if 0
2658             printf("n1\n");
2659             elem_print(n1);
2660             printf("enbytes\n");
2661             elem_print(enbytes);
2662 #endif
2663
2664             if (irs->arrayBoundsCheck() && eupr && ta->ty != Tpointer)
2665             {
2666                 elem *c1;
2667                 elem *c2;
2668                 elem *ea;
2669                 elem *eb;
2670                 elem *enbytesx;
2671
2672                 assert(elwr);
2673                 enbytesx = enbytes;
2674                 enbytes = el_same(&enbytesx);
2675                 c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx);
2676                 c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr));
2677                 c1 = el_bin(OPandand, TYint, c1, c2);
2678
2679                 // Construct: (c1 || ModuleArray(line))
2680                 Symbol *sassert;
2681
2682                 sassert = irs->blx->module->toModuleArray();
2683                 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
2684                 eb = el_bin(OPoror,TYvoid,c1,ea);
2685                 einit = el_combine(einit, eb);
2686             }
2687
2688             if (elwr)
2689             {   elem *elwr2;
2690
2691                 el_free(enbytes);
2692                 elwr2 = el_copytree(elwr);
2693                 elwr2 = el_bin(OPmul, TYsize_t, elwr2, el_long(TYsize_t, sz));
2694                 n1 = el_bin(OPadd, TYnptr, n1, elwr2);
2695                 enbytes = el_bin(OPmin, TYsize_t, eupr, elwr);
2696                 elength = el_copytree(enbytes);
2697             }
2698             else
2699                 elength = el_copytree(enbytes);
2700             e = setArray(n1, enbytes, tb, evalue, irs, op);
2701         Lpair:
2702             e = el_pair(TYdarray, elength, e);
2703         Lret2:
2704             e = el_combine(einit, e);
2705             //elem_print(e);
2706             goto Lret;
2707         }
2708 #if 0
2709         else if (e2->op == TOKadd || e2->op == TOKmin)
2710         {
2711             /* It's ea[] = eb[] +- ec[]
2712              */
2713             BinExp *e2a = (BinExp *)e2;
2714             Type *t = e2->type->toBasetype()->nextOf()->toBasetype();
2715             if (t->ty != Tfloat32 && t->ty != Tfloat64 && t->ty != Tfloat80)
2716             {
2717                 e2->error("array add/min for %s not supported", t->toChars());
2718                 return el_long(TYint, 0);
2719             }
2720             elem *ea = e1->toElem(irs);
2721             ea = array_toDarray(e1->type, ea);
2722             elem *eb = e2a->e1->toElem(irs);
2723             eb = array_toDarray(e2a->e1->type, eb);
2724             elem *ec = e2a->e2->toElem(irs);
2725             ec = array_toDarray(e2a->e2->type, ec);
2726
2727             int rtl = RTLSYM_ARRAYASSADDFLOAT;
2728             if (t->ty == Tfloat64)
2729                 rtl = RTLSYM_ARRAYASSADDDOUBLE;
2730             else if (t->ty == Tfloat80)
2731                 rtl = RTLSYM_ARRAYASSADDREAL;
2732             if (e2->op == TOKmin)
2733             {
2734                 rtl = RTLSYM_ARRAYASSMINFLOAT;
2735                 if (t->ty == Tfloat64)
2736                     rtl = RTLSYM_ARRAYASSMINDOUBLE;
2737                 else if (t->ty == Tfloat80)
2738                     rtl = RTLSYM_ARRAYASSMINREAL;
2739             }
2740
2741             /* Set parameters so the order of evaluation is eb, ec, ea
2742              */
2743             elem *ep = el_params(eb, ec, ea, NULL);
2744             e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
2745             goto Lret;
2746         }
2747 #endif
2748         else
2749         {
2750             /* It's array1[]=array2[]
2751              * which is a memcpy
2752              */
2753             elem *ep;
2754
2755             elem *eto = e1->toElem(irs);
2756             elem *efrom = e2->toElem(irs);
2757
2758             unsigned size = t1->nextOf()->size();
2759             elem *esize = el_long(TYsize_t, size);
2760
2761             /* Determine if we need to do postblit
2762              */
2763             int postblit = 0;
2764             if (needsPostblit(t1))
2765                 postblit = 1;
2766
2767             assert(e2->type->ty != Tpointer);
2768
2769             if (!postblit && !irs->arrayBoundsCheck())
2770             {
2771                 elem *ex = el_same(&eto);
2772
2773                 // Determine if elen is a constant
2774                 elem *elen;
2775                 if (eto->Eoper == OPpair &&
2776                     eto->E1->Eoper == OPconst)
2777                 {
2778                     elen = el_copytree(eto->E1);
2779                 }
2780                 else
2781                 {
2782                     // It's not a constant, so pull it from the dynamic array
2783                     elen = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, el_copytree(ex));
2784                 }
2785
2786                 esize = el_bin(OPmul, TYsize_t, elen, esize);
2787                 elem *epto = array_toPtr(e1->type, ex);
2788                 elem *epfr = array_toPtr(e2->type, efrom);
2789 #if 1
2790                 // memcpy() is faster, so if we can't beat 'em, join 'em
2791                 e = el_params(esize, epfr, epto, NULL);
2792                 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_MEMCPY]),e);
2793 #else
2794                 e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize));
2795 #endif
2796                 e = el_pair(eto->Ety, el_copytree(elen), e);
2797                 e = el_combine(eto, e);
2798             }
2799 #if DMDV2
2800             else if (postblit && op != TOKblit)
2801             {
2802                 /* Generate:
2803                  *      _d_arrayassign(ti, efrom, eto)
2804                  * or:
2805                  *      _d_arrayctor(ti, efrom, eto)
2806                  */
2807                 el_free(esize);
2808                 Expression *ti = t1->nextOf()->toBasetype()->getTypeInfo(NULL);
2809                 ep = el_params(eto, efrom, ti->toElem(irs), NULL);
2810                 int rtl = (op == TOKconstruct) ? RTLSYM_ARRAYCTOR : RTLSYM_ARRAYASSIGN;
2811                 e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
2812             }
2813 #endif
2814             else
2815             {
2816                 // Generate:
2817                 //      _d_arraycopy(eto, efrom, esize)
2818
2819                 ep = el_params(eto, efrom, esize, NULL);
2820                 e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep);
2821             }
2822             el_setLoc(e, loc);
2823             return e;
2824         }
2825     }
2826
2827     if (e1->op == TOKindex)
2828     {
2829         elem *eb;
2830         elem *ei;
2831         elem *ev;
2832         TY ty;
2833         Type *ta;
2834
2835         ae = (IndexExp *)(e1);
2836         ta = ae->e1->type->toBasetype();
2837         ty = ta->ty;
2838     }
2839
2840 #if DMDV2
2841     /* Look for reference initializations
2842      */
2843     if (op == TOKconstruct && e1->op == TOKvar)
2844     {
2845         VarExp *ve = (VarExp *)e1;
2846         Declaration *s = ve->var;
2847         if (s->storage_class & (STCout | STCref))
2848         {
2849 #if 0
2850             Expression *ae = e2->addressOf(NULL);
2851             e = ae->toElem(irs);
2852 #else
2853             e = e2->toElem(irs);
2854             e = addressElem(e, e2->type);
2855 #endif
2856             elem *es = el_var(s->toSymbol());
2857             es->Ety = TYnptr;
2858             e = el_bin(OPeq, TYnptr, es, e);
2859 // BUG: type is struct, and e2 is TOKint64
2860             goto Lret;
2861         }
2862     }
2863 #endif
2864
2865 #if 1
2866     /* This will work if we can distinguish an assignment from
2867      * an initialization of the lvalue. It'll work if the latter.
2868      * If the former, because of aliasing of the return value with
2869      * function arguments, it'll fail.
2870      */
2871     if (op == TOKconstruct && e2->op == TOKcall)
2872     {   CallExp *ce = (CallExp *)e2;
2873
2874         TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype();
2875         if (tf->ty == Tfunction && tf->retStyle() == RETstack)
2876         {
2877             elem *ehidden = e1->toElem(irs);
2878             ehidden = el_una(OPaddr, TYnptr, ehidden);
2879             assert(!irs->ehidden);
2880             irs->ehidden = ehidden;
2881             e = e2->toElem(irs);
2882             goto Lret;
2883         }
2884     }
2885 #endif
2886 //if (op == TOKconstruct) printf("construct\n");
2887     if (t1b->ty == Tstruct || t1b->ty == Tsarray)
2888     {   elem *eleft = e1->toElem(irs);
2889
2890         if (e2->op == TOKint64)
2891         {   /* Implement:
2892              *  (struct = 0)
2893              * with:
2894              *  memset(&struct, 0, struct.sizeof)
2895              */
2896             elem *ey = NULL;
2897             int sz = e1->type->size();
2898             StructDeclaration *sd = ((TypeStruct *)t1b)->sym;
2899             if (sd->isnested && op == TOKconstruct)
2900             {
2901                 ey = el_una(OPaddr, TYnptr, eleft);
2902                 eleft = el_same(&ey);
2903                 ey = setEthis(loc, irs, ey, sd);
2904                 sz = sd->vthis->offset;
2905             }
2906
2907             elem *el = eleft;
2908             elem *enbytes = el_long(TYsize_t, sz);
2909             elem *evalue = el_long(TYsize_t, 0);
2910
2911             if (!(sd->isnested && op == TOKconstruct))
2912                 el = el_una(OPaddr, TYnptr, el);
2913             e = el_param(enbytes, evalue);
2914             e = el_bin(OPmemset,TYnptr,el,e);
2915             e = el_combine(ey, e);
2916             el_setLoc(e, loc);
2917             //e = el_una(OPind, TYstruct, e);
2918         }
2919         else
2920         {
2921             //printf("toElemBin() '%s'\n", toChars());
2922
2923             tym_t tym = type->totym();
2924
2925             elem *e1 = eleft;
2926             elem *ex = e1;
2927             if (e1->Eoper == OPind)
2928                 ex = e1->E1;
2929             if (this->e2->op == TOKstructliteral &&
2930                 ex->Eoper == OPvar && ex->EV.sp.Voffset == 0)
2931             {   StructLiteralExp *se = (StructLiteralExp *)this->e2;
2932
2933                 Symbol *symSave = se->sym;
2934                 size_t soffsetSave = se->soffset;
2935                 int fillHolesSave = se->fillHoles;
2936
2937                 se->sym = ex->EV.sp.Vsym;
2938                 se->soffset = 0;
2939                 se->fillHoles = (op == TOKconstruct || op == TOKblit) ? 1 : 0;
2940
2941                 el_free(e1);
2942                 e = this->e2->toElem(irs);
2943
2944                 se->sym = symSave;
2945                 se->soffset = soffsetSave;
2946                 se->fillHoles = fillHolesSave;
2947             }
2948             else
2949             {
2950                 elem *e2 = this->e2->toElem(irs);
2951                 e = el_bin(OPstreq,tym,e1,e2);
2952                 e->ET = this->e1->type->toCtype();
2953                 if (type_size(e->ET) == 0)
2954                     e->Eoper = OPcomma;
2955             }
2956             goto Lret;
2957         }
2958     }
2959     else
2960         e = toElemBin(irs,OPeq);
2961     return e;
2962
2963   Lret:
2964     el_setLoc(e,loc);
2965     return e;
2966 }
2967
2968 /***************************************
2969  */
2970
2971 elem *AddAssignExp::toElem(IRState *irs)
2972 {
2973     //printf("AddAssignExp::toElem() %s\n", toChars());
2974     elem *e = toElemBin(irs,OPaddass);
2975     return e;
2976 }
2977
2978
2979 /***************************************
2980  */
2981
2982 elem *MinAssignExp::toElem(IRState *irs)
2983 {
2984     return toElemBin(irs,OPminass);
2985 }
2986
2987 /***************************************
2988  */
2989
2990 elem *CatAssignExp::toElem(IRState *irs)
2991 {
2992     //printf("CatAssignExp::toElem('%s')\n", toChars());
2993     elem *e;
2994     Type *tb1 = e1->type->toBasetype();
2995     Type *tb2 = e2->type->toBasetype();
2996
2997     if (tb1->ty == Tarray && tb2->ty == Tdchar &&
2998         (tb1->nextOf()->ty == Tchar || tb1->nextOf()->ty == Twchar))
2999     {   // Append dchar to char[] or wchar[]
3000
3001         elem *e1 = this->e1->toElem(irs);
3002         e1 = el_una(OPaddr, TYnptr, e1);
3003
3004         elem *e2 = this->e2->toElem(irs);
3005
3006         elem *ep = el_params(e2, e1, NULL);
3007         int rtl = (tb1->nextOf()->ty == Tchar)
3008                 ? RTLSYM_ARRAYAPPENDCD
3009                 : RTLSYM_ARRAYAPPENDWD;
3010         e = el_bin(OPcall, TYdarray, el_var(rtlsym[rtl]), ep);
3011         el_setLoc(e,loc);
3012     }
3013     else if (tb1->ty == Tarray || tb2->ty == Tsarray)
3014     {
3015         elem *e1 = this->e1->toElem(irs);
3016         elem *e2 = this->e2->toElem(irs);
3017
3018         Type *tb1n = tb1->nextOf()->toBasetype();
3019         if ((tb2->ty == Tarray || tb2->ty == Tsarray) &&
3020             tb1n->equals(tb2->nextOf()->toBasetype()))
3021         {   // Append array
3022             e1 = el_una(OPaddr, TYnptr, e1);
3023             if (tybasic(e2->Ety) == TYstruct || tybasic(e2->Ety) == TYarray)
3024             {
3025                 e2 = el_una(OPstrpar, TYstruct, e2);
3026                 e2->ET = e2->E1->ET;
3027             }
3028             elem *ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
3029             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep);
3030         }
3031         else if (I64)
3032         {   // Append element
3033
3034             // Extend array with _d_arrayappendcTX(TypeInfo ti, e1, 1)
3035             e1 = el_una(OPaddr, TYnptr, e1);
3036             elem *ep = el_param(e1, this->e1->type->getTypeInfo(NULL)->toElem(irs));
3037             ep = el_param(el_long(TYsize_t, 1), ep);
3038             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCTX]), ep);
3039             symbol *stmp = symbol_genauto(tb1->toCtype());
3040             e = el_bin(OPeq, TYdarray, el_var(stmp), e);
3041
3042             // Assign e2 to last element in stmp[]
3043             // *(stmp.ptr + (stmp.length - 1) * szelem) = e2
3044
3045             elem *eptr = array_toPtr(tb1, el_var(stmp));
3046             elem *elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, el_var(stmp));
3047             elength = el_bin(OPmin, TYsize_t, elength, el_long(TYsize_t, 1));
3048             elength = el_bin(OPmul, TYsize_t, elength, el_long(TYsize_t, this->e2->type->size()));
3049             eptr = el_bin(OPadd, TYnptr, eptr, elength);
3050             eptr = el_una(OPind, e2->Ety, eptr);
3051             elem *eeq = el_bin(OPeq, e2->Ety, eptr, e2);
3052
3053             if (tybasic(e2->Ety) == TYstruct)
3054             {
3055                 eeq->Eoper = OPstreq;
3056                 eeq->ET = tb1n->toCtype();
3057             }
3058             else if (tybasic(e2->Ety) == TYarray)
3059             {
3060                 eeq->Eoper = OPstreq;
3061                 eeq->Ejty = eeq->Ety = TYstruct;
3062                 eeq->ET = tb1n->toCtype();
3063             }
3064
3065             e = el_combine(e, eeq);
3066             e = el_combine(e, el_var(stmp));
3067         }
3068         else
3069         {   // Append element
3070             e1 = el_una(OPaddr, TYnptr, e1);
3071             if (tybasic(e2->Ety) == TYstruct || tybasic(e2->Ety) == TYarray)
3072             {
3073                 e2 = el_una(OPstrpar, TYstruct, e2);
3074                 e2->ET = e2->E1->ET;
3075             }
3076             elem *ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
3077             e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep);
3078             e->Eflags |= EFLAGS_variadic;
3079         }
3080
3081         el_setLoc(e,loc);
3082     }
3083     else
3084         assert(0);
3085     return e;
3086 }
3087
3088
3089 /***************************************
3090  */
3091
3092 elem *DivAssignExp::toElem(IRState *irs)
3093 {
3094     return toElemBin(irs,OPdivass);
3095 }
3096
3097
3098 /***************************************
3099  */
3100
3101 elem *ModAssignExp::toElem(IRState *irs)
3102 {
3103     return toElemBin(irs,OPmodass);
3104 }
3105
3106
3107 /***************************************
3108  */
3109
3110 elem *MulAssignExp::toElem(IRState *irs)
3111 {
3112     return toElemBin(irs,OPmulass);
3113 }
3114
3115
3116 /***************************************
3117  */
3118
3119 elem *ShlAssignExp::toElem(IRState *irs)
3120 {
3121     return toElemBin(irs,OPshlass);
3122 }
3123
3124
3125 /***************************************
3126  */
3127
3128 elem *ShrAssignExp::toElem(IRState *irs)
3129 {
3130     //printf("ShrAssignExp::toElem() %s, %s\n", e1->type->toChars(), e1->toChars());
3131     Type *t1 = e1->type;
3132     if (e1->op == TOKcast)
3133     {   /* Use the type before it was integrally promoted to int
3134          */
3135         CastExp *ce = (CastExp *)e1;
3136         t1 = ce->e1->type;
3137     }
3138     return toElemBin(irs, t1->isunsigned() ? OPshrass : OPashrass);
3139 }
3140
3141
3142 /***************************************
3143  */
3144
3145 elem *UshrAssignExp::toElem(IRState *irs)
3146 {
3147     return toElemBin(irs, OPshrass);
3148 }
3149
3150
3151 /***************************************
3152  */
3153
3154 elem *AndAssignExp::toElem(IRState *irs)
3155 {
3156     return toElemBin(irs,OPandass);
3157 }
3158
3159
3160 /***************************************
3161  */
3162
3163 elem *OrAssignExp::toElem(IRState *irs)
3164 {
3165     return toElemBin(irs,OPorass);
3166 }
3167
3168
3169 /***************************************
3170  */
3171
3172 elem *XorAssignExp::toElem(IRState *irs)
3173 {
3174     return toElemBin(irs,OPxorass);
3175 }
3176
3177
3178 /***************************************
3179  */
3180
3181 elem *AndAndExp::toElem(IRState *irs)
3182 {
3183     elem *e = toElemBin(irs,OPandand);
3184     if (global.params.cov && e2->loc.linnum)
3185         e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
3186     return e;
3187 }
3188
3189
3190 /***************************************
3191  */
3192
3193 elem *OrOrExp::toElem(IRState *irs)
3194 {
3195     elem *e = toElemBin(irs,OPoror);
3196     if (global.params.cov && e2->loc.linnum)
3197         e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
3198     return e;
3199 }
3200
3201
3202 /***************************************
3203  */
3204
3205 elem *XorExp::toElem(IRState *irs)
3206 {
3207     return toElemBin(irs,OPxor);
3208 }
3209
3210
3211 /***************************************
3212  */
3213
3214 elem *AndExp::toElem(IRState *irs)
3215 {
3216     return toElemBin(irs,OPand);
3217 }
3218
3219
3220 /***************************************
3221  */
3222
3223 elem *OrExp::toElem(IRState *irs)
3224 {
3225     return toElemBin(irs,OPor);
3226 }
3227
3228
3229 /***************************************
3230  */
3231
3232 elem *ShlExp::toElem(IRState *irs)
3233 {
3234     return toElemBin(irs, OPshl);
3235 }
3236
3237
3238 /***************************************
3239  */
3240
3241 elem *ShrExp::toElem(IRState *irs)
3242 {
3243     return toElemBin(irs, e1->type->isunsigned() ? OPshr : OPashr);
3244 }
3245
3246
3247 /***************************************
3248  */
3249
3250 elem *UshrExp::toElem(IRState *irs)
3251 {
3252     //return toElemBin(irs, OPshr);
3253     elem *eleft  = e1->toElem(irs);
3254     eleft->Ety = touns(eleft->Ety);
3255     elem *eright = e2->toElem(irs);
3256     elem *e = el_bin(OPshr, type->totym(), eleft, eright);
3257     el_setLoc(e, loc);
3258     return e;
3259 }
3260
3261 /****************************************
3262  */
3263
3264 elem *CommaExp::toElem(IRState *irs)
3265 {
3266     assert(e1 && e2);
3267     elem *eleft  = e1->toElem(irs);
3268     elem *eright = e2->toElem(irs);
3269     elem *e = el_combine(eleft, eright);
3270     if (e)
3271         el_setLoc(e, loc);
3272     return e;
3273 }
3274
3275
3276 /***************************************
3277  */
3278
3279 elem *CondExp::toElem(IRState *irs)
3280 {   elem *eleft;
3281     elem *eright;
3282
3283     elem *ec = econd->toElem(irs);
3284
3285     eleft = e1->toElem(irs);
3286     tym_t ty = eleft->Ety;
3287     if (global.params.cov && e1->loc.linnum)
3288         eleft = el_combine(incUsageElem(irs, e1->loc), eleft);
3289
3290     eright = e2->toElem(irs);
3291     if (global.params.cov && e2->loc.linnum)
3292         eright = el_combine(incUsageElem(irs, e2->loc), eright);
3293
3294     elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright));
3295     if (tybasic(ty) == TYstruct)
3296         e->ET = e1->type->toCtype();
3297     el_setLoc(e, loc);
3298     return e;
3299 }
3300
3301
3302 /***************************************
3303  */
3304
3305 elem *TypeExp::toElem(IRState *irs)
3306 {
3307 #ifdef DEBUG
3308     printf("TypeExp::toElem()\n");
3309 #endif
3310     error("type %s is not an expression", toChars());
3311     return el_long(TYint, 0);
3312 }
3313
3314 elem *ScopeExp::toElem(IRState *irs)
3315 {
3316     error("%s is not an expression", sds->toChars());
3317     return el_long(TYint, 0);
3318 }
3319
3320 elem *DotVarExp::toElem(IRState *irs)
3321 {
3322     // *(&e + offset)
3323
3324     //printf("DotVarExp::toElem('%s')\n", toChars());
3325
3326     VarDeclaration *v = var->isVarDeclaration();
3327     if (!v)
3328     {
3329         error("%s is not a field, but a %s", var->toChars(), var->kind());
3330     }
3331
3332     elem *e = e1->toElem(irs);
3333     Type *tb1 = e1->type->toBasetype();
3334     if (tb1->ty != Tclass && tb1->ty != Tpointer)
3335         //e = el_una(OPaddr, TYnptr, e);
3336         e = addressElem(e, tb1);
3337     e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, v ? v->offset : 0));
3338     e = el_una(OPind, type->totym(), e);
3339     if (tybasic(e->Ety) == TYstruct)
3340     {
3341         e->ET = type->toCtype();
3342     }
3343     el_setLoc(e,loc);
3344     return e;
3345 }
3346
3347 elem *DelegateExp::toElem(IRState *irs)
3348 {
3349     elem *e;
3350     elem *ethis;
3351     elem *ep;
3352     Symbol *sfunc;
3353     int directcall = 0;
3354
3355     //printf("DelegateExp::toElem() '%s'\n", toChars());
3356     sfunc = func->toSymbol();
3357     if (func->isNested())
3358     {
3359         ep = el_ptr(sfunc);
3360         ethis = getEthis(loc, irs, func);
3361     }
3362     else
3363     {
3364         ethis = e1->toElem(irs);
3365         if (e1->type->ty != Tclass && e1->type->ty != Tpointer)
3366             ethis = addressElem(ethis, e1->type);
3367
3368         if (e1->op == TOKsuper)
3369             directcall = 1;
3370
3371         if (!func->isThis())
3372             error("delegates are only for non-static functions");
3373
3374         if (!func->isVirtual() ||
3375             directcall ||
3376             func->isFinal())
3377         {
3378             ep = el_ptr(sfunc);
3379         }
3380         else
3381         {
3382             // Get pointer to function out of virtual table
3383             unsigned vindex;
3384
3385             assert(ethis);
3386             ep = el_same(&ethis);
3387             ep = el_una(OPind, TYnptr, ep);
3388             vindex = func->vtblIndex;
3389
3390             if ((int)vindex < 0)
3391                 error("Internal compiler error: malformed delegate. See Bugzilla 4860");
3392
3393             // Build *(ep + vindex * 4)
3394             ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * PTRSIZE));
3395             ep = el_una(OPind,TYnptr,ep);
3396         }
3397
3398 //      if (func->tintro)
3399 //          func->error(loc, "cannot form delegate due to covariant return type");
3400     }
3401     if (ethis->Eoper == OPcomma)
3402     {
3403         ethis->E2 = el_pair(TYdelegate, ethis->E2, ep);
3404         ethis->Ety = TYdelegate;
3405         e = ethis;
3406     }
3407     else
3408         e = el_pair(TYdelegate, ethis, ep);
3409     el_setLoc(e,loc);
3410     return e;
3411 }
3412
3413 elem *DotTypeExp::toElem(IRState *irs)
3414 {
3415     // Just a pass-thru to e1
3416     elem *e;
3417
3418     //printf("DotTypeExp::toElem() %s\n", toChars());
3419     e = e1->toElem(irs);
3420     el_setLoc(e,loc);
3421     return e;
3422 }
3423
3424 elem *CallExp::toElem(IRState *irs)
3425 {
3426     //printf("CallExp::toElem('%s')\n", toChars());
3427     assert(e1->type);
3428     elem *ec;
3429     int directcall;
3430     FuncDeclaration *fd;
3431     Type *t1 = e1->type->toBasetype();
3432     Type *ectype = t1;
3433     elem *eeq = NULL;
3434
3435     elem *ehidden = irs->ehidden;
3436     irs->ehidden = NULL;
3437
3438     directcall = 0;
3439     fd = NULL;
3440     if (e1->op == TOKdotvar && t1->ty != Tdelegate)
3441     {   DotVarExp *dve = (DotVarExp *)e1;
3442
3443         fd = dve->var->isFuncDeclaration();
3444         Expression *ex = dve->e1;
3445         while (1)
3446         {
3447             switch (ex->op)
3448             {
3449                 case TOKsuper:          // super.member() calls directly
3450                 case TOKdottype:        // type.member() calls directly
3451                     directcall = 1;
3452                     break;
3453
3454                 case TOKcast:
3455                     ex = ((CastExp *)ex)->e1;
3456                     continue;
3457
3458                 default:
3459                     //ex->dump(0);
3460                     break;
3461             }
3462             break;
3463         }
3464         ec = dve->e1->toElem(irs);
3465         ectype = dve->e1->type->toBasetype();
3466     }
3467     else if (e1->op == TOKvar)
3468     {
3469         fd = ((VarExp *)e1)->var->isFuncDeclaration();
3470
3471         if (fd && fd->ident == Id::alloca &&
3472             !fd->fbody && fd->linkage == LINKc &&
3473             arguments && arguments->dim == 1)
3474         {   Expression *arg = (Expression *)arguments->data[0];
3475             arg = arg->optimize(WANTvalue);
3476             if (arg->isConst() && arg->type->isintegral())
3477             {   dinteger_t sz = arg->toInteger();
3478                 if (sz > 0 && sz < 0x40000)
3479                 {
3480                     // It's an alloca(sz) of a fixed amount.
3481                     // Replace with an array allocated on the stack
3482                     // of the same size: char[sz] tmp;
3483
3484                     Symbol *stmp;
3485                     ::type *t;
3486
3487                     assert(!ehidden);
3488                     t = type_allocn(TYarray, tschar);
3489                     t->Tdim = sz;
3490                     stmp = symbol_genauto(t);
3491                     ec = el_ptr(stmp);
3492                     el_setLoc(ec,loc);
3493                     return ec;
3494                 }
3495             }
3496         }
3497
3498         ec = e1->toElem(irs);
3499     }
3500     else
3501     {
3502         ec = e1->toElem(irs);
3503         if (arguments && arguments->dim)
3504         {
3505             /* The idea is to enforce expressions being evaluated left to right,
3506              * even though call trees are evaluated parameters first.
3507              * We just do a quick hack to catch the more obvious cases, though
3508              * we need to solve this generally.
3509              */
3510             if (ec->Eoper == OPind && el_sideeffect(ec->E1))
3511             {   /* Rewrite (*exp)(arguments) as:
3512                  * tmp=exp, (*tmp)(arguments)
3513                  */
3514                 elem *ec1 = ec->E1;
3515                 Symbol *stmp = symbol_genauto(type_fake(ec1->Ety));
3516                 eeq = el_bin(OPeq, ec->Ety, el_var(stmp), ec1);
3517                 ec->E1 = el_var(stmp);
3518             }
3519             else if (tybasic(ec->Ety) == TYdelegate && el_sideeffect(ec))
3520             {   /* Rewrite (exp)(arguments) as:
3521                  * tmp=exp, (tmp)(arguments)
3522                  */
3523                 Symbol *stmp = symbol_genauto(type_fake(ec->Ety));
3524                 eeq = el_bin(OPeq, ec->Ety, el_var(stmp), ec);
3525                 ec = el_var(stmp);
3526             }
3527         }
3528     }
3529     ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
3530     el_setLoc(ec,loc);
3531     if (eeq)
3532         ec = el_combine(eeq, ec);
3533     return ec;
3534 }
3535
3536 elem *AddrExp::toElem(IRState *irs)
3537 {   elem *e;
3538     elem **pe;
3539
3540     //printf("AddrExp::toElem('%s')\n", toChars());
3541
3542     e = e1->toElem(irs);
3543     e = addressElem(e, e1->type);
3544 L2:
3545     e->Ety = type->totym();
3546     el_setLoc(e,loc);
3547     return e;
3548 }
3549
3550 elem *PtrExp::toElem(IRState *irs)
3551 {   elem *e;
3552
3553     //printf("PtrExp::toElem() %s\n", toChars());
3554     e = e1->toElem(irs);
3555     e = el_una(OPind,type->totym(),e);
3556     if (tybasic(e->Ety) == TYstruct)
3557     {
3558         e->ET = type->toCtype();
3559     }
3560     el_setLoc(e,loc);
3561     return e;
3562 }
3563
3564 elem *BoolExp::toElem(IRState *irs)
3565 {   elem *e1;
3566
3567     e1 = this->e1->toElem(irs);
3568     return el_una(OPbool,type->totym(),e1);
3569 }
3570
3571 elem *DeleteExp::toElem(IRState *irs)
3572 {   elem *e;
3573     int rtl;
3574     Type *tb;
3575
3576     //printf("DeleteExp::toElem()\n");
3577     if (e1->op == TOKindex)
3578     {
3579         IndexExp *ae = (IndexExp *)(e1);
3580         tb = ae->e1->type->toBasetype();
3581         if (tb->ty == Taarray)
3582         {
3583             TypeAArray *taa = (TypeAArray *)tb;
3584             elem *ea = ae->e1->toElem(irs);
3585             elem *ekey = ae->e2->toElem(irs);
3586             elem *ep;
3587             elem *keyti;
3588
3589             if (tybasic(ekey->Ety) == TYstruct || tybasic(ekey->Ety) == TYarray)
3590             {
3591                 ekey = el_una(OPstrpar, TYstruct, ekey);
3592                 ekey->ET = ekey->E1->ET;
3593             }
3594
3595             Symbol *s = taa->aaGetSymbol("Del", 0);
3596             keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
3597             ep = el_params(ekey, keyti, ea, NULL);
3598             e = el_bin(OPcall, TYnptr, el_var(s), ep);
3599             goto Lret;
3600         }
3601     }
3602     //e1->type->print();
3603     e = e1->toElem(irs);
3604     tb = e1->type->toBasetype();
3605     switch (tb->ty)
3606     {
3607         case Tarray:
3608         {   e = addressElem(e, e1->type);
3609             rtl = RTLSYM_DELARRAYT;
3610
3611             /* See if we need to run destructors on the array contents
3612              */
3613             elem *et = NULL;
3614             Type *tv = tb->nextOf()->toBasetype();
3615             while (tv->ty == Tsarray)
3616             {   TypeSArray *ta = (TypeSArray *)tv;
3617                 tv = tv->nextOf()->toBasetype();
3618             }
3619             if (tv->ty == Tstruct)
3620             {   TypeStruct *ts = (TypeStruct *)tv;
3621                 StructDeclaration *sd = ts->sym;
3622                 if (sd->dtor)
3623                     et = tb->nextOf()->getTypeInfo(NULL)->toElem(irs);
3624             }
3625             if (!et)                            // if no destructors needed
3626                 et = el_long(TYnptr, 0);        // pass null for TypeInfo
3627             e = el_params(et, e, NULL);
3628             // call _d_delarray_t(e, et);
3629             e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
3630             goto Lret;
3631         }
3632         case Tclass:
3633             if (e1->op == TOKvar)
3634             {   VarExp *ve = (VarExp *)e1;
3635                 if (ve->var->isVarDeclaration() &&
3636                     ve->var->isVarDeclaration()->onstack)
3637                 {
3638                     rtl = RTLSYM_CALLFINALIZER;
3639                     if (tb->isClassHandle()->isInterfaceDeclaration())
3640                         rtl = RTLSYM_CALLINTERFACEFINALIZER;
3641                     break;
3642                 }
3643             }
3644             e = addressElem(e, e1->type);
3645             rtl = RTLSYM_DELCLASS;
3646             if (tb->isClassHandle()->isInterfaceDeclaration())
3647                 rtl = RTLSYM_DELINTERFACE;
3648             break;
3649
3650         case Tpointer:
3651             e = addressElem(e, e1->type);
3652             rtl = RTLSYM_DELMEMORY;
3653             break;
3654
3655         default:
3656             assert(0);
3657             break;
3658     }
3659     e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
3660
3661   Lret:
3662     el_setLoc(e,loc);
3663     return e;
3664 }
3665
3666 elem *CastExp::toElem(IRState *irs)
3667 {
3668     TY fty;
3669     TY tty;
3670     tym_t ftym;
3671     tym_t ttym;
3672     enum OPER eop;
3673
3674 #if 0
3675     printf("CastExp::toElem()\n");
3676     print();
3677     printf("\tfrom: %s\n", e1->type->toChars());
3678     printf("\tto  : %s\n", to->toChars());
3679 #endif
3680
3681     elem *e = e1->toElem(irs);
3682     Type *tfrom = e1->type->toBasetype();
3683     Type *t = to->toBasetype();         // skip over typedef's
3684
3685 #if DMDV2
3686     if (tfrom->ty == Taarray)
3687         tfrom = ((TypeAArray*)tfrom)->getImpl()->type;
3688     if (t->ty == Taarray)
3689         t = ((TypeAArray*)t)->getImpl()->type;
3690 #endif
3691
3692     if (t->equals(tfrom))
3693         goto Lret;
3694
3695     fty = tfrom->ty;
3696     //printf("fty = %d\n", fty);
3697     tty = t->ty;
3698
3699     if (tty == Tpointer && fty == Tarray
3700 #if 0
3701         && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3702 #endif
3703        )
3704     {
3705         if (e->Eoper == OPvar)
3706         {
3707             // e1 -> *(&e1 + 4)
3708             e = el_una(OPaddr, TYnptr, e);
3709             e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, tysize[TYnptr]));
3710             e = el_una(OPind,t->totym(),e);
3711         }
3712         else
3713         {
3714             // e1 -> (unsigned)(e1 >> 32)
3715             if (I64)
3716             {
3717                 e = el_bin(OPshr, TYucent, e, el_long(TYint, 64));
3718                 e = el_una(OP128_64, t->totym(), e);
3719             }
3720             else
3721             {
3722                 e = el_bin(OPshr, TYullong, e, el_long(TYint, 32));
3723                 e = el_una(OP64_32, t->totym(), e);
3724             }
3725         }
3726         goto Lret;
3727     }
3728
3729     if (tty == Tpointer && fty == Tsarray
3730 #if 0
3731         && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3732 #endif
3733         )
3734     {
3735         // e1 -> &e1
3736         e = el_una(OPaddr, TYnptr, e);
3737         goto Lret;
3738     }
3739
3740     // Convert from static array to dynamic array
3741     if (tty == Tarray && fty == Tsarray)
3742     {
3743         e = sarray_toDarray(loc, tfrom, t, e);
3744         goto Lret;
3745     }
3746
3747     // Convert from dynamic array to dynamic array
3748     if (tty == Tarray && fty == Tarray)
3749     {
3750         unsigned fsize = tfrom->nextOf()->size();
3751         unsigned tsize = t->nextOf()->size();
3752
3753         if (fsize != tsize)
3754         {   // Array element sizes do not match, so we must adjust the dimensions
3755             elem *ep = el_params(e, el_long(TYsize_t, fsize), el_long(TYsize_t, tsize), NULL);
3756             e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep);
3757         }
3758         goto Lret;
3759     }
3760
3761     // Casting from base class to derived class requires a runtime check
3762     if (fty == Tclass && tty == Tclass)
3763     {
3764         // Casting from derived class to base class is a no-op
3765         int offset;
3766         int rtl = RTLSYM_DYNAMIC_CAST;
3767
3768         ClassDeclaration *cdfrom = tfrom->isClassHandle();
3769         ClassDeclaration *cdto   = t->isClassHandle();
3770         if (cdfrom->isInterfaceDeclaration())
3771         {
3772             rtl = RTLSYM_INTERFACE_CAST;
3773             if (cdfrom->isCPPinterface())
3774             {
3775                 if (cdto->isCPPinterface())
3776                 {
3777                     /* Casting from a C++ interface to a C++ interface
3778                      * is always a 'paint' operation
3779                      */
3780                     goto Lret;                  // no-op
3781                 }
3782
3783                 /* Casting from a C++ interface to a class
3784                  * always results in null because there is no runtime
3785                  * information available to do it.
3786                  *
3787                  * Casting from a C++ interface to a non-C++ interface
3788                  * always results in null because there's no way one
3789                  * can be derived from the other.
3790                  */
3791                 e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0));
3792                 goto Lret;
3793             }
3794         }
3795         if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME)
3796         {
3797             /* The offset from cdfrom=>cdto is known at compile time.
3798              */
3799
3800             //printf("offset = %d\n", offset);
3801             if (offset)
3802             {   /* Rewrite cast as (e ? e + offset : null)
3803                  */
3804                 if (e1->op == TOKthis)
3805                 {   // Assume 'this' is never null, so skip null check
3806                     e = el_bin(OPadd, TYnptr, e, el_long(TYsize_t, offset));
3807                 }
3808                 else
3809                 {
3810                     elem *etmp = el_same(&e);
3811                     elem *ex = el_bin(OPadd, TYnptr, etmp, el_long(TYsize_t, offset));
3812                     ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0));
3813                     e = el_bin(OPcond, TYnptr, e, ex);
3814                 }
3815             }
3816             goto Lret;                  // no-op
3817         }
3818
3819         /* The offset from cdfrom=>cdto can only be determined at runtime.
3820          */
3821         elem *ep = el_param(el_ptr(cdto->toSymbol()), e);
3822         e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep);
3823         goto Lret;
3824     }
3825
3826     ftym = tybasic(e->Ety);
3827     ttym = tybasic(t->totym());
3828     if (ftym == ttym)
3829         goto Lret;
3830
3831     /* Reduce combinatorial explosion by rewriting the 'to' and 'from' types to a
3832      * generic equivalent (as far as casting goes)
3833      */
3834     switch (tty)
3835     {
3836         case Tpointer:
3837             if (fty == Tdelegate)
3838                 goto Lpaint;
3839             tty = I64 ? Tuns64 : Tuns32;
3840             break;
3841
3842         case Tchar:     tty = Tuns8;    break;
3843         case Twchar:    tty = Tuns16;   break;
3844         case Tdchar:    tty = Tuns32;   break;
3845         case Tvoid:     goto Lpaint;
3846
3847         case Tbool:
3848         {
3849             // Construct e?true:false
3850             e = el_una(OPbool, ttym, e);
3851             goto Lret;
3852         }
3853     }
3854
3855     switch (fty)
3856     {
3857         case Tpointer:  fty = I64 ? Tuns64 : Tuns32;  break;
3858         case Tchar:     fty = Tuns8;    break;
3859         case Twchar:    fty = Tuns16;   break;
3860         case Tdchar:    fty = Tuns32;   break;
3861     }
3862
3863     #define X(fty, tty) ((fty) * TMAX + (tty))
3864 Lagain:
3865     switch (X(fty,tty))
3866     {
3867         /* ============================= */
3868
3869         case X(Tbool,Tint8):
3870         case X(Tbool,Tuns8):
3871                                 goto Lpaint;
3872         case X(Tbool,Tint16):
3873         case X(Tbool,Tuns16):
3874         case X(Tbool,Tint32):
3875         case X(Tbool,Tuns32):   eop = OPu8_16;  goto Leop;
3876         case X(Tbool,Tint64):
3877         case X(Tbool,Tuns64):
3878         case X(Tbool,Tfloat32):
3879         case X(Tbool,Tfloat64):
3880         case X(Tbool,Tfloat80):
3881         case X(Tbool,Tcomplex32):
3882         case X(Tbool,Tcomplex64):
3883         case X(Tbool,Tcomplex80):
3884                                 e = el_una(OPu8_16, TYuint, e);
3885                                 fty = Tuns32;
3886                                 goto Lagain;
3887         case X(Tbool,Timaginary32):
3888         case X(Tbool,Timaginary64):
3889         case X(Tbool,Timaginary80): goto Lzero;
3890
3891         /* ============================= */
3892
3893         case X(Tint8,Tuns8):    goto Lpaint;
3894         case X(Tint8,Tint16):
3895         case X(Tint8,Tuns16):
3896         case X(Tint8,Tint32):
3897         case X(Tint8,Tuns32):   eop = OPs8_16;  goto Leop;
3898         case X(Tint8,Tint64):
3899         case X(Tint8,Tuns64):
3900         case X(Tint8,Tfloat32):
3901         case X(Tint8,Tfloat64):
3902         case X(Tint8,Tfloat80):
3903         case X(Tint8,Tcomplex32):
3904         case X(Tint8,Tcomplex64):
3905         case X(Tint8,Tcomplex80):
3906                                 e = el_una(OPs8_16, TYint, e);
3907                                 fty = Tint32;
3908                                 goto Lagain;
3909         case X(Tint8,Timaginary32):
3910         case X(Tint8,Timaginary64):
3911         case X(Tint8,Timaginary80): goto Lzero;
3912
3913         /* ============================= */
3914
3915         case X(Tuns8,Tint8):    goto Lpaint;
3916         case X(Tuns8,Tint16):
3917         case X(Tuns8,Tuns16):
3918         case X(Tuns8,Tint32):
3919         case X(Tuns8,Tuns32):   eop = OPu8_16;  goto Leop;
3920         case X(Tuns8,Tint64):
3921         case X(Tuns8,Tuns64):
3922         case X(Tuns8,Tfloat32):
3923         case X(Tuns8,Tfloat64):
3924         case X(Tuns8,Tfloat80):
3925         case X(Tuns8,Tcomplex32):
3926         case X(Tuns8,Tcomplex64):
3927         case X(Tuns8,Tcomplex80):
3928                                 e = el_una(OPu8_16, TYuint, e);
3929                                 fty = Tuns32;
3930                                 goto Lagain;
3931         case X(Tuns8,Timaginary32):
3932         case X(Tuns8,Timaginary64):
3933         case X(Tuns8,Timaginary80): goto Lzero;
3934
3935         /* ============================= */
3936
3937         case X(Tint16,Tint8):
3938         case X(Tint16,Tuns8):   eop = OP16_8;   goto Leop;
3939         case X(Tint16,Tuns16):  goto Lpaint;
3940         case X(Tint16,Tint32):
3941         case X(Tint16,Tuns32):  eop = OPs16_32; goto Leop;
3942         case X(Tint16,Tint64):
3943         case X(Tint16,Tuns64):  e = el_una(OPs16_32, TYint, e);
3944                                 fty = Tint32;
3945                                 goto Lagain;
3946         case X(Tint16,Tfloat32):
3947         case X(Tint16,Tfloat64):
3948         case X(Tint16,Tfloat80):
3949         case X(Tint16,Tcomplex32):
3950         case X(Tint16,Tcomplex64):
3951         case X(Tint16,Tcomplex80):
3952                                 e = el_una(OPs16_d, TYdouble, e);
3953                                 fty = Tfloat64;
3954                                 goto Lagain;
3955         case X(Tint16,Timaginary32):
3956         case X(Tint16,Timaginary64):
3957         case X(Tint16,Timaginary80): goto Lzero;
3958
3959         /* ============================= */
3960
3961         case X(Tuns16,Tint8):
3962         case X(Tuns16,Tuns8):   eop = OP16_8;   goto Leop;
3963         case X(Tuns16,Tint16):  goto Lpaint;
3964         case X(Tuns16,Tint32):
3965         case X(Tuns16,Tuns32):  eop = OPu16_32; goto Leop;
3966         case X(Tuns16,Tint64):
3967         case X(Tuns16,Tuns64):
3968         case X(Tuns16,Tfloat64):
3969         case X(Tuns16,Tfloat32):
3970         case X(Tuns16,Tfloat80):
3971         case X(Tuns16,Tcomplex32):
3972         case X(Tuns16,Tcomplex64):
3973         case X(Tuns16,Tcomplex80):
3974                                 e = el_una(OPu16_32, TYuint, e);
3975                                 fty = Tuns32;
3976                                 goto Lagain;
3977         case X(Tuns16,Timaginary32):
3978         case X(Tuns16,Timaginary64):
3979         case X(Tuns16,Timaginary80): goto Lzero;
3980
3981         /* ============================= */
3982
3983         case X(Tint32,Tint8):
3984         case X(Tint32,Tuns8):   e = el_una(OP32_16, TYshort, e);
3985                                 fty = Tint16;
3986                                 goto Lagain;
3987         case X(Tint32,Tint16):
3988         case X(Tint32,Tuns16):  eop = OP32_16;  goto Leop;
3989         case X(Tint32,Tuns32):  goto Lpaint;
3990         case X(Tint32,Tint64):
3991         case X(Tint32,Tuns64):  eop = OPs32_64; goto Leop;
3992         case X(Tint32,Tfloat32):
3993         case X(Tint32,Tfloat64):
3994         case X(Tint32,Tfloat80):
3995         case X(Tint32,Tcomplex32):
3996         case X(Tint32,Tcomplex64):
3997         case X(Tint32,Tcomplex80):
3998                                 e = el_una(OPs32_d, TYdouble, e);
3999                                 fty = Tfloat64;
4000                                 goto Lagain;
4001         case X(Tint32,Timaginary32):
4002         case X(Tint32,Timaginary64):
4003         case X(Tint32,Timaginary80): goto Lzero;
4004
4005         /* ============================= */
4006
4007         case X(Tuns32,Tint8):
4008         case X(Tuns32,Tuns8):   e = el_una(OP32_16, TYshort, e);
4009                                 fty = Tuns16;
4010                                 goto Lagain;
4011         case X(Tuns32,Tint16):
4012         case X(Tuns32,Tuns16):  eop = OP32_16;  goto Leop;
4013         case X(Tuns32,Tint32):  goto Lpaint;
4014         case X(Tuns32,Tint64):
4015         case X(Tuns32,Tuns64):  eop = OPu32_64; goto Leop;
4016         case X(Tuns32,Tfloat32):
4017         case X(Tuns32,Tfloat64):
4018         case X(Tuns32,Tfloat80):
4019         case X(Tuns32,Tcomplex32):
4020         case X(Tuns32,Tcomplex64):
4021         case X(Tuns32,Tcomplex80):
4022                                 e = el_una(OPu32_d, TYdouble, e);
4023                                 fty = Tfloat64;
4024                                 goto Lagain;
4025         case X(Tuns32,Timaginary32):
4026         case X(Tuns32,Timaginary64):
4027         case X(Tuns32,Timaginary80): goto Lzero;
4028
4029         /* ============================= */
4030
4031         case X(Tint64,Tint8):
4032         case X(Tint64,Tuns8):
4033         case X(Tint64,Tint16):
4034         case X(Tint64,Tuns16):  e = el_una(OP64_32, TYint, e);
4035                                 fty = Tint32;
4036                                 goto Lagain;
4037         case X(Tint64,Tint32):
4038         case X(Tint64,Tuns32):  eop = OP64_32; goto Leop;
4039         case X(Tint64,Tuns64):  goto Lpaint;
4040         case X(Tint64,Tfloat32):
4041         case X(Tint64,Tfloat64):
4042         case X(Tint64,Tfloat80):
4043         case X(Tint64,Tcomplex32):
4044         case X(Tint64,Tcomplex64):
4045         case X(Tint64,Tcomplex80):
4046                                 e = el_una(OPs64_d, TYdouble, e);
4047                                 fty = Tfloat64;
4048                                 goto Lagain;
4049         case X(Tint64,Timaginary32):
4050         case X(Tint64,Timaginary64):
4051         case X(Tint64,Timaginary80): goto Lzero;
4052
4053         /* ============================= */
4054
4055         case X(Tuns64,Tint8):
4056         case X(Tuns64,Tuns8):
4057         case X(Tuns64,Tint16):
4058         case X(Tuns64,Tuns16):  e = el_una(OP64_32, TYint, e);
4059                                 fty = Tint32;
4060                                 goto Lagain;
4061         case X(Tuns64,Tint32):
4062         case X(Tuns64,Tuns32):  eop = OP64_32;  goto Leop;
4063         case X(Tuns64,Tint64):  goto Lpaint;
4064         case X(Tuns64,Tfloat32):
4065         case X(Tuns64,Tfloat64):
4066         case X(Tuns64,Tfloat80):
4067         case X(Tuns64,Tcomplex32):
4068         case X(Tuns64,Tcomplex64):
4069         case X(Tuns64,Tcomplex80):
4070                                  e = el_una(OPu64_d, TYdouble, e);
4071                                  fty = Tfloat64;
4072                                  goto Lagain;
4073         case X(Tuns64,Timaginary32):
4074         case X(Tuns64,Timaginary64):
4075         case X(Tuns64,Timaginary80): goto Lzero;
4076
4077         /* ============================= */
4078
4079         case X(Tfloat32,Tint8):
4080         case X(Tfloat32,Tuns8):
4081         case X(Tfloat32,Tint16):
4082         case X(Tfloat32,Tuns16):
4083         case X(Tfloat32,Tint32):
4084         case X(Tfloat32,Tuns32):
4085         case X(Tfloat32,Tint64):
4086         case X(Tfloat32,Tuns64):
4087         case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e);
4088                                    fty = Tfloat64;
4089                                    goto Lagain;
4090         case X(Tfloat32,Tfloat64): eop = OPf_d; goto Leop;
4091         case X(Tfloat32,Timaginary32): goto Lzero;
4092         case X(Tfloat32,Timaginary64): goto Lzero;
4093         case X(Tfloat32,Timaginary80): goto Lzero;
4094         case X(Tfloat32,Tcomplex32):
4095         case X(Tfloat32,Tcomplex64):
4096         case X(Tfloat32,Tcomplex80):
4097             e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e);
4098             fty = Tcomplex32;
4099             goto Lagain;
4100
4101         /* ============================= */
4102
4103         case X(Tfloat64,Tint8):
4104         case X(Tfloat64,Tuns8):    e = el_una(OPd_s16, TYshort, e);
4105                                    fty = Tint16;
4106                                    goto Lagain;
4107         case X(Tfloat64,Tint16):   eop = OPd_s16; goto Leop;
4108         case X(Tfloat64,Tuns16):   eop = OPd_u16; goto Leop;
4109         case X(Tfloat64,Tint32):   eop = OPd_s32; goto Leop;
4110         case X(Tfloat64,Tuns32):   eop = OPd_u32; goto Leop;
4111         case X(Tfloat64,Tint64):   eop = OPd_s64; goto Leop;
4112         case X(Tfloat64,Tuns64):   eop = OPd_u64; goto Leop;
4113         case X(Tfloat64,Tfloat32): eop = OPd_f;   goto Leop;
4114         case X(Tfloat64,Tfloat80): eop = OPd_ld;  goto Leop;
4115         case X(Tfloat64,Timaginary32):  goto Lzero;
4116         case X(Tfloat64,Timaginary64):  goto Lzero;
4117         case X(Tfloat64,Timaginary80):  goto Lzero;
4118         case X(Tfloat64,Tcomplex32):
4119         case X(Tfloat64,Tcomplex64):
4120         case X(Tfloat64,Tcomplex80):
4121             e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e);
4122             fty = Tcomplex64;
4123             goto Lagain;
4124
4125         /* ============================= */
4126
4127         case X(Tfloat80,Tint8):
4128         case X(Tfloat80,Tuns8):
4129         case X(Tfloat80,Tint16):
4130         case X(Tfloat80,Tuns16):
4131         case X(Tfloat80,Tint32):
4132         case X(Tfloat80,Tuns32):
4133         case X(Tfloat80,Tint64):
4134         case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e);
4135                                    fty = Tfloat64;
4136                                    goto Lagain;
4137         case X(Tfloat80,Tuns64):
4138                                    eop = OPld_u64; goto Leop;
4139         case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop;
4140         case X(Tfloat80,Timaginary32): goto Lzero;
4141         case X(Tfloat80,Timaginary64): goto Lzero;
4142         case X(Tfloat80,Timaginary80): goto Lzero;
4143         case X(Tfloat80,Tcomplex32):
4144         case X(Tfloat80,Tcomplex64):
4145         case X(Tfloat80,Tcomplex80):
4146             e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0));
4147             fty = Tcomplex80;
4148             goto Lagain;
4149
4150         /* ============================= */
4151
4152         case X(Timaginary32,Tint8):
4153         case X(Timaginary32,Tuns8):
4154         case X(Timaginary32,Tint16):
4155         case X(Timaginary32,Tuns16):
4156         case X(Timaginary32,Tint32):
4157         case X(Timaginary32,Tuns32):
4158         case X(Timaginary32,Tint64):
4159         case X(Timaginary32,Tuns64):
4160         case X(Timaginary32,Tfloat32):
4161         case X(Timaginary32,Tfloat64):
4162         case X(Timaginary32,Tfloat80):  goto Lzero;
4163         case X(Timaginary32,Timaginary64): eop = OPf_d; goto Leop;
4164         case X(Timaginary32,Timaginary80):
4165                                    e = el_una(OPf_d, TYidouble, e);
4166                                    fty = Timaginary64;
4167                                    goto Lagain;
4168         case X(Timaginary32,Tcomplex32):
4169         case X(Timaginary32,Tcomplex64):
4170         case X(Timaginary32,Tcomplex80):
4171             e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e);
4172             fty = Tcomplex32;
4173             goto Lagain;
4174
4175         /* ============================= */
4176
4177         case X(Timaginary64,Tint8):
4178         case X(Timaginary64,Tuns8):
4179         case X(Timaginary64,Tint16):
4180         case X(Timaginary64,Tuns16):
4181         case X(Timaginary64,Tint32):
4182         case X(Timaginary64,Tuns32):
4183         case X(Timaginary64,Tint64):
4184         case X(Timaginary64,Tuns64):
4185         case X(Timaginary64,Tfloat32):
4186         case X(Timaginary64,Tfloat64):
4187         case X(Timaginary64,Tfloat80):  goto Lzero;
4188         case X(Timaginary64,Timaginary32): eop = OPd_f;   goto Leop;
4189         case X(Timaginary64,Timaginary80): eop = OPd_ld;  goto Leop;
4190         case X(Timaginary64,Tcomplex32):
4191         case X(Timaginary64,Tcomplex64):
4192         case X(Timaginary64,Tcomplex80):
4193             e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e);
4194             fty = Tcomplex64;
4195             goto Lagain;
4196
4197         /* ============================= */
4198
4199         case X(Timaginary80,Tint8):
4200         case X(Timaginary80,Tuns8):
4201         case X(Timaginary80,Tint16):
4202         case X(Timaginary80,Tuns16):
4203         case X(Timaginary80,Tint32):
4204         case X(Timaginary80,Tuns32):
4205         case X(Timaginary80,Tint64):
4206         case X(Timaginary80,Tuns64):
4207         case X(Timaginary80,Tfloat32):
4208         case X(Timaginary80,Tfloat64):
4209         case X(Timaginary80,Tfloat80):  goto Lzero;
4210         case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e);
4211                                    fty = Timaginary64;
4212                                    goto Lagain;
4213         case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop;
4214         case X(Timaginary80,Tcomplex32):
4215         case X(Timaginary80,Tcomplex64):
4216         case X(Timaginary80,Tcomplex80):
4217             e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e);
4218             fty = Tcomplex80;
4219             goto Lagain;
4220
4221         /* ============================= */
4222
4223         case X(Tcomplex32,Tint8):
4224         case X(Tcomplex32,Tuns8):
4225         case X(Tcomplex32,Tint16):
4226         case X(Tcomplex32,Tuns16):
4227         case X(Tcomplex32,Tint32):
4228         case X(Tcomplex32,Tuns32):
4229         case X(Tcomplex32,Tint64):
4230         case X(Tcomplex32,Tuns64):
4231         case X(Tcomplex32,Tfloat32):
4232         case X(Tcomplex32,Tfloat64):
4233         case X(Tcomplex32,Tfloat80):
4234                 e = el_una(OPc_r, TYfloat, e);
4235                 fty = Tfloat32;
4236                 goto Lagain;
4237         case X(Tcomplex32,Timaginary32):
4238         case X(Tcomplex32,Timaginary64):
4239         case X(Tcomplex32,Timaginary80):
4240                 e = el_una(OPc_i, TYifloat, e);
4241                 fty = Timaginary32;
4242                 goto Lagain;
4243         case X(Tcomplex32,Tcomplex64):
4244         case X(Tcomplex32,Tcomplex80):
4245                 e = el_una(OPf_d, TYcdouble, e);
4246                 fty = Tcomplex64;
4247                 goto Lagain;
4248
4249         /* ============================= */
4250
4251         case X(Tcomplex64,Tint8):
4252         case X(Tcomplex64,Tuns8):
4253         case X(Tcomplex64,Tint16):
4254         case X(Tcomplex64,Tuns16):
4255         case X(Tcomplex64,Tint32):
4256         case X(Tcomplex64,Tuns32):
4257         case X(Tcomplex64,Tint64):
4258         case X(Tcomplex64,Tuns64):
4259         case X(Tcomplex64,Tfloat32):
4260         case X(Tcomplex64,Tfloat64):
4261         case X(Tcomplex64,Tfloat80):
4262                 e = el_una(OPc_r, TYdouble, e);
4263                 fty = Tfloat64;
4264                 goto Lagain;
4265         case X(Tcomplex64,Timaginary32):
4266         case X(Tcomplex64,Timaginary64):
4267         case X(Tcomplex64,Timaginary80):
4268                 e = el_una(OPc_i, TYidouble, e);
4269                 fty = Timaginary64;
4270                 goto Lagain;
4271         case X(Tcomplex64,Tcomplex32):   eop = OPd_f;   goto Leop;
4272         case X(Tcomplex64,Tcomplex80):   eop = OPd_ld;  goto Leop;
4273
4274         /* ============================= */
4275
4276         case X(Tcomplex80,Tint8):
4277         case X(Tcomplex80,Tuns8):
4278         case X(Tcomplex80,Tint16):
4279         case X(Tcomplex80,Tuns16):
4280         case X(Tcomplex80,Tint32):
4281         case X(Tcomplex80,Tuns32):
4282         case X(Tcomplex80,Tint64):
4283         case X(Tcomplex80,Tuns64):
4284         case X(Tcomplex80,Tfloat32):
4285         case X(Tcomplex80,Tfloat64):
4286         case X(Tcomplex80,Tfloat80):
4287                 e = el_una(OPc_r, TYldouble, e);
4288                 fty = Tfloat80;
4289                 goto Lagain;
4290         case X(Tcomplex80,Timaginary32):
4291         case X(Tcomplex80,Timaginary64):
4292         case X(Tcomplex80,Timaginary80):
4293                 e = el_una(OPc_i, TYildouble, e);
4294                 fty = Timaginary80;
4295                 goto Lagain;
4296         case X(Tcomplex80,Tcomplex32):
4297         case X(Tcomplex80,Tcomplex64):
4298                 e = el_una(OPld_d, TYcdouble, e);
4299                 fty = Tcomplex64;
4300                 goto Lagain;
4301
4302         /* ============================= */
4303
4304         default:
4305             if (fty == tty)
4306                 goto Lpaint;
4307             //dump(0);
4308             //printf("fty = %d, tty = %d, %d\n", fty, tty, t->ty);
4309             error("e2ir: cannot cast %s of type %s to type %s", e1->toChars(), e1->type->toChars(), t->toChars());
4310             goto Lzero;
4311
4312         Lzero:
4313             e = el_long(ttym, 0);
4314             break;
4315
4316         Lpaint:
4317             e->Ety = ttym;
4318             break;
4319
4320         Leop:
4321             e = el_una(eop, ttym, e);
4322             break;
4323     }
4324 Lret:
4325     // Adjust for any type paints
4326     t = type->toBasetype();
4327     e->Ety = t->totym();
4328
4329     el_setLoc(e,loc);
4330     return e;
4331 }
4332
4333 elem *ArrayLengthExp::toElem(IRState *irs)
4334 {
4335     elem *e = e1->toElem(irs);
4336     e = el_una(I64 ? OP128_64 : OP64_32, type->totym(), e);
4337     el_setLoc(e,loc);
4338     return e;
4339 }
4340
4341 elem *SliceExp::toElem(IRState *irs)
4342 {
4343     //printf("SliceExp::toElem()\n");
4344     Type *t1 = e1->type->toBasetype();
4345     elem *e = e1->toElem(irs);
4346     if (lwr)
4347     {
4348         elem *einit = resolveLengthVar(lengthVar, &e, t1);
4349
4350         int sz = t1->nextOf()->size();
4351
4352         elem *elwr = lwr->toElem(irs);
4353         elem *eupr = upr->toElem(irs);
4354
4355         elem *elwr2 = el_same(&elwr);
4356
4357         // Create an array reference where:
4358         // length is (upr - lwr)
4359         // pointer is (ptr + lwr*sz)
4360         // Combine as (length pair ptr)
4361
4362         if (irs->arrayBoundsCheck())
4363         {
4364             // Checks (unsigned compares):
4365             //  upr <= array.length
4366             //  lwr <= upr
4367
4368             elem *c1;
4369             elem *c2;
4370             elem *ea;
4371             elem *eb;
4372             elem *eupr2;
4373             elem *elength;
4374
4375             if (t1->ty == Tpointer)
4376             {
4377                 // Just do lwr <= upr check
4378
4379                 eupr2 = el_same(&eupr);
4380                 eupr2->Ety = TYsize_t;                    // make sure unsigned comparison
4381                 c1 = el_bin(OPle, TYint, elwr2, eupr2);
4382                 c1 = el_combine(eupr, c1);
4383                 goto L2;
4384             }
4385             else if (t1->ty == Tsarray)
4386             {   TypeSArray *tsa = (TypeSArray *)t1;
4387                 dinteger_t length = tsa->dim->toInteger();
4388
4389                 elength = el_long(TYsize_t, length);
4390                 goto L1;
4391             }
4392             else if (t1->ty == Tarray)
4393             {
4394                 if (lengthVar)
4395                     elength = el_var(lengthVar->toSymbol());
4396                 else
4397                 {
4398                     elength = e;
4399                     e = el_same(&elength);
4400                     elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elength);
4401                 }
4402             L1:
4403                 eupr2 = el_same(&eupr);
4404                 c1 = el_bin(OPle, TYint, eupr, elength);
4405                 eupr2->Ety = TYsize_t;                    // make sure unsigned comparison
4406                 c2 = el_bin(OPle, TYint, elwr2, eupr2);
4407                 c1 = el_bin(OPandand, TYint, c1, c2);   // (c1 && c2)
4408
4409             L2:
4410                 // Construct: (c1 || ModuleArray(line))
4411                 Symbol *sassert;
4412
4413                 sassert = irs->blx->module->toModuleArray();
4414                 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
4415                 eb = el_bin(OPoror,TYvoid,c1,ea);
4416                 elwr = el_combine(elwr, eb);
4417
4418                 elwr2 = el_copytree(elwr2);
4419                 eupr = el_copytree(eupr2);
4420             }
4421         }
4422
4423         elem *eptr = array_toPtr(e1->type, e);
4424
4425         elem *elength = el_bin(OPmin, TYsize_t, eupr, elwr2);
4426         eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYsize_t, el_copytree(elwr2), el_long(TYsize_t, sz)));
4427
4428         e = el_pair(TYdarray, elength, eptr);
4429         e = el_combine(elwr, e);
4430         e = el_combine(einit, e);
4431     }
4432     else if (t1->ty == Tsarray)
4433     {
4434         e = sarray_toDarray(loc, t1, NULL, e);
4435     }
4436     el_setLoc(e,loc);
4437     return e;
4438 }
4439
4440 elem *IndexExp::toElem(IRState *irs)
4441 {   elem *e;
4442     elem *n1 = e1->toElem(irs);
4443     elem *eb = NULL;
4444
4445     //printf("IndexExp::toElem() %s\n", toChars());
4446     Type *t1 = e1->type->toBasetype();
4447     if (t1->ty == Taarray)
4448     {
4449         // set to:
4450         //      *aaGetX(aa, keyti, valuesize, &key);
4451
4452         TypeAArray *taa = (TypeAArray *)t1;
4453         int vsize = taa->next->size();
4454         Symbol *s;
4455
4456         // n2 becomes the index, also known as the key
4457         elem *n2 = e2->toElem(irs);
4458
4459         if (I64)
4460         {
4461             /* Turn n2 into a pointer to the index.  If it's an lvalue,
4462              * take the address of it. If not, copy it to a temp and
4463              * take the address of that.
4464              */
4465             n2 = addressElem(n2, taa->index);
4466         }
4467         else
4468         {
4469             if (tybasic(n2->Ety) == TYstruct || tybasic(n2->Ety) == TYarray)
4470             {
4471                 n2 = el_una(OPstrpar, TYstruct, n2);
4472                 n2->ET = n2->E1->ET;
4473                 if (taa->index->ty == Tsarray)
4474                 {
4475                     assert(e2->type->size() == taa->index->size());
4476                 }
4477                 //printf("numbytes = %d\n", n2->Enumbytes);
4478             }
4479         }
4480
4481         elem *valuesize = el_long(TYsize_t, vsize);
4482         //printf("valuesize: "); elem_print(valuesize);
4483         if (modifiable)
4484         {
4485             n1 = el_una(OPaddr, TYnptr, n1);
4486             s = taa->aaGetSymbol(I64 ? "GetX" : "Get", 1);
4487         }
4488         else
4489         {
4490             s = taa->aaGetSymbol(I64 ? "GetRvalueX" : "GetRvalue", 1);
4491         }
4492         //printf("taa->index = %s\n", taa->index->toChars());
4493         elem* keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
4494         //keyti = taa->index->getTypeInfo(NULL)->toElem(irs);
4495         //printf("keyti:\n");
4496         //elem_print(keyti);
4497         elem* ep = el_params(n2, valuesize, keyti, n1, NULL);
4498         e = el_bin(OPcall, TYnptr, el_var(s), ep);
4499         if (irs->arrayBoundsCheck())
4500         {
4501             elem *ea;
4502
4503             elem *n = el_same(&e);
4504
4505             // Construct: ((e || ModuleAssert(line)),n)
4506             Symbol *sassert = irs->blx->module->toModuleArray();
4507             ea = el_bin(OPcall,TYvoid,el_var(sassert),
4508                 el_long(TYint, loc.linnum));
4509             e = el_bin(OPoror,TYvoid,e,ea);
4510             e = el_bin(OPcomma, TYnptr, e, n);
4511         }
4512         e = el_una(OPind, type->totym(), e);
4513         if (tybasic(e->Ety) == TYstruct)
4514             e->ET = type->toCtype();
4515     }
4516     else
4517     {
4518         elem *einit = resolveLengthVar(lengthVar, &n1, t1);
4519         elem *n2 = e2->toElem(irs);
4520
4521         if (irs->arrayBoundsCheck())
4522         {
4523             elem *elength;
4524             elem *n2x;
4525             elem *ea;
4526
4527             if (t1->ty == Tsarray)
4528             {   TypeSArray *tsa = (TypeSArray *)t1;
4529                 dinteger_t length = tsa->dim->toInteger();
4530
4531                 elength = el_long(TYsize_t, length);
4532                 goto L1;
4533             }
4534             else if (t1->ty == Tarray)
4535             {
4536                 elength = n1;
4537                 n1 = el_same(&elength);
4538                 elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elength);
4539             L1:
4540                 n2x = n2;
4541                 n2 = el_same(&n2x);
4542                 n2x = el_bin(OPlt, TYint, n2x, elength);
4543
4544                 // Construct: (n2x || ModuleAssert(line))
4545                 Symbol *sassert;
4546
4547                 sassert = irs->blx->module->toModuleArray();
4548                 ea = el_bin(OPcall,TYvoid,el_var(sassert),
4549                     el_long(TYint, loc.linnum));
4550                 eb = el_bin(OPoror,TYvoid,n2x,ea);
4551             }
4552         }
4553
4554         n1 = array_toPtr(t1, n1);
4555
4556         {
4557             elem *escale = el_long(TYsize_t, t1->nextOf()->size());
4558             n2 = el_bin(OPmul, TYsize_t, n2, escale);
4559             e = el_bin(OPadd, TYnptr, n1, n2);
4560             e = el_una(OPind, type->totym(), e);
4561             if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
4562             {   e->Ety = TYstruct;
4563                 e->ET = type->toCtype();
4564             }
4565         }
4566
4567         eb = el_combine(einit, eb);
4568         e = el_combine(eb, e);
4569     }
4570     el_setLoc(e,loc);
4571     return e;
4572 }
4573
4574
4575 elem *TupleExp::toElem(IRState *irs)
4576 {   elem *e = NULL;
4577
4578     //printf("TupleExp::toElem() %s\n", toChars());
4579     for (size_t i = 0; i < exps->dim; i++)
4580     {   Expression *el = (Expression *)exps->data[i];
4581         elem *ep = el->toElem(irs);
4582
4583         e = el_combine(e, ep);
4584     }
4585     return e;
4586 }
4587
4588 #if DMDV2
4589 elem *tree_insert(Expressions *args, int low, int high)
4590 {
4591     assert(low < high);
4592     if (low + 1 == high)
4593         return (elem *)args->data[low];
4594     int mid = (low + high) >> 1;
4595     return el_param(tree_insert(args, low, mid),
4596                     tree_insert(args, mid, high));
4597 }
4598 #endif
4599
4600 elem *ArrayLiteralExp::toElem(IRState *irs)
4601 {   elem *e;
4602     size_t dim;
4603     elem *earg = NULL;
4604
4605     //printf("ArrayLiteralExp::toElem() %s, type = %s\n", toChars(), type->toChars());
4606     Type *tb = type->toBasetype();
4607     if (elements)
4608     {
4609         if (I64)
4610         {   /* Instead of passing the initializers on the stack, allocate the
4611              * array and assign the members inline.
4612              * Avoids the whole variadic arg mess.
4613              */
4614             dim = elements->dim;
4615             Expressions args;
4616             args.setDim(dim);           // +1 for number of args parameter
4617             e = el_long(TYsize_t, dim);
4618             e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4619             // call _d_arrayliteralTX(ti, dim)
4620             e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALTX]),e);
4621             Symbol *stmp = symbol_genauto(Type::tvoid->pointerTo()->toCtype());
4622             e = el_bin(OPeq,TYnptr,el_var(stmp),e);
4623
4624             targ_size_t sz = tb->nextOf()->size();      // element size
4625             ::type *te = tb->nextOf()->toCtype();       // element type
4626             for (size_t i = 0; i < dim; i++)
4627             {   Expression *el = (Expression *)elements->data[i];
4628
4629                 /* Generate: *(stmp + i * sz) = element[i]
4630                  */
4631                 elem *ep = el->toElem(irs);
4632                 elem *ev = el_var(stmp);
4633                 ev = el_bin(OPadd, TYnptr, ev, el_long(TYsize_t, i * sz));
4634                 ev = el_una(OPind, te->Tty, ev);
4635                 elem *eeq = el_bin(OPeq,te->Tty,ev,ep);
4636
4637                 if (tybasic(te->Tty) == TYstruct)
4638                 {
4639                     eeq->Eoper = OPstreq;
4640                     eeq->ET = te;
4641                 }
4642                 else if (tybasic(te->Tty) == TYarray)
4643                 {
4644                     eeq->Eoper = OPstreq;
4645                     eeq->Ejty = eeq->Ety = TYstruct;
4646                     eeq->ET = te;
4647                 }
4648                 args.data[i] = (void *)eeq;
4649             }
4650             e = el_combine(e, el_combines(args.data, dim));
4651             e = el_combine(e, el_var(stmp));
4652         }
4653         else
4654         {
4655             Expressions args;
4656             dim = elements->dim;
4657             args.setDim(dim + 1);           // +1 for number of args parameter
4658             e = el_long(TYsize_t, dim);
4659             args.data[dim] = (void *)e;
4660             for (size_t i = 0; i < dim; i++)
4661             {   Expression *el = (Expression *)elements->data[i];
4662                 elem *ep = el->toElem(irs);
4663
4664                 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
4665                 {
4666                     ep = el_una(OPstrpar, TYstruct, ep);
4667                     ep->ET = el->type->toCtype();
4668                 }
4669                 args.data[dim - (i + 1)] = (void *)ep;
4670             }
4671
4672             /* Because the number of parameters can get very large, produce
4673              * a balanced binary tree so we don't blow up the stack in
4674              * the subsequent tree walking code.
4675              */
4676             e = el_params(args.data, dim + 1);
4677
4678             e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4679
4680             // call _d_arrayliteralT(ti, dim, ...)
4681             e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
4682             e->Eflags |= EFLAGS_variadic;
4683         }
4684     }
4685     else
4686     {   dim = 0;
4687         e = el_long(TYsize_t, 0);
4688     }
4689     if (tb->ty == Tarray)
4690     {
4691         e = el_pair(TYdarray, el_long(TYsize_t, dim), e);
4692     }
4693     else if (tb->ty == Tpointer)
4694     {
4695     }
4696     else
4697     {
4698         e = el_una(OPind,TYstruct,e);
4699         e->ET = type->toCtype();
4700     }
4701
4702     el_setLoc(e,loc);
4703     e = el_combine(earg, e);
4704     return e;
4705 }
4706
4707 /*************************************************
4708  * Allocate a static array, and initialize its members with
4709  * exps[].
4710  * Return the initialization expression, and the symbol for the static array in *psym.
4711  */
4712 elem *ExpressionsToStaticArray(IRState *irs, Loc loc, Expressions *exps, Type *telem, symbol **psym)
4713 {
4714     // Create a static array of type telem[dim]
4715     size_t dim = exps->dim;
4716     Type *tsarray = new TypeSArray(telem, new IntegerExp(loc, dim, Type::tsize_t));
4717     tsarray = tsarray->semantic(loc, NULL);
4718     symbol *stmp = symbol_genauto(tsarray->toCtype());
4719     targ_size_t szelem = telem->size();
4720
4721     Array elems;
4722     elems.setDim(dim);
4723
4724     ::type *te = telem->toCtype();      // stmp[] element type
4725
4726     for (size_t i = 0; i < dim; i++)
4727     {   Expression *el = (Expression *)exps->data[i];
4728
4729         /* Generate: *(&stmp + i * szelem) = element[i]
4730          */
4731         elem *ep = el->toElem(irs);
4732         elem *ev = el_ptr(stmp);
4733         ev = el_bin(OPadd, TYnptr, ev, el_long(TYsize_t, i * szelem));
4734         ev = el_una(OPind, te->Tty, ev);
4735         elem *eeq = el_bin(OPeq,te->Tty,ev,ep);
4736
4737         if (tybasic(te->Tty) == TYstruct)
4738         {
4739             eeq->Eoper = OPstreq;
4740             eeq->ET = te;
4741         }
4742         else if (tybasic(te->Tty) == TYarray)
4743         {
4744             eeq->Eoper = OPstreq;
4745             eeq->Ejty = eeq->Ety = TYstruct;
4746             eeq->ET = te;
4747         }
4748         elems.data[i] = (void *)eeq;
4749     }
4750
4751     *psym = stmp;
4752     return el_combines(elems.data, dim);
4753 }
4754
4755 elem *AssocArrayLiteralExp::toElem(IRState *irs)
4756 {
4757     //printf("AssocArrayLiteralExp::toElem() %s\n", toChars());
4758     size_t dim = keys->dim;
4759     elem *e;
4760
4761     if (I64)
4762     {   // call _d_assocarrayliteralTX(TypeInfo_AssociativeArray ti, void[] keys, void[] values)
4763         // Prefer this to avoid the varargs fiasco in 64 bit code
4764         Type *t = type->toBasetype();
4765         assert(t->ty == Taarray);
4766         TypeAArray *ta = (TypeAArray *)t;
4767
4768         symbol *skeys;
4769         elem *ekeys = ExpressionsToStaticArray(irs, loc, keys, ta->index, &skeys);
4770
4771         symbol *svalues;
4772         elem *evalues = ExpressionsToStaticArray(irs, loc, values, ta->nextOf(), &svalues);
4773
4774         e = el_params(el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(svalues)),
4775                       el_pair(TYdarray, el_long(TYsize_t, dim), el_ptr(skeys  )),
4776                       ta->getTypeInfo(NULL)->toElem(irs),
4777                       NULL);
4778
4779         // call _d_assocarrayliteralTX(ti, keys, values)
4780         e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALTX]),e);
4781         el_setLoc(e,loc);
4782
4783         e = el_combine(evalues, e);
4784         e = el_combine(ekeys, e);
4785     }
4786     else // Keep for binary backwards compatibility
4787     {    // call _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
4788         e = el_long(TYsize_t, dim);
4789         for (size_t i = 0; i < dim; i++)
4790         {   Expression *el = (Expression *)keys->data[i];
4791
4792             for (int j = 0; j < 2; j++)
4793             {
4794                 elem *ep = el->toElem(irs);
4795
4796                 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
4797                 {
4798                     ep = el_una(OPstrpar, TYstruct, ep);
4799                     ep->ET = el->type->toCtype();
4800                 }
4801                 //printf("[%d] %s\n", i, el->toChars());
4802                 //elem_print(ep);
4803                 e = el_param(ep, e);
4804                 el = (Expression *)values->data[i];
4805             }
4806         }
4807
4808         Type *t = type->toBasetype()->mutableOf();
4809         assert(t->ty == Taarray);
4810         TypeAArray *ta = (TypeAArray *)t;
4811
4812 #if 0
4813         /* Unfortunately, the hash function for Aa (array of chars) is custom and
4814          * different from Axa and Aya, which get the generic hash function.
4815          * So, rewrite the type of the AArray so that if it's key type
4816          * is an array of const or invariant, make it an array of mutable.
4817          */
4818         Type *tkey = ta->index->toBasetype();
4819         if (tkey->ty == Tarray)
4820         {
4821             tkey = tkey->nextOf()->mutableOf()->arrayOf();
4822             tkey = tkey->semantic(0, NULL);
4823             ta = new TypeAArray(ta->nextOf(), tkey);
4824             ta = (TypeAArray *)ta->merge();
4825         }
4826 #endif
4827
4828         e = el_param(e, ta->getTypeInfo(NULL)->toElem(irs));
4829
4830         // call _d_assocarrayliteralT(ti, dim, ...)
4831         e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e);
4832         e->Eflags |= EFLAGS_variadic;
4833         el_setLoc(e,loc);
4834     }
4835
4836     return e;
4837 }
4838
4839
4840 /*******************************************
4841  * Generate elem to zero fill contents of Symbol stmp
4842  * from *poffset..offset2.
4843  * May store anywhere from 0..maxoff, as this function
4844  * tries to use aligned int stores whereever possible.
4845  * Update *poffset to end of initialized hole; *poffset will be >= offset2.
4846  */
4847
4848 elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff)
4849 {   elem *e = NULL;
4850     int basealign = 1;
4851
4852     while (*poffset < offset2)
4853     {   tym_t ty;
4854         elem *e1;
4855
4856         if (tybasic(stmp->Stype->Tty) == TYnptr)
4857             e1 = el_var(stmp);
4858         else
4859             e1 = el_ptr(stmp);
4860         if (basealign)
4861             *poffset &= ~3;
4862         basealign = 1;
4863         size_t sz = maxoff - *poffset;
4864         switch (sz)
4865         {   case 1: ty = TYchar;        break;
4866             case 2: ty = TYshort;       break;
4867             case 3:
4868                 ty = TYshort;
4869                 basealign = 0;
4870                 break;
4871             default:
4872                 ty = TYlong;
4873                 break;
4874         }
4875         e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
4876         e1 = el_una(OPind, ty, e1);
4877         e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
4878         e = el_combine(e, e1);
4879         *poffset += tysize[ty];
4880     }
4881     return e;
4882 }
4883
4884 elem *StructLiteralExp::toElem(IRState *irs)
4885 {   elem *e;
4886     size_t dim;
4887
4888     //printf("StructLiteralExp::toElem() %s\n", toChars());
4889
4890     // struct symbol to initialize with the literal
4891     Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype());
4892
4893     e = NULL;
4894
4895     if (fillHoles)
4896     {
4897         /* Initialize all alignment 'holes' to zero.
4898          * Do before initializing fields, as the hole filling process
4899          * can spill over into the fields.
4900          */
4901         size_t offset = 0;
4902         for (size_t i = 0; i < sd->fields.dim; i++)
4903         {
4904             Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4905             VarDeclaration *v = s->isVarDeclaration();
4906             assert(v);
4907
4908             e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize));
4909             size_t vend = v->offset + v->type->size();
4910             if (offset < vend)
4911                 offset = vend;
4912         }
4913         e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize));
4914     }
4915
4916     if (elements)
4917     {
4918         dim = elements->dim;
4919         assert(dim <= sd->fields.dim);
4920         for (size_t i = 0; i < dim; i++)
4921         {   Expression *el = (Expression *)elements->data[i];
4922             if (!el)
4923                 continue;
4924
4925             Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4926             VarDeclaration *v = s->isVarDeclaration();
4927             assert(v);
4928             assert(!v->isThisDeclaration());
4929
4930             elem *e1;
4931             if (tybasic(stmp->Stype->Tty) == TYnptr)
4932             {   e1 = el_var(stmp);
4933                 e1->EV.sp.Voffset = soffset;
4934             }
4935             else
4936             {   e1 = el_ptr(stmp);
4937                 if (soffset)
4938                     e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
4939             }
4940             e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset));
4941             elem *ec = e1;                      // pointer to destination
4942
4943             elem *ep = el->toElem(irs);
4944
4945             Type *t1b = v->type->toBasetype();
4946             Type *t2b = el->type->toBasetype();
4947             if (t1b->ty == Tsarray)
4948             {
4949                 if (t2b->implicitConvTo(t1b))
4950                 {
4951 #if DMDV2
4952                     // Determine if postblit is needed
4953                     int postblit = 0;
4954                     if (needsPostblit(t1b))
4955                         postblit = 1;
4956
4957                     if (postblit)
4958                     {
4959                         /* Generate:
4960                          *      _d_arrayctor(ti, From: ep, To: e1)
4961                          */
4962                         Expression *ti = t1b->nextOf()->toBasetype()->getTypeInfo(NULL);
4963                         elem *esize = el_long(TYsize_t, ((TypeSArray *)t1b)->dim->toInteger());
4964                         e1 = el_pair(TYdarray, esize, e1);
4965                         ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el->type, ep));
4966                         ep = el_params(e1, ep, ti->toElem(irs), NULL);
4967                         int rtl = RTLSYM_ARRAYCTOR;
4968                         e1 = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
4969                     }
4970                     else
4971 #endif
4972                     {
4973                         elem *esize = el_long(TYsize_t, t1b->size());
4974                         ep = array_toPtr(el->type, ep);
4975                         e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
4976                     }
4977                 }
4978                 else
4979                 {
4980                     elem *edim = el_long(TYsize_t, t1b->size() / t2b->size());
4981                     e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct);
4982                 }
4983             }
4984             else
4985             {
4986                 tym_t ty = v->type->totym();
4987                 e1 = el_una(OPind, ty, e1);
4988                 if (tybasic(ty) == TYstruct)
4989                     e1->ET = v->type->toCtype();
4990                 e1 = el_bin(OPeq, ty, e1, ep);
4991                 if (tybasic(ty) == TYstruct)
4992                 {   e1->Eoper = OPstreq;
4993                     e1->ET = v->type->toCtype();
4994                 }
4995 #if DMDV2
4996                 /* Call postblit() on e1
4997                  */
4998                 StructDeclaration *sd = needsPostblit(v->type);
4999                 if (sd)
5000                 {   FuncDeclaration *fd = sd->postblit;
5001                     ec = el_copytree(ec);
5002                     ec = callfunc(loc, irs, 1, Type::tvoid, ec, sd->type->pointerTo(), fd, fd->type, NULL, NULL);
5003                     e1 = el_bin(OPcomma, ec->Ety, e1, ec);
5004                 }
5005 #endif
5006             }
5007             e = el_combine(e, e1);
5008         }
5009     }
5010
5011 #if DMDV2
5012     if (sd->isnested)
5013     {   // Initialize the hidden 'this' pointer
5014         assert(sd->fields.dim);
5015         Dsymbol *s = (Dsymbol *)sd->fields.data[sd->fields.dim - 1];
5016         ThisDeclaration *v = s->isThisDeclaration();
5017         assert(v);
5018
5019         elem *e1;
5020         if (tybasic(stmp->Stype->Tty) == TYnptr)
5021         {   e1 = el_var(stmp);
5022             e1->EV.sp.Voffset = soffset;
5023         }
5024         else
5025         {   e1 = el_ptr(stmp);
5026             if (soffset)
5027                 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
5028         }
5029         e1 = setEthis(loc, irs, e1, sd);
5030
5031         e = el_combine(e, e1);
5032     }
5033 #endif
5034
5035     elem *ev = el_var(stmp);
5036     ev->ET = sd->type->toCtype();
5037     e = el_combine(e, ev);
5038     el_setLoc(e,loc);
5039     return e;
5040 }
Note: See TracBrowser for help on using the browser.