Document search flags
[delight/core.git] / dmd2 / e2ir.c
blob308d867039e6c04f6a5de632bbf5f798cddc1725
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 #include <stdio.h>
12 #include <string.h>
13 #include <time.h>
14 #include <complex.h>
16 #include "lexer.h"
17 #include "expression.h"
18 #include "mtype.h"
19 #include "dsymbol.h"
20 #include "declaration.h"
21 #include "enum.h"
22 #include "aggregate.h"
23 #include "attrib.h"
24 #include "module.h"
25 #include "init.h"
26 #include "template.h"
28 #if _WIN32
29 #include "..\tk\mem.h" // for mem_malloc
30 #elif linux
31 #include "../tk/mem.h" // for mem_malloc
32 #endif
34 #include "cc.h"
35 #include "el.h"
36 #include "oper.h"
37 #include "global.h"
38 #include "code.h"
39 #include "type.h"
40 #include "dt.h"
41 #include "irstate.h"
42 #include "id.h"
43 #include "type.h"
44 #include "toir.h"
46 static char __file__[] = __FILE__; /* for tassert.h */
47 #include "tassert.h"
50 elem *addressElem(elem *e, Type *t);
51 elem *array_toPtr(Type *t, elem *e);
52 elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result);
53 elem *bit_read(elem *eb, elem *ei, int result);
54 elem *exp2_copytotemp(elem *e);
56 #define el_setLoc(e,loc) ((e)->Esrcpos.Sfilename = (loc).filename, \
57 (e)->Esrcpos.Slinnum = (loc).linnum)
59 /************************************
60 * Call a function.
63 elem *callfunc(Loc loc,
64 IRState *irs,
65 int directcall, // 1: don't do virtual call
66 Type *tret, // return type
67 elem *ec, // evaluates to function address
68 Type *ectype, // original type of ec
69 FuncDeclaration *fd, // if !=NULL, this is the function being called
70 Type *t, // TypeDelegate or TypeFunction for this function
71 elem *ehidden, // if !=NULL, this is the 'hidden' argument
72 Array *arguments)
74 elem *ep;
75 elem *e;
76 elem *ethis = NULL;
77 elem *eside = NULL;
78 int i;
79 tym_t ty;
80 tym_t tyret;
81 enum RET retmethod;
82 int reverse;
83 TypeFunction *tf;
84 int op;
86 #if 0
87 printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
88 directcall, tret->toChars(), ec, fd);
89 printf("ec: "); elem_print(ec);
90 if (fd)
91 printf("fd = '%s'\n", fd->toChars());
92 #endif
94 t = t->toBasetype();
95 if (t->ty == Tdelegate)
97 // A delegate consists of:
98 // { Object *this; Function *funcptr; }
99 assert(!fd);
100 assert(t->nextOf()->ty == Tfunction);
101 tf = (TypeFunction *)(t->nextOf());
102 ethis = ec;
103 ec = el_same(&ethis);
104 ethis = el_una(OP64_32, TYnptr, ethis); // get this
105 ec = array_toPtr(t, ec); // get funcptr
106 ec = el_una(OPind, tf->totym(), ec);
108 else
109 { assert(t->ty == Tfunction);
110 tf = (TypeFunction *)(t);
112 retmethod = tf->retStyle();
113 ty = ec->Ety;
114 if (fd)
115 ty = fd->toSymbol()->Stype->Tty;
116 reverse = tyrevfunc(ty);
117 ep = NULL;
118 if (arguments)
120 // j=1 if _arguments[] is first argument
121 int j = (tf->linkage == LINKd && tf->varargs == 1);
123 for (i = 0; i < arguments->dim ; i++)
124 { Expression *arg;
125 elem *ea;
127 arg = (Expression *)arguments->data[i];
128 //printf("\targ[%d]: %s\n", i, arg->toChars());
130 size_t nparams = Argument::dim(tf->parameters);
131 if (i - j < nparams && i >= j)
133 Argument *p = Argument::getNth(tf->parameters, i - j);
135 if (p->storageClass & (STCout | STCref))
137 // Convert argument to a pointer,
138 // use AddrExp::toElem()
139 Expression *ae = arg->addressOf(NULL);
140 ea = ae->toElem(irs);
141 goto L1;
144 ea = arg->toElem(irs);
146 if (ea->Ety == TYstruct)
148 ea = el_una(OPstrpar, TYstruct, ea);
149 ea->Enumbytes = ea->E1->Enumbytes;
150 assert(ea->Enumbytes);
152 if (reverse)
153 ep = el_param(ep,ea);
154 else
155 ep = el_param(ea,ep);
159 if (retmethod == RETstack)
161 if (!ehidden)
162 { // Don't have one, so create one
163 type *t;
165 if (tf->next->toBasetype()->ty == Tstruct)
166 t = tf->next->toCtype();
167 else
168 t = type_fake(tf->next->totym());
169 Symbol *stmp = symbol_genauto(t);
170 ehidden = el_ptr(stmp);
172 if (ep)
174 #if 0 // BUG: implement
175 if (reverse && type_mangle(tfunc) == mTYman_cpp)
176 ep = el_param(ehidden,ep);
177 else
178 #endif
179 ep = el_param(ep,ehidden);
181 else
182 ep = ehidden;
183 ehidden = NULL;
185 assert(ehidden == NULL);
187 if (fd && fd->isMember2())
189 InterfaceDeclaration *intd;
190 Symbol *sfunc;
191 AggregateDeclaration *ad;
193 ad = fd->isThis();
194 if (ad)
196 ethis = ec;
197 if (ad->handle->ty == Tpointer && tybasic(ec->Ety) != TYnptr)
199 ethis = addressElem(ec, ectype);
202 else
204 // Evaluate ec for side effects
205 eside = ec;
207 sfunc = fd->toSymbol();
209 if (!fd->isVirtual() ||
210 directcall || // BUG: fix
211 fd->isFinal()
214 // make static call
215 ec = el_var(sfunc);
217 else
219 // make virtual call
220 elem *ev;
221 unsigned vindex;
223 assert(ethis);
224 ev = el_same(&ethis);
225 ev = el_una(OPind, TYnptr, ev);
226 vindex = fd->vtblIndex;
228 // Build *(ev + vindex * 4)
229 ec = el_bin(OPadd,TYnptr,ev,el_long(TYint, vindex * 4));
230 ec = el_una(OPind,TYnptr,ec);
231 ec = el_una(OPind,tybasic(sfunc->Stype->Tty),ec);
234 else if (fd && fd->isNested())
236 assert(!ethis);
237 ethis = getEthis(0, irs, fd);
241 ep = el_param(ep, ethis);
243 tyret = tret->totym();
245 // Look for intrinsic functions
246 if (ec->Eoper == OPvar && (op = intrinsic_op(ec->EV.sp.Vsym->Sident)) != -1)
248 el_free(ec);
249 if (OTbinary(op))
251 ep->Eoper = op;
252 ep->Ety = tyret;
253 e = ep;
254 if (op == OPscale)
255 { elem *et;
257 et = e->E1;
258 e->E1 = el_una(OPs32_d, TYdouble, e->E2);
259 e->E1 = el_una(OPd_ld, TYldouble, e->E1);
260 e->E2 = et;
261 e->Ety = tyret;
264 else
265 e = el_una(op,tyret,ep);
267 else if (ep)
268 e = el_bin(OPcall,tyret,ec,ep);
269 else
270 e = el_una(OPucall,tyret,ec);
272 if (retmethod == RETstack)
274 e->Ety = TYnptr;
275 e = el_una(OPind, tyret, e);
277 if (tybasic(tyret) == TYstruct)
279 e->Enumbytes = tret->size();
281 e = el_combine(eside, e);
282 return e;
285 /*******************************************
286 * Take address of an elem.
289 elem *addressElem(elem *e, Type *t)
291 elem **pe;
293 //printf("addressElem()\n");
295 for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2)
297 if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind)
298 { Symbol *stmp;
299 elem *eeq;
300 elem *e = *pe;
301 type *tx;
303 // Convert to ((tmp=e),tmp)
304 TY ty;
305 if (t && ((ty = t->toBasetype()->ty) == Tstruct || ty == Tsarray))
306 tx = t->toCtype();
307 else
308 tx = type_fake(e->Ety);
309 stmp = symbol_genauto(tx);
310 eeq = el_bin(OPeq,e->Ety,el_var(stmp),e);
311 if (e->Ety == TYstruct)
313 eeq->Eoper = OPstreq;
314 eeq->Enumbytes = e->Enumbytes;
316 else if (e->Ety == TYarray)
318 eeq->Eoper = OPstreq;
319 eeq->Ejty = eeq->Ety = TYstruct;
320 eeq->Enumbytes = t->size();
322 *pe = el_bin(OPcomma,e->Ety,eeq,el_var(stmp));
324 e = el_una(OPaddr,TYnptr,e);
325 return e;
328 /*****************************************
329 * Convert array to a pointer to the data.
332 elem *array_toPtr(Type *t, elem *e)
334 //printf("array_toPtr()\n");
335 //elem_print(e);
336 t = t->toBasetype();
337 switch (t->ty)
339 case Tpointer:
340 break;
342 case Tarray:
343 case Tdelegate:
344 if (e->Eoper == OPcomma)
346 e->Ety = TYnptr;
347 e->E2 = array_toPtr(t, e->E2);
349 else if (e->Eoper == OPpair)
351 e->Eoper = OPcomma;
352 e->Ety = TYnptr;
354 else
356 #if 1
357 e = el_una(OPmsw, TYnptr, e);
358 #else
359 e = el_una(OPaddr, TYnptr, e);
360 e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
361 e = el_una(OPind, TYnptr, e);
362 #endif
364 break;
366 case Tsarray:
367 e = el_una(OPaddr, TYnptr, e);
368 break;
370 default:
371 t->print();
372 assert(0);
374 return e;
377 /*****************************************
378 * Convert array to a dynamic array.
381 elem *array_toDarray(Type *t, elem *e)
383 unsigned dim;
384 elem *ef = NULL;
385 elem *ex;
387 //printf("array_toDarray(t = %s)\n", t->toChars());
388 //elem_print(e);
389 t = t->toBasetype();
390 switch (t->ty)
392 case Tarray:
393 break;
395 case Tsarray:
396 e = el_una(OPaddr, TYnptr, e);
397 dim = ((TypeSArray *)t)->dim->toInteger();
398 e = el_pair(TYullong, el_long(TYint, dim), e);
399 break;
401 default:
403 switch (e->Eoper)
405 case OPconst:
407 size_t len = tysize[tybasic(e->Ety)];
408 elem *es = el_calloc();
409 es->Eoper = OPstring;
411 // Match MEM_PH_FREE for OPstring in ztc\el.c
412 es->EV.ss.Vstring = (char *)mem_malloc(len);
413 memcpy(es->EV.ss.Vstring, &e->EV, len);
415 es->EV.ss.Vstrlen = len;
416 es->Ety = TYnptr;
417 e = es;
418 break;
421 case OPvar:
422 e = el_una(OPaddr, TYnptr, e);
423 break;
425 case OPcomma:
426 ef = el_combine(ef, e->E1);
427 ex = e;
428 e = e->E2;
429 ex->E1 = NULL;
430 ex->E2 = NULL;
431 el_free(ex);
432 goto L1;
434 case OPind:
435 ex = e;
436 e = e->E1;
437 ex->E1 = NULL;
438 ex->E2 = NULL;
439 el_free(ex);
440 break;
442 default:
444 // Copy expression to a variable and take the
445 // address of that variable.
446 Symbol *stmp;
447 tym_t ty = tybasic(e->Ety);
449 if (ty == TYstruct)
451 if (e->Enumbytes == 4)
452 ty = TYint;
453 else if (e->Enumbytes == 8)
454 ty = TYllong;
456 e->Ety = ty;
457 stmp = symbol_genauto(type_fake(ty));
458 e = el_bin(OPeq, e->Ety, el_var(stmp), e);
459 e = el_bin(OPcomma, TYnptr, e, el_una(OPaddr, TYnptr, el_var(stmp)));
460 break;
463 dim = 1;
464 e = el_pair(TYullong, el_long(TYint, dim), e);
465 break;
467 return el_combine(ef, e);
470 /*****************************************
471 * Evaluate elem and convert to dynamic array.
474 elem *eval_Darray(IRState *irs, Expression *e)
476 elem *ex;
478 ex = e->toElem(irs);
479 return array_toDarray(e->type, ex);
482 /************************************
485 elem *sarray_toDarray(Type *tfrom, Type *tto, elem *e)
487 //printf("sarray_toDarray()\n");
488 //elem_print(e);
490 elem *elen;
491 unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger();
493 if (tto)
495 unsigned fsize = tfrom->nextOf()->size();
496 unsigned tsize = tto->nextOf()->size();
498 if ((dim * fsize) % tsize != 0)
500 Lerr:
501 error((Loc)0, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars());
503 dim = (dim * fsize) / tsize;
506 elen = el_long(TYint, dim);
507 e = el_una(OPaddr, TYnptr, e);
508 e = el_pair(TYullong, elen, e);
509 return e;
512 /*******************************************
513 * Set an array pointed to by eptr to evalue:
514 * eptr[0..edim] = evalue;
515 * Input:
516 * eptr where to write the data to
517 * evalue value to write
518 * edim number of times to write evalue to eptr[]
519 * tb type of evalue
522 elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue, IRState *irs, int op)
523 { int r;
524 elem *e;
525 int sz = tb->size();
527 if (tb->ty == Tfloat80 || tb->ty == Timaginary80)
528 r = RTLSYM_MEMSET80;
529 else if (tb->ty == Tcomplex80)
530 r = RTLSYM_MEMSET160;
531 else if (tb->ty == Tcomplex64)
532 r = RTLSYM_MEMSET128;
533 else
535 switch (sz)
537 case 1: r = RTLSYM_MEMSET8; break;
538 case 2: r = RTLSYM_MEMSET16; break;
539 case 4: r = RTLSYM_MEMSET32; break;
540 case 8: r = RTLSYM_MEMSET64; break;
541 default: r = RTLSYM_MEMSETN; break;
544 /* Determine if we need to do postblit
546 if (op != TOKblit)
548 Type *t = tb;
549 while (t->ty == Tsarray)
550 t = t->nextOf()->toBasetype();
551 if (t->ty == Tstruct)
552 { StructDeclaration *sd = ((TypeStruct *)t)->sym;
553 if (sd->postblit)
554 { /* Need to do postblit.
555 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
557 r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN;
558 evalue = el_una(OPaddr, TYnptr, evalue);
559 Expression *ti = tb->getTypeInfo(NULL);
560 elem *eti = ti->toElem(irs);
561 e = el_params(eti, edim, evalue, eptr, NULL);
562 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
563 return e;
568 if (r == RTLSYM_MEMSETN)
570 // void *_memsetn(void *p, void *value, int dim, int sizelem)
571 evalue = el_una(OPaddr, TYnptr, evalue);
572 elem *esz = el_long(TYint, sz);
573 e = el_params(esz, edim, evalue, eptr, NULL);
574 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
575 return e;
578 if (sz > 1 && sz <= 8 &&
579 evalue->Eoper == OPconst && el_allbits(evalue, 0))
581 r = RTLSYM_MEMSET8;
582 edim = el_bin(OPmul, TYuint, edim, el_long(TYuint, sz));
585 if (evalue->Ety == TYstruct)
587 evalue = el_una(OPstrpar, TYstruct, evalue);
588 evalue->Enumbytes = evalue->E1->Enumbytes;
589 assert(evalue->Enumbytes);
592 // Be careful about parameter side effect ordering
593 if (r == RTLSYM_MEMSET8)
595 e = el_param(edim, evalue);
596 e = el_bin(OPmemset,TYnptr,eptr,e);
598 else
600 e = el_params(edim, evalue, eptr, NULL);
601 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
603 return e;
606 /***************************************
609 elem *Expression::toElem(IRState *irs)
611 print();
612 assert(0);
613 return NULL;
616 /************************************
619 elem *SymbolExp::toElem(IRState *irs)
620 { Symbol *s;
621 elem *e;
622 tym_t tym;
623 Type *tb = (op == TOKsymoff) ? var->type->toBasetype() : type->toBasetype();
624 int offset = (op == TOKsymoff) ? ((SymOffExp*)this)->offset : 0;
625 FuncDeclaration *fd;
626 VarDeclaration *v = var->isVarDeclaration();
628 //printf("SymbolExp::toElem('%s') %p\n", toChars(), this);
629 //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
630 if (op == TOKvar && var->needThis())
632 error("need 'this' to access member %s", toChars());
633 return el_long(TYint, 0);
635 s = var->toSymbol();
636 fd = NULL;
637 if (var->toParent2())
638 fd = var->toParent2()->isFuncDeclaration();
640 int nrvo = 0;
641 if (fd && fd->nrvo_can && fd->nrvo_var == var)
643 s = fd->shidden;
644 nrvo = 1;
647 if (s->Sclass == SCauto || s->Sclass == SCparameter)
649 if (fd && fd != irs->getFunc())
650 { // 'var' is a variable in an enclosing function.
651 elem *ethis;
652 int soffset;
654 ethis = getEthis(loc, irs, fd);
655 ethis = el_una(OPaddr, TYnptr, ethis);
657 if (v && v->offset)
658 soffset = v->offset;
659 else
661 soffset = s->Soffset;
662 /* If fd is a non-static member function of a class or struct,
663 * then ethis isn't the frame pointer.
664 * ethis is the 'this' pointer to the class/struct instance.
665 * We must offset it.
667 if (fd->vthis)
669 soffset -= fd->vthis->toSymbol()->Soffset;
671 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
674 if (!nrvo)
675 soffset += offset;
677 e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
678 if (op == TOKvar)
679 e = el_una(OPind, TYnptr, e);
680 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
681 e = el_una(OPind, s->ty(), e);
682 else if (op == TOKsymoff && nrvo)
683 { e = el_una(OPind, TYnptr, e);
684 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
686 goto L1;
690 /* If var is a member of a closure
692 if (v && v->offset)
693 { assert(irs->sclosure);
694 e = el_var(irs->sclosure);
695 e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
696 if (op == TOKvar)
697 { e = el_una(OPind, type->totym(), e);
698 if (tybasic(e->Ety) == TYstruct)
699 e->Enumbytes = type->size();
700 el_setLoc(e, loc);
702 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
703 { e->Ety = TYnptr;
704 e = el_una(OPind, s->ty(), e);
706 else if (op == TOKsymoff && nrvo)
707 { e = el_una(OPind, TYnptr, e);
708 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
710 else if (op == TOKsymoff)
712 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
714 goto L1;
717 if (s->Sclass == SCauto && s->Ssymnum == -1)
719 //printf("\tadding symbol\n");
720 symbol_add(s);
723 if (var->isImportedSymbol())
725 assert(op == TOKvar);
726 e = el_var(var->toImport());
727 e = el_una(OPind,s->ty(),e);
729 else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
730 { // Static arrays are really passed as pointers to the array
731 // Out parameters are really references
732 e = el_var(s);
733 e->Ety = TYnptr;
734 if (op == TOKvar)
735 e = el_una(OPind, s->ty(), e);
736 else if (offset)
737 e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
739 else if (op == TOKvar)
740 e = el_var(s);
741 else
742 { e = nrvo ? el_var(s) : el_ptr(s);
743 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
746 if (op == TOKvar)
748 if (nrvo)
750 e->Ety = TYnptr;
751 e = el_una(OPind, 0, e);
753 if (tb->ty == Tfunction)
755 tym = s->Stype->Tty;
757 else
758 tym = type->totym();
759 e->Ejty = e->Ety = tym;
760 if (tybasic(tym) == TYstruct)
762 e->Enumbytes = type->size();
764 else if (tybasic(tym) == TYarray)
766 e->Ejty = e->Ety = TYstruct;
767 e->Enumbytes = type->size();
770 el_setLoc(e,loc);
771 return e;
774 #if 0
775 elem *VarExp::toElem(IRState *irs)
776 { Symbol *s;
777 elem *e;
778 tym_t tym;
779 Type *tb = type->toBasetype();
780 FuncDeclaration *fd;
781 VarDeclaration *v = var->isVarDeclaration();
783 //printf("VarExp::toElem('%s') %p\n", toChars(), this);
784 //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
785 if (var->needThis())
787 error("need 'this' to access member %s", toChars());
788 return el_long(TYint, 0);
790 s = var->toSymbol();
791 fd = NULL;
792 if (var->toParent2())
793 fd = var->toParent2()->isFuncDeclaration();
795 int nrvo = 0;
796 if (fd && fd->nrvo_can && fd->nrvo_var == var)
798 s = fd->shidden;
799 nrvo = 1;
802 if (s->Sclass == SCauto || s->Sclass == SCparameter)
804 if (fd && fd != irs->getFunc())
805 { // 'var' is a variable in an enclosing function.
806 elem *ethis;
807 int soffset;
809 ethis = getEthis(loc, irs, fd);
810 ethis = el_una(OPaddr, TYnptr, ethis);
812 if (v && v->offset)
813 soffset = v->offset;
814 else
816 soffset = s->Soffset;
817 /* If fd is a non-static member function of a class or struct,
818 * then ethis isn't the frame pointer.
819 * ethis is the 'this' pointer to the class/struct instance.
820 * We must offset it.
822 if (fd->vthis)
824 soffset -= fd->vthis->toSymbol()->Soffset;
826 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
829 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
830 e = el_una(OPind, 0, ethis);
831 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
832 goto L2;
833 goto L1;
837 /* If var is a member of a closure
839 if (v && v->offset)
840 { assert(irs->sclosure);
841 e = el_var(irs->sclosure);
842 e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
843 e = el_una(OPind, type->totym(), e);
844 if (tybasic(e->Ety) == TYstruct)
845 e->Enumbytes = type->size();
846 el_setLoc(e, loc);
848 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
849 goto L2;
850 goto L1;
853 if (s->Sclass == SCauto && s->Ssymnum == -1)
855 //printf("\tadding symbol\n");
856 symbol_add(s);
859 if (var->isImportedSymbol())
861 e = el_var(var->toImport());
862 e = el_una(OPind,s->ty(),e);
864 else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
865 { // Static arrays are really passed as pointers to the array
866 // Out parameters are really references
867 e = el_var(s);
869 e->Ety = TYnptr;
870 e = el_una(OPind, s->ty(), e);
872 else
873 e = el_var(s);
875 if (nrvo)
877 e->Ety = TYnptr;
878 e = el_una(OPind, 0, e);
880 if (tb->ty == Tfunction)
882 tym = s->Stype->Tty;
884 else
885 tym = type->totym();
886 e->Ejty = e->Ety = tym;
887 if (tybasic(tym) == TYstruct)
889 e->Enumbytes = type->size();
891 else if (tybasic(tym) == TYarray)
893 e->Ejty = e->Ety = TYstruct;
894 e->Enumbytes = type->size();
896 el_setLoc(e,loc);
897 return e;
899 #endif
901 #if 0
902 elem *SymOffExp::toElem(IRState *irs)
903 { Symbol *s;
904 elem *e;
905 Type *tb = var->type->toBasetype();
906 VarDeclaration *v = var->isVarDeclaration();
907 FuncDeclaration *fd = NULL;
908 if (var->toParent2())
909 fd = var->toParent2()->isFuncDeclaration();
911 //printf("SymOffExp::toElem(): %s\n", toChars());
912 s = var->toSymbol();
914 int nrvo = 0;
915 if (fd && fd->nrvo_can && fd->nrvo_var == var)
916 { s = fd->shidden;
917 nrvo = 1;
920 if (s->Sclass == SCauto && s->Ssymnum == -1)
921 symbol_add(s);
922 assert(!var->isImportedSymbol());
924 // This code closely parallels that in VarExp::toElem()
925 if (s->Sclass == SCauto || s->Sclass == SCparameter)
927 if (fd && fd != irs->getFunc())
928 { // 'var' is a variable in an enclosing function.
929 elem *ethis;
930 int soffset;
932 ethis = getEthis(loc, irs, fd);
933 ethis = el_una(OPaddr, TYnptr, ethis);
935 if (v && v->offset)
936 soffset = v->offset;
937 else
939 soffset = s->Soffset;
940 /* If fd is a non-static member function of a class or struct,
941 * then ethis isn't the frame pointer.
942 * ethis is the 'this' pointer to the class/struct instance.
943 * We must offset it.
945 if (fd->vthis)
947 soffset -= fd->vthis->toSymbol()->Soffset;
949 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
952 if (!nrvo)
953 soffset += offset;
954 e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
955 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
956 e = el_una(OPind, s->ty(), e);
957 else if (nrvo)
958 { e = el_una(OPind, TYnptr, e);
959 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
961 goto L1;
965 /* If var is a member of a closure
967 if (v && v->offset)
968 { assert(irs->sclosure);
969 e = el_var(irs->sclosure);
970 e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset));
971 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
972 e = el_una(OPind, s->ty(), e);
973 else if (nrvo)
974 { e = el_una(OPind, TYnptr, e);
975 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
977 goto L1;
980 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
981 { // Static arrays are really passed as pointers to the array
982 // Out parameters are really references
983 e = el_var(s);
984 e->Ety = TYnptr;
985 if (offset)
986 e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
988 else
989 { e = nrvo ? el_var(s) : el_ptr(s);
990 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
994 el_setLoc(e,loc);
995 return e;
997 #endif
999 /**************************************
1002 elem *FuncExp::toElem(IRState *irs)
1004 elem *e;
1005 Symbol *s;
1007 //printf("FuncExp::toElem() %s\n", toChars());
1008 s = fd->toSymbol();
1009 e = el_ptr(s);
1010 if (fd->isNested())
1012 elem *ethis = getEthis(loc, irs, fd);
1013 e = el_pair(TYullong, ethis, e);
1016 irs->deferToObj->push(fd);
1017 el_setLoc(e,loc);
1018 return e;
1021 /**************************************
1024 elem *Dsymbol_toElem(Dsymbol *s, IRState *irs)
1026 elem *e = NULL;
1027 Symbol *sp;
1028 AttribDeclaration *ad;
1029 VarDeclaration *vd;
1030 ClassDeclaration *cd;
1031 StructDeclaration *sd;
1032 FuncDeclaration *fd;
1033 TemplateMixin *tm;
1034 TupleDeclaration *td;
1035 TypedefDeclaration *tyd;
1037 //printf("Dsymbol_toElem() %s\n", s->toChars());
1038 ad = s->isAttribDeclaration();
1039 if (ad)
1041 Array *decl = ad->include(NULL, NULL);
1042 if (decl && decl->dim)
1044 for (size_t i = 0; i < decl->dim; i++)
1046 s = (Dsymbol *)decl->data[i];
1047 e = el_combine(e, Dsymbol_toElem(s, irs));
1051 else if ((vd = s->isVarDeclaration()) != NULL)
1053 s = s->toAlias();
1054 if (s != vd)
1055 return Dsymbol_toElem(s, irs);
1056 if (vd->isStatic() || vd->storage_class & STCextern)
1057 vd->toObjFile(0);
1058 else
1060 sp = s->toSymbol();
1061 symbol_add(sp);
1062 //printf("\tadding symbol '%s'\n", sp->Sident);
1063 if (vd->init)
1065 ExpInitializer *ie;
1067 ie = vd->init->isExpInitializer();
1068 if (ie)
1069 e = ie->exp->toElem(irs);
1073 else if ((cd = s->isClassDeclaration()) != NULL)
1075 irs->deferToObj->push(s);
1077 else if ((sd = s->isStructDeclaration()) != NULL)
1079 irs->deferToObj->push(sd);
1081 else if ((fd = s->isFuncDeclaration()) != NULL)
1083 //printf("function %s\n", fd->toChars());
1084 irs->deferToObj->push(fd);
1086 else if ((tm = s->isTemplateMixin()) != NULL)
1088 //printf("%s\n", tm->toChars());
1089 if (tm->members)
1091 for (size_t i = 0; i < tm->members->dim; i++)
1093 Dsymbol *sm = (Dsymbol *)tm->members->data[i];
1094 e = el_combine(e, Dsymbol_toElem(sm, irs));
1098 else if ((td = s->isTupleDeclaration()) != NULL)
1100 for (size_t i = 0; i < td->objects->dim; i++)
1101 { Object *o = (Object *)td->objects->data[i];
1102 if (o->dyncast() == DYNCAST_EXPRESSION)
1103 { Expression *eo = (Expression *)o;
1104 if (eo->op == TOKdsymbol)
1105 { DsymbolExp *se = (DsymbolExp *)eo;
1106 e = el_combine(e, Dsymbol_toElem(se->s, irs));
1111 else if ((tyd = s->isTypedefDeclaration()) != NULL)
1113 irs->deferToObj->push(tyd);
1115 return e;
1118 elem *DeclarationExp::toElem(IRState *irs)
1119 { elem *e;
1121 //printf("DeclarationExp::toElem() %s\n", toChars());
1122 e = Dsymbol_toElem(declaration, irs);
1123 return e;
1126 /***************************************
1129 elem *ThisExp::toElem(IRState *irs)
1130 { elem *ethis;
1131 FuncDeclaration *fd;
1133 //printf("ThisExp::toElem()\n");
1134 assert(irs->sthis);
1136 if (var)
1138 assert(var->parent);
1139 fd = var->toParent2()->isFuncDeclaration();
1140 assert(fd);
1141 ethis = getEthis(loc, irs, fd);
1143 else
1144 ethis = el_var(irs->sthis);
1146 el_setLoc(ethis,loc);
1147 return ethis;
1150 /***************************************
1153 elem *IntegerExp::toElem(IRState *irs)
1154 { elem *e;
1156 e = el_long(type->totym(), value);
1157 el_setLoc(e,loc);
1158 return e;
1161 /***************************************
1164 elem *RealExp::toElem(IRState *irs)
1165 { union eve c;
1166 tym_t ty;
1168 //printf("RealExp::toElem(%p)\n", this);
1169 memset(&c, 0, sizeof(c));
1170 ty = type->toBasetype()->totym();
1171 switch (ty)
1173 case TYfloat:
1174 case TYifloat:
1175 c.Vfloat = value;
1176 break;
1178 case TYdouble:
1179 case TYidouble:
1180 c.Vdouble = value;
1181 break;
1183 case TYldouble:
1184 case TYildouble:
1185 c.Vldouble = value;
1186 break;
1188 default:
1189 print();
1190 type->print();
1191 type->toBasetype()->print();
1192 printf("ty = %d, tym = %x\n", type->ty, ty);
1193 assert(0);
1195 return el_const(ty, &c);
1199 /***************************************
1202 elem *ComplexExp::toElem(IRState *irs)
1203 { union eve c;
1204 tym_t ty;
1205 real_t re;
1206 real_t im;
1208 re = creall(value);
1209 im = cimagl(value);
1211 memset(&c, 0, sizeof(c));
1212 ty = type->totym();
1213 switch (ty)
1215 case TYcfloat:
1216 c.Vcfloat.re = (float) re;
1217 c.Vcfloat.im = (float) im;
1218 break;
1220 case TYcdouble:
1221 c.Vcdouble.re = (double) re;
1222 c.Vcdouble.im = (double) im;
1223 break;
1225 case TYcldouble:
1226 c.Vcldouble.re = re;
1227 c.Vcldouble.im = im;
1228 break;
1230 default:
1231 assert(0);
1233 return el_const(ty, &c);
1236 /***************************************
1239 elem *NullExp::toElem(IRState *irs)
1241 return el_long(type->totym(), 0);
1244 /***************************************
1247 struct StringTab
1249 Module *m; // module we're generating code for
1250 Symbol *si;
1251 void *string;
1252 size_t sz;
1253 size_t len;
1256 #define STSIZE 16
1257 StringTab stringTab[STSIZE];
1258 size_t stidx;
1260 static Symbol *assertexp_sfilename = NULL;
1261 static char *assertexp_name = NULL;
1262 static Module *assertexp_mn = NULL;
1264 void clearStringTab()
1266 //printf("clearStringTab()\n");
1267 memset(stringTab, 0, sizeof(stringTab));
1268 stidx = 0;
1270 assertexp_sfilename = NULL;
1271 assertexp_name = NULL;
1272 assertexp_mn = NULL;
1275 elem *StringExp::toElem(IRState *irs)
1277 elem *e;
1278 Type *tb= type->toBasetype();
1281 #if 0
1282 printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars());
1283 #endif
1285 if (tb->ty == Tarray)
1287 Symbol *si;
1288 dt_t *dt;
1289 StringTab *st;
1291 #if 0
1292 printf("irs->m = %p\n", irs->m);
1293 printf(" m = %s\n", irs->m->toChars());
1294 printf(" len = %d\n", len);
1295 printf(" sz = %d\n", sz);
1296 #endif
1297 for (size_t i = 0; i < STSIZE; i++)
1299 st = &stringTab[(stidx + i) % STSIZE];
1300 //if (!st->m) continue;
1301 //printf(" st.m = %s\n", st->m->toChars());
1302 //printf(" st.len = %d\n", st->len);
1303 //printf(" st.sz = %d\n", st->sz);
1304 if (st->m == irs->m &&
1305 st->si &&
1306 st->len == len &&
1307 st->sz == sz &&
1308 memcmp(st->string, string, sz * len) == 0)
1310 //printf("use cached value\n");
1311 si = st->si; // use cached value
1312 goto L1;
1316 stidx = (stidx + 1) % STSIZE;
1317 st = &stringTab[stidx];
1319 dt = NULL;
1320 toDt(&dt);
1322 si = symbol_generate(SCstatic,type_fake(TYdarray));
1323 si->Sdt = dt;
1324 si->Sfl = FLdata;
1325 #if ELFOBJ // Burton
1326 si->Sseg = CDATA;
1327 #endif
1328 outdata(si);
1330 st->m = irs->m;
1331 st->si = si;
1332 st->string = string;
1333 st->len = len;
1334 st->sz = sz;
1336 e = el_var(si);
1338 else if (tb->ty == Tsarray)
1340 Symbol *si;
1341 dt_t *dt = NULL;
1343 toDt(&dt);
1344 dtnzeros(&dt, sz); // leave terminating 0
1346 si = symbol_generate(SCstatic,type_allocn(TYarray, tschar));
1347 si->Sdt = dt;
1348 si->Sfl = FLdata;
1350 #if ELFOBJ // Burton
1351 si->Sseg = CDATA;
1352 #endif
1353 outdata(si);
1355 e = el_var(si);
1357 else if (tb->ty == Tpointer)
1359 e = el_calloc();
1360 e->Eoper = OPstring;
1361 #if 1
1362 // Match MEM_PH_FREE for OPstring in ztc\el.c
1363 e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz);
1364 memcpy(e->EV.ss.Vstring, string, (len + 1) * sz);
1365 #else
1366 e->EV.ss.Vstring = (char *)string;
1367 #endif
1368 e->EV.ss.Vstrlen = (len + 1) * sz;
1369 e->Ety = TYnptr;
1371 else
1373 printf("type is %s\n", type->toChars());
1374 assert(0);
1376 el_setLoc(e,loc);
1377 return e;
1380 elem *NewExp::toElem(IRState *irs)
1381 { elem *e;
1382 Type *t;
1383 Type *ectype;
1385 //printf("NewExp::toElem() %s\n", toChars());
1386 t = type->toBasetype();
1387 //printf("\ttype = %s\n", t->toChars());
1388 if (t->ty == Tclass)
1390 Symbol *csym;
1392 t = newtype->toBasetype();
1393 assert(t->ty == Tclass);
1394 TypeClass *tclass = (TypeClass *)(t);
1395 ClassDeclaration *cd = tclass->sym;
1397 /* Things to do:
1398 * 1) ex: call allocator
1399 * 2) ey: set vthis for nested classes
1400 * 3) ez: call constructor
1403 elem *ex = NULL;
1404 elem *ey = NULL;
1405 elem *ez = NULL;
1407 if (allocator || onstack)
1408 { elem *ei;
1409 Symbol *si;
1411 if (onstack)
1413 /* Create an instance of the class on the stack,
1414 * and call it stmp.
1415 * Set ex to be the &stmp.
1417 Symbol *s = symbol_calloc(tclass->sym->toChars());
1418 s->Sclass = SCstruct;
1419 s->Sstruct = struct_calloc();
1420 s->Sstruct->Sflags |= 0;
1421 s->Sstruct->Salignsize = tclass->sym->alignsize;
1422 s->Sstruct->Sstructalign = tclass->sym->structalign;
1423 s->Sstruct->Sstructsize = tclass->sym->structsize;
1425 ::type *tc = type_alloc(TYstruct);
1426 tc->Ttag = (Classsym *)s; // structure tag name
1427 tc->Tcount++;
1428 s->Stype = tc;
1430 Symbol *stmp = symbol_genauto(tc);
1431 ex = el_ptr(stmp);
1433 else
1435 ex = el_var(allocator->toSymbol());
1436 ex = callfunc(loc, irs, 1, type, ex, allocator->type,
1437 allocator, allocator->type, NULL, newargs);
1440 si = tclass->sym->toInitializer();
1441 ei = el_var(si);
1443 if (cd->isNested())
1445 ey = el_same(&ex);
1446 ez = el_copytree(ey);
1448 else if (member)
1449 ez = el_same(&ex);
1451 ex = el_una(OPind, TYstruct, ex);
1452 ex = el_bin(OPstreq, TYnptr, ex, ei);
1453 ex->Enumbytes = cd->size(loc);
1454 ex = el_una(OPaddr, TYnptr, ex);
1455 ectype = tclass;
1457 else
1459 csym = cd->toSymbol();
1460 ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym));
1461 ectype = NULL;
1463 if (cd->isNested())
1465 ey = el_same(&ex);
1466 ez = el_copytree(ey);
1468 else if (member)
1469 ez = el_same(&ex);
1470 //elem_print(ex);
1471 //elem_print(ey);
1472 //elem_print(ez);
1475 if (thisexp)
1476 { ClassDeclaration *cdthis = thisexp->type->isClassHandle();
1477 assert(cdthis);
1478 //printf("cd = %s\n", cd->toChars());
1479 //printf("cdthis = %s\n", cdthis->toChars());
1480 assert(cd->isNested());
1481 int offset = 0;
1482 Dsymbol *cdp = cd->toParent2(); // class we're nested in
1483 elem *ethis;
1485 //printf("member = %p\n", member);
1486 //printf("cdp = %s\n", cdp->toChars());
1487 //printf("cdthis = %s\n", cdthis->toChars());
1488 if (cdp != cdthis)
1489 { int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset);
1490 assert(i);
1492 ethis = thisexp->toElem(irs);
1493 if (offset)
1494 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset));
1496 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
1497 ey = el_una(OPind, TYnptr, ey);
1498 ey = el_bin(OPeq, TYnptr, ey, ethis);
1500 //printf("ex: "); elem_print(ex);
1501 //printf("ey: "); elem_print(ey);
1502 //printf("ez: "); elem_print(ez);
1504 else if (cd->isNested())
1505 { /* Initialize cd->vthis:
1506 * *(ey + cd.vthis.offset) = this;
1508 elem *ethis;
1509 FuncDeclaration *thisfd = irs->getFunc();
1510 int offset = 0;
1511 Dsymbol *cdp = cd->toParent2(); // class/func we're nested in
1513 if (cdp == thisfd)
1514 { /* Class we're new'ing is a local class in this function:
1515 * void thisfd() { class cd { } }
1517 if (irs->sclosure)
1518 ethis = el_var(irs->sclosure);
1519 else if (irs->sthis)
1521 #if V2
1522 if (thisfd->closureVars.dim)
1523 #else
1524 if (thisfd->nestedFrameRef)
1525 #endif
1526 ethis = el_ptr(irs->sthis);
1527 else
1528 ethis = el_var(irs->sthis);
1530 else
1532 ethis = el_long(TYnptr, 0);
1533 #if V2
1534 if (thisfd->closureVars.dim)
1535 #else
1536 if (thisfd->nestedFrameRef)
1537 #endif
1538 ethis->Eoper = OPframeptr;
1541 else if (thisfd->vthis &&
1542 (cdp == thisfd->toParent2() ||
1543 (cdp->isClassDeclaration() &&
1544 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset)
1548 { /* Class we're new'ing is at the same level as thisfd
1550 assert(offset == 0); // BUG: should handle this case
1551 ethis = el_var(irs->sthis);
1553 else
1555 ethis = getEthis(loc, irs, cd->toParent2());
1556 ethis = el_una(OPaddr, TYnptr, ethis);
1559 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
1560 ey = el_una(OPind, TYnptr, ey);
1561 ey = el_bin(OPeq, TYnptr, ey, ethis);
1565 if (member)
1566 // Call constructor
1567 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
1569 e = el_combine(ex, ey);
1570 e = el_combine(e, ez);
1572 else if (t->ty == Tarray)
1574 TypeDArray *tda = (TypeDArray *)(t);
1576 assert(arguments && arguments->dim >= 1);
1577 if (arguments->dim == 1)
1578 { // Single dimension array allocations
1579 Expression *arg = (Expression *)arguments->data[0]; // gives array length
1580 e = arg->toElem(irs);
1581 d_uns64 elemsize = tda->next->size();
1583 // call _d_newT(ti, arg)
1584 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1585 int rtl = tda->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1586 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1588 else
1589 { // Multidimensional array allocations
1590 e = el_long(TYint, arguments->dim);
1591 for (size_t i = 0; i < arguments->dim; i++)
1593 Expression *arg = (Expression *)arguments->data[i]; // gives array length
1594 e = el_param(arg->toElem(irs), e);
1595 assert(t->ty == Tarray);
1596 t = t->nextOf();
1597 assert(t);
1600 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1602 int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
1603 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1606 else if (t->ty == Tpointer)
1608 TypePointer *tp = (TypePointer *)t;
1609 d_uns64 elemsize = tp->next->size();
1610 Expression *di = tp->next->defaultInit();
1611 d_uns64 disize = di->type->size();
1613 // call _d_newarrayT(ti, 1)
1614 e = el_long(TYsize_t, 1);
1615 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1617 int rtl = tp->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1618 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1620 // The new functions return an array, so convert to a pointer
1621 // e -> (unsigned)(e >> 32)
1622 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
1623 e = el_una(OP64_32, t->totym(), e);
1625 else
1627 assert(0);
1630 el_setLoc(e,loc);
1631 return e;
1634 //////////////////////////// Unary ///////////////////////////////
1636 /***************************************
1639 elem *NegExp::toElem(IRState *irs)
1641 elem *e = el_una(OPneg, type->totym(), e1->toElem(irs));
1642 el_setLoc(e,loc);
1643 return e;
1646 /***************************************
1649 elem *ComExp::toElem(IRState *irs)
1650 { elem *e;
1652 elem *e1 = this->e1->toElem(irs);
1653 tym_t ty = type->totym();
1654 if (this->e1->type->toBasetype()->ty == Tbool)
1655 e = el_bin(OPxor, ty, e1, el_long(ty, 1));
1656 else
1657 e = el_una(OPcom,ty,e1);
1658 el_setLoc(e,loc);
1659 return e;
1662 /***************************************
1665 elem *NotExp::toElem(IRState *irs)
1667 elem *e = el_una(OPnot, type->totym(), e1->toElem(irs));
1668 el_setLoc(e,loc);
1669 return e;
1673 /***************************************
1676 elem *HaltExp::toElem(IRState *irs)
1677 { elem *e;
1679 e = el_calloc();
1680 e->Ety = TYvoid;
1681 e->Eoper = OPhalt;
1682 el_setLoc(e,loc);
1683 return e;
1686 /********************************************
1689 elem *AssertExp::toElem(IRState *irs)
1690 { elem *e;
1691 elem *ea;
1692 Type *t1 = e1->type->toBasetype();
1694 //printf("AssertExp::toElem() %s\n", toChars());
1695 if (global.params.useAssert)
1697 e = e1->toElem(irs);
1699 InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1;
1701 // If e1 is a class object, call the class invariant on it
1702 if (global.params.useInvariants && t1->ty == Tclass &&
1703 !((TypeClass *)t1)->sym->isInterfaceDeclaration())
1705 #if TARGET_LINUX
1706 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
1707 #else
1708 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
1709 #endif
1711 // If e1 is a struct object, call the struct invariant on it
1712 else if (global.params.useInvariants &&
1713 t1->ty == Tpointer &&
1714 t1->nextOf()->ty == Tstruct &&
1715 (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL)
1717 e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL);
1719 else
1721 // Construct: (e1 || ModuleAssert(line))
1722 Symbol *sassert;
1723 Module *m = irs->blx->module;
1724 char *mname = m->srcfile->toChars();
1726 //printf("filename = '%s'\n", loc.filename);
1727 //printf("module = '%s'\n", m->srcfile->toChars());
1729 /* If the source file name has changed, probably due
1730 * to a #line directive.
1732 if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
1733 { elem *efilename;
1735 /* Cache values.
1737 //static Symbol *assertexp_sfilename = NULL;
1738 //static char *assertexp_name = NULL;
1739 //static Module *assertexp_mn = NULL;
1741 if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m)
1743 dt_t *dt = NULL;
1744 char *id;
1745 int len;
1747 id = loc.filename;
1748 len = strlen(id);
1749 dtdword(&dt, len);
1750 dtabytes(&dt,TYnptr, 0, len + 1, id);
1752 assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
1753 assertexp_sfilename->Sdt = dt;
1754 assertexp_sfilename->Sfl = FLdata;
1755 #if ELFOBJ
1756 assertexp_sfilename->Sseg = CDATA;
1757 #endif
1758 outdata(assertexp_sfilename);
1760 assertexp_mn = m;
1761 assertexp_name = id;
1764 efilename = el_var(assertexp_sfilename);
1766 if (msg)
1767 { elem *emsg = msg->toElem(irs);
1768 ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]);
1769 ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
1771 else
1773 ea = el_var(rtlsym[RTLSYM_DASSERT]);
1774 ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
1777 else
1779 sassert = m->toModuleAssert();
1780 ea = el_bin(OPcall,TYvoid,el_var(sassert),
1781 el_long(TYint, loc.linnum));
1783 e = el_bin(OPoror,TYvoid,e,ea);
1786 else
1787 { // BUG: should replace assert(0); with a HLT instruction
1788 e = el_long(TYint, 0);
1790 el_setLoc(e,loc);
1791 return e;
1794 elem *PostExp::toElem(IRState *irs)
1795 { elem *e;
1796 elem *einc;
1798 e = e1->toElem(irs);
1799 einc = e2->toElem(irs);
1800 e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
1801 e->Ety,e,einc);
1802 el_setLoc(e,loc);
1803 return e;
1806 //////////////////////////// Binary ///////////////////////////////
1808 /********************************************
1811 elem *BinExp::toElemBin(IRState *irs,int op)
1813 //printf("toElemBin() '%s'\n", toChars());
1815 tym_t tym = type->totym();
1817 elem *el = e1->toElem(irs);
1818 elem *er = e2->toElem(irs);
1819 elem *e = el_bin(op,tym,el,er);
1820 el_setLoc(e,loc);
1821 return e;
1825 /***************************************
1828 elem *AddExp::toElem(IRState *irs)
1829 { elem *e;
1830 Type *tb1 = e1->type->toBasetype();
1831 Type *tb2 = e2->type->toBasetype();
1833 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1834 (tb2->ty == Tarray || tb2->ty == Tsarray)
1837 error("Array operations not implemented");
1839 else
1840 e = toElemBin(irs,OPadd);
1841 return e;
1844 /***************************************
1847 elem *MinExp::toElem(IRState *irs)
1849 return toElemBin(irs,OPmin);
1852 /***************************************
1855 elem *CatExp::toElem(IRState *irs)
1856 { elem *e;
1858 #if 0
1859 printf("CatExp::toElem()\n");
1860 print();
1861 #endif
1863 Type *tb1 = e1->type->toBasetype();
1864 Type *tb2 = e2->type->toBasetype();
1865 Type *tn;
1867 #if 0
1868 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1869 (tb2->ty == Tarray || tb2->ty == Tsarray)
1871 #endif
1873 Type *ta = tb1->nextOf() ? e1->type : e2->type;
1874 tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf();
1876 if (e1->op == TOKcat)
1878 elem *ep;
1879 CatExp *ce = this;
1880 int n = 2;
1882 ep = eval_Darray(irs, ce->e2);
1885 n++;
1886 ce = (CatExp *)ce->e1;
1887 ep = el_param(ep, eval_Darray(irs, ce->e2));
1888 } while (ce->e1->op == TOKcat);
1889 ep = el_param(ep, eval_Darray(irs, ce->e1));
1890 #if 1
1891 ep = el_params(
1893 el_long(TYint, n),
1894 ta->getTypeInfo(NULL)->toElem(irs),
1895 NULL);
1896 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep);
1897 #else
1898 ep = el_params(
1900 el_long(TYint, n),
1901 el_long(TYint, tn->size()),
1902 NULL);
1903 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep);
1904 #endif
1906 else
1908 elem *e1;
1909 elem *e2;
1910 elem *ep;
1912 e1 = eval_Darray(irs, this->e1);
1913 e2 = eval_Darray(irs, this->e2);
1914 #if 1
1915 ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL);
1916 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep);
1917 #else
1918 ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL);
1919 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep);
1920 #endif
1922 el_setLoc(e,loc);
1924 #if 0
1925 else if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1926 e2->type->equals(tb1->next))
1928 error("array cat with element not implemented");
1929 e = el_long(TYint, 0);
1931 else
1932 assert(0);
1933 #endif
1934 return e;
1937 /***************************************
1940 elem *MulExp::toElem(IRState *irs)
1942 return toElemBin(irs,OPmul);
1945 /************************************
1948 elem *DivExp::toElem(IRState *irs)
1950 return toElemBin(irs,OPdiv);
1953 /***************************************
1956 elem *ModExp::toElem(IRState *irs)
1958 elem *e;
1959 elem *e1;
1960 elem *e2;
1961 tym_t tym;
1963 tym = type->totym();
1965 e1 = this->e1->toElem(irs);
1966 e2 = this->e2->toElem(irs);
1968 #if 0 // Now inlined
1969 if (this->e1->type->isfloating())
1970 { elem *ep;
1972 switch (this->e1->type->ty)
1974 case Tfloat32:
1975 case Timaginary32:
1976 e1 = el_una(OPf_d, TYdouble, e1);
1977 e2 = el_una(OPf_d, TYdouble, e2);
1978 case Tfloat64:
1979 case Timaginary64:
1980 e1 = el_una(OPd_ld, TYldouble, e1);
1981 e2 = el_una(OPd_ld, TYldouble, e2);
1982 break;
1983 case Tfloat80:
1984 case Timaginary80:
1985 break;
1986 default:
1987 assert(0);
1988 break;
1990 ep = el_param(e2,e1);
1991 e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep);
1993 else
1994 #endif
1995 e = el_bin(OPmod,tym,e1,e2);
1996 el_setLoc(e,loc);
1997 return e;
2000 /***************************************
2003 elem *CmpExp::toElem(IRState *irs)
2005 elem *e;
2006 enum OPER eop;
2007 Type *t1 = e1->type->toBasetype();
2008 Type *t2 = e2->type->toBasetype();
2010 switch (op)
2012 case TOKlt: eop = OPlt; break;
2013 case TOKgt: eop = OPgt; break;
2014 case TOKle: eop = OPle; break;
2015 case TOKge: eop = OPge; break;
2016 case TOKequal: eop = OPeqeq; break;
2017 case TOKnotequal: eop = OPne; break;
2019 // NCEG floating point compares
2020 case TOKunord: eop = OPunord; break;
2021 case TOKlg: eop = OPlg; break;
2022 case TOKleg: eop = OPleg; break;
2023 case TOKule: eop = OPule; break;
2024 case TOKul: eop = OPul; break;
2025 case TOKuge: eop = OPuge; break;
2026 case TOKug: eop = OPug; break;
2027 case TOKue: eop = OPue; break;
2028 default:
2029 dump(0);
2030 assert(0);
2032 if (!t1->isfloating())
2034 // Convert from floating point compare to equivalent
2035 // integral compare
2036 eop = (enum OPER)rel_integral(eop);
2038 if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass)
2040 #if 1
2041 assert(0);
2042 #else
2043 elem *ec1;
2044 elem *ec2;
2046 ec1 = e1->toElem(irs);
2047 ec2 = e2->toElem(irs);
2048 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2));
2049 e = el_bin(eop, TYint, e, el_long(TYint, 0));
2050 #endif
2052 else if ((int)eop > 1 &&
2053 (t1->ty == Tarray || t1->ty == Tsarray) &&
2054 (t2->ty == Tarray || t2->ty == Tsarray))
2056 elem *ea1;
2057 elem *ea2;
2058 elem *ep;
2059 Type *telement = t1->nextOf()->toBasetype();
2060 int rtlfunc;
2062 ea1 = e1->toElem(irs);
2063 ea1 = array_toDarray(t1, ea1);
2064 ea2 = e2->toElem(irs);
2065 ea2 = array_toDarray(t2, ea2);
2067 ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
2068 rtlfunc = RTLSYM_ARRAYCMP;
2069 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
2070 e = el_bin(eop, TYint, e, el_long(TYint, 0));
2071 el_setLoc(e,loc);
2073 else
2075 if ((int)eop <= 1)
2077 /* The result is determinate, create:
2078 * (e1 , e2) , eop
2080 e = toElemBin(irs,OPcomma);
2081 e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop));
2083 else
2084 e = toElemBin(irs,eop);
2086 return e;
2089 elem *EqualExp::toElem(IRState *irs)
2091 //printf("EqualExp::toElem() %s\n", toChars());
2093 elem *e;
2094 enum OPER eop;
2095 Type *t1 = e1->type->toBasetype();
2096 Type *t2 = e2->type->toBasetype();
2098 switch (op)
2100 case TOKequal: eop = OPeqeq; break;
2101 case TOKnotequal: eop = OPne; break;
2102 default:
2103 dump(0);
2104 assert(0);
2107 //printf("EqualExp::toElem()\n");
2108 if (t1->ty == Tstruct)
2109 { // Do bit compare of struct's
2110 elem *es1;
2111 elem *es2;
2112 elem *ecount;
2114 es1 = e1->toElem(irs);
2115 es2 = e2->toElem(irs);
2116 #if 1
2117 es1 = addressElem(es1, t1);
2118 es2 = addressElem(es2, t2);
2119 #else
2120 es1 = el_una(OPaddr, TYnptr, es1);
2121 es2 = el_una(OPaddr, TYnptr, es2);
2122 #endif
2123 e = el_param(es1, es2);
2124 ecount = el_long(TYint, t1->size());
2125 e = el_bin(OPmemcmp, TYint, e, ecount);
2126 e = el_bin(eop, TYint, e, el_long(TYint, 0));
2127 el_setLoc(e,loc);
2129 #if 0
2130 else if (t1->ty == Tclass && t2->ty == Tclass)
2132 elem *ec1;
2133 elem *ec2;
2135 ec1 = e1->toElem(irs);
2136 ec2 = e2->toElem(irs);
2137 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
2139 #endif
2140 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
2141 (t2->ty == Tarray || t2->ty == Tsarray))
2143 elem *ea1;
2144 elem *ea2;
2145 elem *ep;
2146 Type *telement = t1->nextOf()->toBasetype();
2147 int rtlfunc;
2149 ea1 = e1->toElem(irs);
2150 ea1 = array_toDarray(t1, ea1);
2151 ea2 = e2->toElem(irs);
2152 ea2 = array_toDarray(t2, ea2);
2154 ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
2155 rtlfunc = RTLSYM_ARRAYEQ;
2156 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
2157 if (op == TOKnotequal)
2158 e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
2159 el_setLoc(e,loc);
2161 else
2162 e = toElemBin(irs, eop);
2163 return e;
2166 elem *IdentityExp::toElem(IRState *irs)
2168 elem *e;
2169 enum OPER eop;
2170 Type *t1 = e1->type->toBasetype();
2171 Type *t2 = e2->type->toBasetype();
2173 switch (op)
2175 case TOKidentity: eop = OPeqeq; break;
2176 case TOKnotidentity: eop = OPne; break;
2177 default:
2178 dump(0);
2179 assert(0);
2182 //printf("IdentityExp::toElem() %s\n", toChars());
2184 if (t1->ty == Tstruct)
2185 { // Do bit compare of struct's
2186 elem *es1;
2187 elem *es2;
2188 elem *ecount;
2190 es1 = e1->toElem(irs);
2191 es1 = addressElem(es1, e1->type);
2192 //es1 = el_una(OPaddr, TYnptr, es1);
2193 es2 = e2->toElem(irs);
2194 es2 = addressElem(es2, e2->type);
2195 //es2 = el_una(OPaddr, TYnptr, es2);
2196 e = el_param(es1, es2);
2197 ecount = el_long(TYint, t1->size());
2198 e = el_bin(OPmemcmp, TYint, e, ecount);
2199 e = el_bin(eop, TYint, e, el_long(TYint, 0));
2200 el_setLoc(e,loc);
2202 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
2203 (t2->ty == Tarray || t2->ty == Tsarray))
2205 elem *ea1;
2206 elem *ea2;
2208 ea1 = e1->toElem(irs);
2209 ea1 = array_toDarray(t1, ea1);
2210 ea2 = e2->toElem(irs);
2211 ea2 = array_toDarray(t2, ea2);
2213 e = el_bin(eop, type->totym(), ea1, ea2);
2214 el_setLoc(e,loc);
2216 else
2217 e = toElemBin(irs, eop);
2219 return e;
2223 /***************************************
2226 elem *InExp::toElem(IRState *irs)
2227 { elem *e;
2228 elem *key = e1->toElem(irs);
2229 elem *aa = e2->toElem(irs);
2230 elem *ep;
2231 elem *keyti;
2232 TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
2235 // set to:
2236 // aaIn(aa, keyti, key);
2238 if (key->Ety == TYstruct)
2240 key = el_una(OPstrpar, TYstruct, key);
2241 key->Enumbytes = key->E1->Enumbytes;
2242 assert(key->Enumbytes);
2245 Symbol *s = taa->aaGetSymbol("In", 0);
2246 keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
2247 ep = el_params(key, keyti, aa, NULL);
2248 e = el_bin(OPcall, type->totym(), el_var(s), ep);
2250 el_setLoc(e,loc);
2251 return e;
2254 /***************************************
2257 elem *RemoveExp::toElem(IRState *irs)
2258 { elem *e;
2259 Type *tb = e1->type->toBasetype();
2260 assert(tb->ty == Taarray);
2261 TypeAArray *taa = (TypeAArray *)tb;
2262 elem *ea = e1->toElem(irs);
2263 elem *ekey = e2->toElem(irs);
2264 elem *ep;
2265 elem *keyti;
2267 if (ekey->Ety == TYstruct)
2269 ekey = el_una(OPstrpar, TYstruct, ekey);
2270 ekey->Enumbytes = ekey->E1->Enumbytes;
2271 assert(ekey->Enumbytes);
2274 Symbol *s = taa->aaGetSymbol("Del", 0);
2275 keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
2276 ep = el_params(ekey, keyti, ea, NULL);
2277 e = el_bin(OPcall, TYnptr, el_var(s), ep);
2279 el_setLoc(e,loc);
2280 return e;
2283 /***************************************
2286 elem *AssignExp::toElem(IRState *irs)
2287 { elem *e;
2288 IndexExp *ae;
2289 int r;
2290 Type *t1b;
2292 //printf("AssignExp::toElem('%s')\n", toChars());
2293 t1b = e1->type->toBasetype();
2295 // Look for array.length = n
2296 if (e1->op == TOKarraylength)
2298 // Generate:
2299 // _d_arraysetlength(e2, sizeelem, &ale->e1);
2301 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
2302 elem *p1;
2303 elem *p2;
2304 elem *p3;
2305 elem *ep;
2306 Type *t1;
2308 p1 = e2->toElem(irs);
2309 p3 = ale->e1->toElem(irs);
2310 p3 = addressElem(p3, NULL);
2311 t1 = ale->e1->type->toBasetype();
2313 #if 1
2314 // call _d_arraysetlengthT(ti, e2, &ale->e1);
2315 p2 = t1->getTypeInfo(NULL)->toElem(irs);
2316 ep = el_params(p3, p1, p2, NULL); // c function
2317 r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
2318 #else
2319 if (t1->next->isZeroInit())
2320 { p2 = t1->getTypeInfo(NULL)->toElem(irs);
2321 ep = el_params(p3, p1, p2, NULL); // c function
2322 r = RTLSYM_ARRAYSETLENGTHT;
2324 else
2326 p2 = el_long(TYint, t1->next->size());
2327 ep = el_params(p3, p2, p1, NULL); // c function
2328 Expression *init = t1->next->defaultInit();
2329 ep = el_param(el_long(TYint, init->type->size()), ep);
2330 elem *ei = init->toElem(irs);
2331 ep = el_param(ei, ep);
2332 r = RTLSYM_ARRAYSETLENGTH3;
2334 #endif
2336 e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
2337 el_setLoc(e, loc);
2338 return e;
2341 // Look for array[]=n
2342 if (e1->op == TOKslice)
2344 SliceExp *are = (SliceExp *)(e1);
2345 Type *t1 = t1b;
2346 Type *t2 = e2->type->toBasetype();
2348 // which we do if the 'next' types match
2349 if (ismemset)
2350 { // Do a memset for array[]=v
2351 //printf("Lpair %s\n", toChars());
2352 SliceExp *are = (SliceExp *)e1;
2353 elem *elwr;
2354 elem *eupr;
2355 elem *n1;
2356 elem *evalue;
2357 elem *enbytes;
2358 elem *elength;
2359 elem *einit;
2360 integer_t value;
2361 Type *ta = are->e1->type->toBasetype();
2362 Type *tb = ta->nextOf()->toBasetype();
2363 int sz = tb->size();
2364 tym_t tym = type->totym();
2366 n1 = are->e1->toElem(irs);
2367 elwr = are->lwr ? are->lwr->toElem(irs) : NULL;
2368 eupr = are->upr ? are->upr->toElem(irs) : NULL;
2370 elem *n1x = n1;
2372 // Look for array[]=n
2373 if (ta->ty == Tsarray)
2375 TypeSArray *ts;
2377 ts = (TypeSArray *) ta;
2378 n1 = array_toPtr(ta, n1);
2379 enbytes = ts->dim->toElem(irs);
2380 n1x = n1;
2381 n1 = el_same(&n1x);
2382 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2384 else if (ta->ty == Tarray)
2386 n1 = el_same(&n1x);
2387 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2388 enbytes = el_copytree(n1);
2389 n1 = array_toPtr(ta, n1);
2390 enbytes = el_una(OP64_32, TYint, enbytes);
2392 else if (ta->ty == Tpointer)
2394 n1 = el_same(&n1x);
2395 enbytes = el_long(TYint, -1); // largest possible index
2396 einit = NULL;
2399 // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr
2400 elem *elwrx = elwr;
2401 if (elwr) elwr = el_same(&elwrx);
2402 elem *euprx = eupr;
2403 if (eupr) eupr = el_same(&euprx);
2405 #if 0
2406 printf("sz = %d\n", sz);
2407 printf("n1x\n");
2408 elem_print(n1x);
2409 printf("einit\n");
2410 elem_print(einit);
2411 printf("elwrx\n");
2412 elem_print(elwrx);
2413 printf("euprx\n");
2414 elem_print(euprx);
2415 printf("n1\n");
2416 elem_print(n1);
2417 printf("elwr\n");
2418 elem_print(elwr);
2419 printf("eupr\n");
2420 elem_print(eupr);
2421 printf("enbytes\n");
2422 elem_print(enbytes);
2423 #endif
2424 einit = el_combine(n1x, einit);
2425 einit = el_combine(einit, elwrx);
2426 einit = el_combine(einit, euprx);
2428 evalue = this->e2->toElem(irs);
2430 #if 0
2431 printf("n1\n");
2432 elem_print(n1);
2433 printf("enbytes\n");
2434 elem_print(enbytes);
2435 #endif
2437 if (global.params.useArrayBounds && eupr && ta->ty != Tpointer)
2439 elem *c1;
2440 elem *c2;
2441 elem *ea;
2442 elem *eb;
2443 elem *enbytesx;
2445 assert(elwr);
2446 enbytesx = enbytes;
2447 enbytes = el_same(&enbytesx);
2448 c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx);
2449 c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr));
2450 c1 = el_bin(OPandand, TYint, c1, c2);
2452 // Construct: (c1 || ModuleArray(line))
2453 Symbol *sassert;
2455 sassert = irs->blx->module->toModuleArray();
2456 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
2457 eb = el_bin(OPoror,TYvoid,c1,ea);
2458 einit = el_combine(einit, eb);
2461 if (elwr)
2462 { elem *elwr2;
2464 el_free(enbytes);
2465 elwr2 = el_copytree(elwr);
2466 elwr2 = el_bin(OPmul, TYint, elwr2, el_long(TYint, sz));
2467 n1 = el_bin(OPadd, TYnptr, n1, elwr2);
2468 enbytes = el_bin(OPmin, TYint, eupr, elwr);
2469 elength = el_copytree(enbytes);
2471 else
2472 elength = el_copytree(enbytes);
2473 e = setArray(n1, enbytes, tb, evalue, irs, op);
2474 Lpair:
2475 e = el_pair(TYullong, elength, e);
2476 Lret2:
2477 e = el_combine(einit, e);
2478 //elem_print(e);
2479 goto Lret;
2481 else
2483 /* It's array1[]=array2[]
2484 * which is a memcpy
2486 elem *eto;
2487 elem *efrom;
2488 elem *esize;
2489 elem *ep;
2491 eto = e1->toElem(irs);
2492 efrom = e2->toElem(irs);
2494 unsigned size = t1->nextOf()->size();
2495 esize = el_long(TYint, size);
2497 /* Determine if we need to do postblit
2499 int postblit = 0;
2500 Type *t = t1;
2502 t = t->nextOf()->toBasetype();
2503 while (t->ty == Tsarray);
2504 if (t->ty == Tstruct)
2505 { StructDeclaration *sd = ((TypeStruct *)t)->sym;
2506 if (sd->postblit)
2507 postblit = 1;
2510 assert(e2->type->ty != Tpointer);
2512 if (!postblit && !global.params.useArrayBounds)
2513 { elem *epto;
2514 elem *epfr;
2515 elem *elen;
2516 elem *ex;
2518 ex = el_same(&eto);
2520 // Determine if elen is a constant
2521 if (eto->Eoper == OPpair &&
2522 eto->E1->Eoper == OPconst)
2524 elen = el_copytree(eto->E1);
2526 else
2528 // It's not a constant, so pull it from the dynamic array
2529 elen = el_una(OP64_32, TYint, el_copytree(ex));
2532 esize = el_bin(OPmul, TYint, elen, esize);
2533 epto = array_toPtr(e1->type, ex);
2534 epfr = array_toPtr(e2->type, efrom);
2535 e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize));
2536 e = el_pair(eto->Ety, el_copytree(elen), e);
2537 e = el_combine(eto, e);
2539 else if (postblit && op != TOKblit)
2541 /* Generate:
2542 * _d_arrayassign(ti, efrom, eto)
2543 * or:
2544 * _d_arrayctor(ti, efrom, eto)
2546 el_free(esize);
2547 Expression *ti = t1->nextOf()->toBasetype()->getTypeInfo(NULL);
2548 ep = el_params(eto, efrom, ti->toElem(irs), NULL);
2549 int rtl = (op == TOKconstruct) ? RTLSYM_ARRAYCTOR : RTLSYM_ARRAYASSIGN;
2550 e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep);
2552 else
2554 // Generate:
2555 // _d_arraycopy(eto, efrom, esize)
2557 ep = el_params(eto, efrom, esize, NULL);
2558 e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep);
2560 el_setLoc(e, loc);
2561 return e;
2565 if (e1->op == TOKindex)
2567 elem *eb;
2568 elem *ei;
2569 elem *ev;
2570 TY ty;
2571 Type *ta;
2573 ae = (IndexExp *)(e1);
2574 ta = ae->e1->type->toBasetype();
2575 ty = ta->ty;
2577 #if 1
2578 /* This will work if we can distinguish an assignment from
2579 * an initialization of the lvalue. It'll work if the latter.
2580 * If the former, because of aliasing of the return value with
2581 * function arguments, it'll fail.
2583 if (op == TOKconstruct && e2->op == TOKcall)
2584 { CallExp *ce = (CallExp *)e2;
2586 TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype();
2587 if (tf->ty == Tfunction && tf->retStyle() == RETstack)
2589 elem *ehidden = e1->toElem(irs);
2590 ehidden = el_una(OPaddr, TYnptr, ehidden);
2591 assert(!irs->ehidden);
2592 irs->ehidden = ehidden;
2593 e = e2->toElem(irs);
2594 goto Lret;
2597 #endif
2598 if (t1b->ty == Tstruct)
2600 if (e2->op == TOKint64)
2601 { /* Implement:
2602 * (struct = 0)
2603 * with:
2604 * memset(&struct, 0, struct.sizeof)
2606 elem *el = e1->toElem(irs);
2607 elem *enbytes = el_long(TYint, e1->type->size());
2608 elem *evalue = el_long(TYint, 0);
2610 el = el_una(OPaddr, TYnptr, el);
2611 e = el_param(enbytes, evalue);
2612 e = el_bin(OPmemset,TYnptr,el,e);
2613 el_setLoc(e, loc);
2614 //e = el_una(OPind, TYstruct, e);
2616 else
2618 elem *e1;
2619 elem *e2;
2620 tym_t tym;
2622 //printf("toElemBin() '%s'\n", toChars());
2624 tym = type->totym();
2626 e1 = this->e1->toElem(irs);
2627 elem *ex = e1;
2628 if (e1->Eoper == OPind)
2629 ex = e1->E1;
2630 if (this->e2->op == TOKstructliteral &&
2631 ex->Eoper == OPvar && ex->EV.sp.Voffset == 0)
2632 { StructLiteralExp *se = (StructLiteralExp *)this->e2;
2634 Symbol *symSave = se->sym;
2635 size_t soffsetSave = se->soffset;
2636 int fillHolesSave = se->fillHoles;
2638 se->sym = ex->EV.sp.Vsym;
2639 se->soffset = 0;
2640 se->fillHoles = (op == TOKconstruct || op == TOKblit) ? 1 : 0;
2642 el_free(e1);
2643 e = this->e2->toElem(irs);
2645 se->sym = symSave;
2646 se->soffset = soffsetSave;
2647 se->fillHoles = fillHolesSave;
2649 else
2651 e2 = this->e2->toElem(irs);
2652 e = el_bin(OPstreq,tym,e1,e2);
2653 e->Enumbytes = this->e1->type->size();
2655 goto Lret;
2658 else
2659 e = toElemBin(irs,OPeq);
2660 return e;
2662 Lret:
2663 el_setLoc(e,loc);
2664 return e;
2667 /***************************************
2670 elem *AddAssignExp::toElem(IRState *irs)
2672 //printf("AddAssignExp::toElem() %s\n", toChars());
2673 elem *e;
2674 Type *tb1 = e1->type->toBasetype();
2675 Type *tb2 = e2->type->toBasetype();
2677 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
2678 (tb2->ty == Tarray || tb2->ty == Tsarray)
2681 error("Array operations not implemented");
2683 else
2684 e = toElemBin(irs,OPaddass);
2685 return e;
2689 /***************************************
2692 elem *MinAssignExp::toElem(IRState *irs)
2694 return toElemBin(irs,OPminass);
2697 /***************************************
2700 elem *CatAssignExp::toElem(IRState *irs)
2702 //printf("CatAssignExp::toElem('%s')\n", toChars());
2703 elem *e;
2704 Type *tb1 = e1->type->toBasetype();
2705 Type *tb2 = e2->type->toBasetype();
2707 if (tb1->ty == Tarray || tb2->ty == Tsarray)
2708 { elem *e1;
2709 elem *e2;
2710 elem *ep;
2712 e1 = this->e1->toElem(irs);
2713 e1 = el_una(OPaddr, TYnptr, e1);
2715 e2 = this->e2->toElem(irs);
2716 if (e2->Ety == TYstruct)
2718 e2 = el_una(OPstrpar, TYstruct, e2);
2719 e2->Enumbytes = e2->E1->Enumbytes;
2720 assert(e2->Enumbytes);
2723 Type *tb1n = tb1->nextOf()->toBasetype();
2724 if ((tb2->ty == Tarray || tb2->ty == Tsarray) &&
2725 tb1n->equals(tb2->nextOf()->toBasetype()))
2726 { // Append array
2727 #if 1
2728 ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
2729 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep);
2730 #else
2731 ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL);
2732 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep);
2733 #endif
2735 else
2736 { // Append element
2737 #if 1
2738 ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
2739 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep);
2740 #else
2741 ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL);
2742 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep);
2743 #endif
2745 el_setLoc(e,loc);
2747 else
2748 assert(0);
2749 return e;
2753 /***************************************
2756 elem *DivAssignExp::toElem(IRState *irs)
2758 return toElemBin(irs,OPdivass);
2762 /***************************************
2765 elem *ModAssignExp::toElem(IRState *irs)
2767 return toElemBin(irs,OPmodass);
2771 /***************************************
2774 elem *MulAssignExp::toElem(IRState *irs)
2776 return toElemBin(irs,OPmulass);
2780 /***************************************
2783 elem *ShlAssignExp::toElem(IRState *irs)
2784 { elem *e;
2786 e = toElemBin(irs,OPshlass);
2787 return e;
2791 /***************************************
2794 elem *ShrAssignExp::toElem(IRState *irs)
2796 return toElemBin(irs,OPshrass);
2800 /***************************************
2803 elem *UshrAssignExp::toElem(IRState *irs)
2805 elem *eleft = e1->toElem(irs);
2806 eleft->Ety = touns(eleft->Ety);
2807 elem *eright = e2->toElem(irs);
2808 elem *e = el_bin(OPshrass, type->totym(), eleft, eright);
2809 el_setLoc(e, loc);
2810 return e;
2814 /***************************************
2817 elem *AndAssignExp::toElem(IRState *irs)
2819 return toElemBin(irs,OPandass);
2823 /***************************************
2826 elem *OrAssignExp::toElem(IRState *irs)
2828 return toElemBin(irs,OPorass);
2832 /***************************************
2835 elem *XorAssignExp::toElem(IRState *irs)
2837 return toElemBin(irs,OPxorass);
2841 /***************************************
2844 elem *AndAndExp::toElem(IRState *irs)
2846 elem *e = toElemBin(irs,OPandand);
2847 if (global.params.cov && e2->loc.linnum)
2848 e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
2849 return e;
2853 /***************************************
2856 elem *OrOrExp::toElem(IRState *irs)
2858 elem *e = toElemBin(irs,OPoror);
2859 if (global.params.cov && e2->loc.linnum)
2860 e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
2861 return e;
2865 /***************************************
2868 elem *XorExp::toElem(IRState *irs)
2870 return toElemBin(irs,OPxor);
2874 /***************************************
2877 elem *AndExp::toElem(IRState *irs)
2879 return toElemBin(irs,OPand);
2883 /***************************************
2886 elem *OrExp::toElem(IRState *irs)
2888 return toElemBin(irs,OPor);
2892 /***************************************
2895 elem *ShlExp::toElem(IRState *irs)
2897 return toElemBin(irs, OPshl);
2901 /***************************************
2904 elem *ShrExp::toElem(IRState *irs)
2906 return toElemBin(irs,OPshr);
2910 /***************************************
2913 elem *UshrExp::toElem(IRState *irs)
2915 elem *eleft = e1->toElem(irs);
2916 eleft->Ety = touns(eleft->Ety);
2917 elem *eright = e2->toElem(irs);
2918 elem *e = el_bin(OPshr, type->totym(), eleft, eright);
2919 el_setLoc(e, loc);
2920 return e;
2923 /****************************************
2926 elem *CommaExp::toElem(IRState *irs)
2928 assert(e1 && e2);
2929 elem *eleft = e1->toElem(irs);
2930 elem *eright = e2->toElem(irs);
2931 elem *e = el_combine(eleft, eright);
2932 if (e)
2933 el_setLoc(e, loc);
2934 return e;
2938 /***************************************
2941 elem *CondExp::toElem(IRState *irs)
2942 { elem *eleft;
2943 elem *eright;
2945 elem *ec = econd->toElem(irs);
2947 eleft = e1->toElem(irs);
2948 tym_t ty = eleft->Ety;
2949 if (global.params.cov && e1->loc.linnum)
2950 eleft = el_combine(incUsageElem(irs, e1->loc), eleft);
2952 eright = e2->toElem(irs);
2953 if (global.params.cov && e2->loc.linnum)
2954 eright = el_combine(incUsageElem(irs, e2->loc), eright);
2956 elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright));
2957 if (tybasic(ty) == TYstruct)
2958 e->Enumbytes = e1->type->size();
2959 el_setLoc(e, loc);
2960 return e;
2964 /***************************************
2967 elem *TypeDotIdExp::toElem(IRState *irs)
2969 print();
2970 assert(0);
2971 return NULL;
2974 elem *TypeExp::toElem(IRState *irs)
2976 #ifdef DEBUG
2977 printf("TypeExp::toElem()\n");
2978 #endif
2979 error("type %s is not an expression", toChars());
2980 return el_long(TYint, 0);
2983 elem *ScopeExp::toElem(IRState *irs)
2985 error("%s is not an expression", sds->toChars());
2986 return el_long(TYint, 0);
2989 elem *DotVarExp::toElem(IRState *irs)
2991 // *(&e + offset)
2993 //printf("DotVarExp::toElem('%s')\n", toChars());
2995 VarDeclaration *v = var->isVarDeclaration();
2996 if (!v)
2998 error("%s is not a field", var->toChars());
3001 elem *e = e1->toElem(irs);
3002 Type *tb1 = e1->type->toBasetype();
3003 if (tb1->ty != Tclass && tb1->ty != Tpointer)
3004 e = el_una(OPaddr, TYnptr, e);
3005 e = el_bin(OPadd, TYnptr, e, el_long(TYint, v ? v->offset : 0));
3006 e = el_una(OPind, type->totym(), e);
3007 if (tybasic(e->Ety) == TYstruct)
3009 e->Enumbytes = type->size();
3011 el_setLoc(e,loc);
3012 return e;
3015 elem *DelegateExp::toElem(IRState *irs)
3017 elem *e;
3018 elem *ethis;
3019 elem *ep;
3020 Symbol *sfunc;
3021 int directcall = 0;
3023 //printf("DelegateExp::toElem() '%s'\n", toChars());
3024 sfunc = func->toSymbol();
3025 if (func->isNested())
3027 ep = el_ptr(sfunc);
3028 ethis = getEthis(loc, irs, func);
3030 else
3032 ethis = e1->toElem(irs);
3033 if (e1->type->ty != Tclass && e1->type->ty != Tpointer)
3034 ethis = el_una(OPaddr, TYnptr, ethis);
3036 if (e1->op == TOKsuper)
3037 directcall = 1;
3039 if (!func->isThis())
3040 error("delegates are only for non-static functions");
3042 if (!func->isVirtual() ||
3043 directcall ||
3044 func->isFinal())
3046 ep = el_ptr(sfunc);
3048 else
3050 // Get pointer to function out of virtual table
3051 unsigned vindex;
3053 assert(ethis);
3054 ep = el_same(&ethis);
3055 ep = el_una(OPind, TYnptr, ep);
3056 vindex = func->vtblIndex;
3058 // Build *(ep + vindex * 4)
3059 ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4));
3060 ep = el_una(OPind,TYnptr,ep);
3063 // if (func->tintro)
3064 // func->error(loc, "cannot form delegate due to covariant return type");
3066 if (ethis->Eoper == OPcomma)
3068 ethis->E2 = el_pair(TYullong, ethis->E2, ep);
3069 ethis->Ety = TYullong;
3070 e = ethis;
3072 else
3073 e = el_pair(TYullong, ethis, ep);
3074 el_setLoc(e,loc);
3075 return e;
3078 elem *DotTypeExp::toElem(IRState *irs)
3080 // Just a pass-thru to e1
3081 elem *e;
3083 //printf("DotTypeExp::toElem() %s\n", toChars());
3084 e = e1->toElem(irs);
3085 el_setLoc(e,loc);
3086 return e;
3089 elem *CallExp::toElem(IRState *irs)
3091 //printf("CallExp::toElem('%s')\n", toChars());
3092 assert(e1->type);
3093 elem *ec;
3094 int directcall;
3095 FuncDeclaration *fd;
3096 Type *t1 = e1->type->toBasetype();
3097 Type *ectype = t1;
3099 elem *ehidden = irs->ehidden;
3100 irs->ehidden = NULL;
3102 directcall = 0;
3103 fd = NULL;
3104 if (e1->op == TOKdotvar && t1->ty != Tdelegate)
3105 { DotVarExp *dve = (DotVarExp *)e1;
3107 fd = dve->var->isFuncDeclaration();
3108 Expression *ex = dve->e1;
3109 while (1)
3111 switch (ex->op)
3113 case TOKsuper: // super.member() calls directly
3114 case TOKdottype: // type.member() calls directly
3115 directcall = 1;
3116 break;
3118 case TOKcast:
3119 ex = ((CastExp *)ex)->e1;
3120 continue;
3122 default:
3123 //ex->dump(0);
3124 break;
3126 break;
3128 ec = dve->e1->toElem(irs);
3129 ectype = dve->e1->type->toBasetype();
3131 else if (e1->op == TOKvar)
3133 fd = ((VarExp *)e1)->var->isFuncDeclaration();
3135 if (fd && fd->ident == Id::alloca &&
3136 !fd->fbody && fd->linkage == LINKc &&
3137 arguments && arguments->dim == 1)
3138 { Expression *arg = (Expression *)arguments->data[0];
3139 arg = arg->optimize(WANTvalue);
3140 if (arg->isConst() && arg->type->isintegral())
3141 { integer_t sz = arg->toInteger();
3142 if (sz > 0 && sz < 0x40000)
3144 // It's an alloca(sz) of a fixed amount.
3145 // Replace with an array allocated on the stack
3146 // of the same size: char[sz] tmp;
3148 Symbol *stmp;
3149 ::type *t;
3151 assert(!ehidden);
3152 t = type_allocn(TYarray, tschar);
3153 t->Tdim = sz;
3154 stmp = symbol_genauto(t);
3155 ec = el_ptr(stmp);
3156 el_setLoc(ec,loc);
3157 return ec;
3162 ec = e1->toElem(irs);
3164 else
3166 ec = e1->toElem(irs);
3168 ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
3169 el_setLoc(ec,loc);
3170 return ec;
3173 elem *AddrExp::toElem(IRState *irs)
3174 { elem *e;
3175 elem **pe;
3177 //printf("AddrExp::toElem('%s')\n", toChars());
3179 e = e1->toElem(irs);
3180 e = addressElem(e, e1->type);
3182 e->Ety = type->totym();
3183 el_setLoc(e,loc);
3184 return e;
3187 elem *PtrExp::toElem(IRState *irs)
3188 { elem *e;
3190 //printf("PtrExp::toElem() %s\n", toChars());
3191 e = e1->toElem(irs);
3192 e = el_una(OPind,type->totym(),e);
3193 if (tybasic(e->Ety) == TYstruct)
3195 e->Enumbytes = type->size();
3197 el_setLoc(e,loc);
3198 return e;
3201 elem *BoolExp::toElem(IRState *irs)
3202 { elem *e1;
3204 e1 = this->e1->toElem(irs);
3205 return el_una(OPbool,type->totym(),e1);
3208 elem *DeleteExp::toElem(IRState *irs)
3209 { elem *e;
3210 int rtl;
3211 Type *tb;
3213 //printf("DeleteExp::toElem()\n");
3214 if (e1->op == TOKindex)
3216 IndexExp *ae = (IndexExp *)(e1);
3217 tb = ae->e1->type->toBasetype();
3218 if (tb->ty == Taarray)
3220 TypeAArray *taa = (TypeAArray *)tb;
3221 elem *ea = ae->e1->toElem(irs);
3222 elem *ekey = ae->e2->toElem(irs);
3223 elem *ep;
3224 elem *keyti;
3226 if (ekey->Ety == TYstruct)
3228 ekey = el_una(OPstrpar, TYstruct, ekey);
3229 ekey->Enumbytes = ekey->E1->Enumbytes;
3230 assert(ekey->Enumbytes);
3233 Symbol *s = taa->aaGetSymbol("Del", 0);
3234 keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
3235 ep = el_params(ekey, keyti, ea, NULL);
3236 e = el_bin(OPcall, TYnptr, el_var(s), ep);
3237 goto Lret;
3240 //e1->type->print();
3241 e = e1->toElem(irs);
3242 tb = e1->type->toBasetype();
3243 switch (tb->ty)
3245 case Tarray:
3246 { e = addressElem(e, e1->type);
3247 rtl = RTLSYM_DELARRAYT;
3249 /* See if we need to run destructors on the array contents
3251 elem *et = NULL;
3252 Type *tv = tb->nextOf()->toBasetype();
3253 while (tv->ty == Tsarray)
3254 { TypeSArray *ta = (TypeSArray *)tv;
3255 tv = tv->nextOf()->toBasetype();
3257 if (tv->ty == Tstruct)
3258 { TypeStruct *ts = (TypeStruct *)tv;
3259 StructDeclaration *sd = ts->sym;
3260 if (sd->dtor)
3261 et = tb->nextOf()->getTypeInfo(NULL)->toElem(irs);
3263 if (!et) // if no destructors needed
3264 et = el_long(TYnptr, 0); // pass null for TypeInfo
3265 e = el_params(et, e, NULL);
3266 // call _d_delarray_t(e, et);
3267 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
3268 goto Lret;
3270 case Tclass:
3271 if (e1->op == TOKvar)
3272 { VarExp *ve = (VarExp *)e1;
3273 if (ve->var->isVarDeclaration() &&
3274 ve->var->isVarDeclaration()->onstack)
3276 rtl = RTLSYM_CALLFINALIZER;
3277 if (tb->isClassHandle()->isInterfaceDeclaration())
3278 rtl = RTLSYM_CALLINTERFACEFINALIZER;
3279 break;
3282 e = addressElem(e, e1->type);
3283 rtl = RTLSYM_DELCLASS;
3284 if (tb->isClassHandle()->isInterfaceDeclaration())
3285 rtl = RTLSYM_DELINTERFACE;
3286 break;
3288 case Tpointer:
3289 e = addressElem(e, e1->type);
3290 rtl = RTLSYM_DELMEMORY;
3291 break;
3293 default:
3294 assert(0);
3295 break;
3297 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
3299 Lret:
3300 el_setLoc(e,loc);
3301 return e;
3304 elem *CastExp::toElem(IRState *irs)
3305 { elem *e;
3306 TY fty;
3307 TY tty;
3308 tym_t ftym;
3309 tym_t ttym;
3310 enum OPER eop;
3311 Type *t;
3312 Type *tfrom;
3314 #if 0
3315 printf("CastExp::toElem()\n");
3316 print();
3317 printf("\tfrom: %s\n", e1->type->toChars());
3318 printf("\tto : %s\n", to->toChars());
3319 #endif
3321 e = e1->toElem(irs);
3322 tfrom = e1->type->toBasetype();
3323 t = to->toBasetype(); // skip over typedef's
3324 if (t->equals(tfrom))
3325 goto Lret;
3327 fty = tfrom->ty;
3328 //printf("fty = %d\n", fty);
3329 tty = t->ty;
3331 if (tty == Tpointer && fty == Tarray
3332 #if 0
3333 && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3334 #endif
3337 if (e->Eoper == OPvar)
3339 // e1 -> *(&e1 + 4)
3340 e = el_una(OPaddr, TYnptr, e);
3341 e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
3342 e = el_una(OPind,t->totym(),e);
3344 else
3346 // e1 -> (unsigned)(e1 >> 32)
3347 e = el_bin(OPshr, TYullong, e, el_long(TYint, 32));
3348 e = el_una(OP64_32, t->totym(), e);
3350 goto Lret;
3353 if (tty == Tpointer && fty == Tsarray
3354 #if 0
3355 && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3356 #endif
3359 // e1 -> &e1
3360 e = el_una(OPaddr, TYnptr, e);
3361 goto Lret;
3364 // Convert from static array to dynamic array
3365 if (tty == Tarray && fty == Tsarray)
3367 e = sarray_toDarray(tfrom, t, e);
3368 goto Lret;
3371 // Convert from dynamic array to dynamic array
3372 if (tty == Tarray && fty == Tarray)
3374 unsigned fsize = tfrom->nextOf()->size();
3375 unsigned tsize = t->nextOf()->size();
3377 if (fsize != tsize)
3379 elem *ep;
3381 ep = el_params(e, el_long(TYint, fsize), el_long(TYint, tsize), NULL);
3382 e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep);
3384 goto Lret;
3387 // Casting from base class to derived class requires a runtime check
3388 if (fty == Tclass && tty == Tclass)
3390 // Casting from derived class to base class is a no-op
3391 ClassDeclaration *cdfrom;
3392 ClassDeclaration *cdto;
3393 int offset;
3394 int rtl = RTLSYM_DYNAMIC_CAST;
3396 cdfrom = e1->type->isClassHandle();
3397 cdto = t->isClassHandle();
3398 if (cdfrom->isInterfaceDeclaration())
3400 rtl = RTLSYM_INTERFACE_CAST;
3401 if (cdfrom->isCPPinterface())
3403 if (cdto->isCPPinterface())
3405 /* Casting from a C++ interface to a C++ interface
3406 * is always a 'paint' operation
3408 goto Lret; // no-op
3411 /* Casting from a C++ interface to a class
3412 * always results in null because there is no runtime
3413 * information available to do it.
3415 * Casting from a C++ interface to a non-C++ interface
3416 * always results in null because there's no way one
3417 * can be derived from the other.
3419 e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0));
3420 goto Lret;
3423 if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME)
3425 /* The offset from cdfrom=>cdto is known at compile time.
3428 //printf("offset = %d\n", offset);
3429 if (offset)
3430 { /* Rewrite cast as (e ? e + offset : null)
3432 elem *etmp;
3433 elem *ex;
3435 if (e1->op == TOKthis)
3436 { // Assume 'this' is never null, so skip null check
3437 e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
3439 else
3441 etmp = el_same(&e);
3442 ex = el_bin(OPadd, TYnptr, etmp, el_long(TYint, offset));
3443 ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0));
3444 e = el_bin(OPcond, TYnptr, e, ex);
3447 goto Lret; // no-op
3450 /* The offset from cdfrom=>cdto can only be determined at runtime.
3452 elem *ep;
3454 ep = el_param(el_ptr(cdto->toSymbol()), e);
3455 e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep);
3456 goto Lret;
3459 ftym = e->Ety;
3460 ttym = t->totym();
3461 if (ftym == ttym)
3462 goto Lret;
3464 switch (tty)
3466 case Tpointer:
3467 if (fty == Tdelegate)
3468 goto Lpaint;
3469 tty = Tuns32;
3470 break;
3472 case Tchar: tty = Tuns8; break;
3473 case Twchar: tty = Tuns16; break;
3474 case Tdchar: tty = Tuns32; break;
3475 case Tvoid: goto Lpaint;
3477 case Tbool:
3479 // Construct e?true:false
3480 elem *eq;
3482 e = el_una(OPbool, ttym, e);
3483 goto Lret;
3487 switch (fty)
3489 case Tpointer: fty = Tuns32; break;
3490 case Tchar: fty = Tuns8; break;
3491 case Twchar: fty = Tuns16; break;
3492 case Tdchar: fty = Tuns32; break;
3495 #define X(fty, tty) ((fty) * TMAX + (tty))
3496 Lagain:
3497 switch (X(fty,tty))
3499 #if 0
3500 case X(Tbit,Tint8):
3501 case X(Tbit,Tuns8):
3502 goto Lpaint;
3503 case X(Tbit,Tint16):
3504 case X(Tbit,Tuns16):
3505 case X(Tbit,Tint32):
3506 case X(Tbit,Tuns32): eop = OPu8_16; goto Leop;
3507 case X(Tbit,Tint64):
3508 case X(Tbit,Tuns64):
3509 case X(Tbit,Tfloat32):
3510 case X(Tbit,Tfloat64):
3511 case X(Tbit,Tfloat80):
3512 case X(Tbit,Tcomplex32):
3513 case X(Tbit,Tcomplex64):
3514 case X(Tbit,Tcomplex80):
3515 e = el_una(OPu8_16, TYuint, e);
3516 fty = Tuns32;
3517 goto Lagain;
3518 case X(Tbit,Timaginary32):
3519 case X(Tbit,Timaginary64):
3520 case X(Tbit,Timaginary80): goto Lzero;
3521 #endif
3522 /* ============================= */
3524 case X(Tbool,Tint8):
3525 case X(Tbool,Tuns8):
3526 goto Lpaint;
3527 case X(Tbool,Tint16):
3528 case X(Tbool,Tuns16):
3529 case X(Tbool,Tint32):
3530 case X(Tbool,Tuns32): eop = OPu8_16; goto Leop;
3531 case X(Tbool,Tint64):
3532 case X(Tbool,Tuns64):
3533 case X(Tbool,Tfloat32):
3534 case X(Tbool,Tfloat64):
3535 case X(Tbool,Tfloat80):
3536 case X(Tbool,Tcomplex32):
3537 case X(Tbool,Tcomplex64):
3538 case X(Tbool,Tcomplex80):
3539 e = el_una(OPu8_16, TYuint, e);
3540 fty = Tuns32;
3541 goto Lagain;
3542 case X(Tbool,Timaginary32):
3543 case X(Tbool,Timaginary64):
3544 case X(Tbool,Timaginary80): goto Lzero;
3546 /* ============================= */
3548 case X(Tint8,Tuns8): goto Lpaint;
3549 case X(Tint8,Tint16):
3550 case X(Tint8,Tuns16):
3551 case X(Tint8,Tint32):
3552 case X(Tint8,Tuns32): eop = OPs8_16; goto Leop;
3553 case X(Tint8,Tint64):
3554 case X(Tint8,Tuns64):
3555 case X(Tint8,Tfloat32):
3556 case X(Tint8,Tfloat64):
3557 case X(Tint8,Tfloat80):
3558 case X(Tint8,Tcomplex32):
3559 case X(Tint8,Tcomplex64):
3560 case X(Tint8,Tcomplex80):
3561 e = el_una(OPs8_16, TYint, e);
3562 fty = Tint32;
3563 goto Lagain;
3564 case X(Tint8,Timaginary32):
3565 case X(Tint8,Timaginary64):
3566 case X(Tint8,Timaginary80): goto Lzero;
3568 /* ============================= */
3570 case X(Tuns8,Tint8): goto Lpaint;
3571 case X(Tuns8,Tint16):
3572 case X(Tuns8,Tuns16):
3573 case X(Tuns8,Tint32):
3574 case X(Tuns8,Tuns32): eop = OPu8_16; goto Leop;
3575 case X(Tuns8,Tint64):
3576 case X(Tuns8,Tuns64):
3577 case X(Tuns8,Tfloat32):
3578 case X(Tuns8,Tfloat64):
3579 case X(Tuns8,Tfloat80):
3580 case X(Tuns8,Tcomplex32):
3581 case X(Tuns8,Tcomplex64):
3582 case X(Tuns8,Tcomplex80):
3583 e = el_una(OPu8_16, TYuint, e);
3584 fty = Tuns32;
3585 goto Lagain;
3586 case X(Tuns8,Timaginary32):
3587 case X(Tuns8,Timaginary64):
3588 case X(Tuns8,Timaginary80): goto Lzero;
3590 /* ============================= */
3592 case X(Tint16,Tint8):
3593 case X(Tint16,Tuns8): eop = OP16_8; goto Leop;
3594 case X(Tint16,Tuns16): goto Lpaint;
3595 case X(Tint16,Tint32):
3596 case X(Tint16,Tuns32): eop = OPs16_32; goto Leop;
3597 case X(Tint16,Tint64):
3598 case X(Tint16,Tuns64): e = el_una(OPs16_32, TYint, e);
3599 fty = Tint32;
3600 goto Lagain;
3601 case X(Tint16,Tfloat32):
3602 case X(Tint16,Tfloat64):
3603 case X(Tint16,Tfloat80):
3604 case X(Tint16,Tcomplex32):
3605 case X(Tint16,Tcomplex64):
3606 case X(Tint16,Tcomplex80):
3607 e = el_una(OPs16_d, TYdouble, e);
3608 fty = Tfloat64;
3609 goto Lagain;
3610 case X(Tint16,Timaginary32):
3611 case X(Tint16,Timaginary64):
3612 case X(Tint16,Timaginary80): goto Lzero;
3614 /* ============================= */
3616 case X(Tuns16,Tint8):
3617 case X(Tuns16,Tuns8): eop = OP16_8; goto Leop;
3618 case X(Tuns16,Tint16): goto Lpaint;
3619 case X(Tuns16,Tint32):
3620 case X(Tuns16,Tuns32): eop = OPu16_32; goto Leop;
3621 case X(Tuns16,Tint64):
3622 case X(Tuns16,Tuns64):
3623 case X(Tuns16,Tfloat64):
3624 case X(Tuns16,Tfloat32):
3625 case X(Tuns16,Tfloat80):
3626 case X(Tuns16,Tcomplex32):
3627 case X(Tuns16,Tcomplex64):
3628 case X(Tuns16,Tcomplex80):
3629 e = el_una(OPu16_32, TYuint, e);
3630 fty = Tuns32;
3631 goto Lagain;
3632 case X(Tuns16,Timaginary32):
3633 case X(Tuns16,Timaginary64):
3634 case X(Tuns16,Timaginary80): goto Lzero;
3636 /* ============================= */
3638 case X(Tint32,Tint8):
3639 case X(Tint32,Tuns8): e = el_una(OP32_16, TYshort, e);
3640 fty = Tint16;
3641 goto Lagain;
3642 case X(Tint32,Tint16):
3643 case X(Tint32,Tuns16): eop = OP32_16; goto Leop;
3644 case X(Tint32,Tuns32): goto Lpaint;
3645 case X(Tint32,Tint64):
3646 case X(Tint32,Tuns64): eop = OPs32_64; goto Leop;
3647 case X(Tint32,Tfloat32):
3648 case X(Tint32,Tfloat64):
3649 case X(Tint32,Tfloat80):
3650 case X(Tint32,Tcomplex32):
3651 case X(Tint32,Tcomplex64):
3652 case X(Tint32,Tcomplex80):
3653 e = el_una(OPs32_d, TYdouble, e);
3654 fty = Tfloat64;
3655 goto Lagain;
3656 case X(Tint32,Timaginary32):
3657 case X(Tint32,Timaginary64):
3658 case X(Tint32,Timaginary80): goto Lzero;
3660 /* ============================= */
3662 case X(Tuns32,Tint8):
3663 case X(Tuns32,Tuns8): e = el_una(OP32_16, TYshort, e);
3664 fty = Tuns16;
3665 goto Lagain;
3666 case X(Tuns32,Tint16):
3667 case X(Tuns32,Tuns16): eop = OP32_16; goto Leop;
3668 case X(Tuns32,Tint32): goto Lpaint;
3669 case X(Tuns32,Tint64):
3670 case X(Tuns32,Tuns64): eop = OPu32_64; goto Leop;
3671 case X(Tuns32,Tfloat32):
3672 case X(Tuns32,Tfloat64):
3673 case X(Tuns32,Tfloat80):
3674 case X(Tuns32,Tcomplex32):
3675 case X(Tuns32,Tcomplex64):
3676 case X(Tuns32,Tcomplex80):
3677 e = el_una(OPu32_d, TYdouble, e);
3678 fty = Tfloat64;
3679 goto Lagain;
3680 case X(Tuns32,Timaginary32):
3681 case X(Tuns32,Timaginary64):
3682 case X(Tuns32,Timaginary80): goto Lzero;
3684 /* ============================= */
3686 case X(Tint64,Tint8):
3687 case X(Tint64,Tuns8):
3688 case X(Tint64,Tint16):
3689 case X(Tint64,Tuns16): e = el_una(OP64_32, TYint, e);
3690 fty = Tint32;
3691 goto Lagain;
3692 case X(Tint64,Tint32):
3693 case X(Tint64,Tuns32): eop = OP64_32; goto Leop;
3694 case X(Tint64,Tuns64): goto Lpaint;
3695 case X(Tint64,Tfloat32):
3696 case X(Tint64,Tfloat64):
3697 case X(Tint64,Tfloat80):
3698 case X(Tint64,Tcomplex32):
3699 case X(Tint64,Tcomplex64):
3700 case X(Tint64,Tcomplex80):
3701 e = el_una(OPs64_d, TYdouble, e);
3702 fty = Tfloat64;
3703 goto Lagain;
3704 case X(Tint64,Timaginary32):
3705 case X(Tint64,Timaginary64):
3706 case X(Tint64,Timaginary80): goto Lzero;
3708 /* ============================= */
3710 case X(Tuns64,Tint8):
3711 case X(Tuns64,Tuns8):
3712 case X(Tuns64,Tint16):
3713 case X(Tuns64,Tuns16): e = el_una(OP64_32, TYint, e);
3714 fty = Tint32;
3715 goto Lagain;
3716 case X(Tuns64,Tint32):
3717 case X(Tuns64,Tuns32): eop = OP64_32; goto Leop;
3718 case X(Tuns64,Tint64): goto Lpaint;
3719 case X(Tuns64,Tfloat32):
3720 case X(Tuns64,Tfloat64):
3721 case X(Tuns64,Tfloat80):
3722 case X(Tuns64,Tcomplex32):
3723 case X(Tuns64,Tcomplex64):
3724 case X(Tuns64,Tcomplex80):
3725 e = el_una(OPu64_d, TYdouble, e);
3726 fty = Tfloat64;
3727 goto Lagain;
3728 case X(Tuns64,Timaginary32):
3729 case X(Tuns64,Timaginary64):
3730 case X(Tuns64,Timaginary80): goto Lzero;
3732 /* ============================= */
3734 case X(Tfloat32,Tint8):
3735 case X(Tfloat32,Tuns8):
3736 case X(Tfloat32,Tint16):
3737 case X(Tfloat32,Tuns16):
3738 case X(Tfloat32,Tint32):
3739 case X(Tfloat32,Tuns32):
3740 case X(Tfloat32,Tint64):
3741 case X(Tfloat32,Tuns64):
3742 case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e);
3743 fty = Tfloat64;
3744 goto Lagain;
3745 case X(Tfloat32,Tfloat64): eop = OPf_d; goto Leop;
3746 case X(Tfloat32,Timaginary32): goto Lzero;
3747 case X(Tfloat32,Timaginary64): goto Lzero;
3748 case X(Tfloat32,Timaginary80): goto Lzero;
3749 case X(Tfloat32,Tcomplex32):
3750 case X(Tfloat32,Tcomplex64):
3751 case X(Tfloat32,Tcomplex80):
3752 e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e);
3753 fty = Tcomplex32;
3754 goto Lagain;
3756 /* ============================= */
3758 case X(Tfloat64,Tint8):
3759 case X(Tfloat64,Tuns8): e = el_una(OPd_s16, TYshort, e);
3760 fty = Tint16;
3761 goto Lagain;
3762 case X(Tfloat64,Tint16): eop = OPd_s16; goto Leop;
3763 case X(Tfloat64,Tuns16): eop = OPd_u16; goto Leop;
3764 case X(Tfloat64,Tint32): eop = OPd_s32; goto Leop;
3765 case X(Tfloat64,Tuns32): eop = OPd_u32; goto Leop;
3766 case X(Tfloat64,Tint64): eop = OPd_s64; goto Leop;
3767 case X(Tfloat64,Tuns64): eop = OPd_u64; goto Leop;
3768 case X(Tfloat64,Tfloat32): eop = OPd_f; goto Leop;
3769 case X(Tfloat64,Tfloat80): eop = OPd_ld; goto Leop;
3770 case X(Tfloat64,Timaginary32): goto Lzero;
3771 case X(Tfloat64,Timaginary64): goto Lzero;
3772 case X(Tfloat64,Timaginary80): goto Lzero;
3773 case X(Tfloat64,Tcomplex32):
3774 case X(Tfloat64,Tcomplex64):
3775 case X(Tfloat64,Tcomplex80):
3776 e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e);
3777 fty = Tcomplex64;
3778 goto Lagain;
3780 /* ============================= */
3782 case X(Tfloat80,Tint8):
3783 case X(Tfloat80,Tuns8):
3784 case X(Tfloat80,Tint16):
3785 case X(Tfloat80,Tuns16):
3786 case X(Tfloat80,Tint32):
3787 case X(Tfloat80,Tuns32):
3788 case X(Tfloat80,Tint64):
3789 case X(Tfloat80,Tuns64):
3790 case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e);
3791 fty = Tfloat64;
3792 goto Lagain;
3793 case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop;
3794 case X(Tfloat80,Timaginary32): goto Lzero;
3795 case X(Tfloat80,Timaginary64): goto Lzero;
3796 case X(Tfloat80,Timaginary80): goto Lzero;
3797 case X(Tfloat80,Tcomplex32):
3798 case X(Tfloat80,Tcomplex64):
3799 case X(Tfloat80,Tcomplex80):
3800 e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0));
3801 fty = Tcomplex80;
3802 goto Lagain;
3804 /* ============================= */
3806 case X(Timaginary32,Tint8):
3807 case X(Timaginary32,Tuns8):
3808 case X(Timaginary32,Tint16):
3809 case X(Timaginary32,Tuns16):
3810 case X(Timaginary32,Tint32):
3811 case X(Timaginary32,Tuns32):
3812 case X(Timaginary32,Tint64):
3813 case X(Timaginary32,Tuns64):
3814 case X(Timaginary32,Tfloat32):
3815 case X(Timaginary32,Tfloat64):
3816 case X(Timaginary32,Tfloat80): goto Lzero;
3817 case X(Timaginary32,Timaginary64): eop = OPf_d; goto Leop;
3818 case X(Timaginary32,Timaginary80):
3819 e = el_una(OPf_d, TYidouble, e);
3820 fty = Timaginary64;
3821 goto Lagain;
3822 case X(Timaginary32,Tcomplex32):
3823 case X(Timaginary32,Tcomplex64):
3824 case X(Timaginary32,Tcomplex80):
3825 e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e);
3826 fty = Tcomplex32;
3827 goto Lagain;
3829 /* ============================= */
3831 case X(Timaginary64,Tint8):
3832 case X(Timaginary64,Tuns8):
3833 case X(Timaginary64,Tint16):
3834 case X(Timaginary64,Tuns16):
3835 case X(Timaginary64,Tint32):
3836 case X(Timaginary64,Tuns32):
3837 case X(Timaginary64,Tint64):
3838 case X(Timaginary64,Tuns64):
3839 case X(Timaginary64,Tfloat32):
3840 case X(Timaginary64,Tfloat64):
3841 case X(Timaginary64,Tfloat80): goto Lzero;
3842 case X(Timaginary64,Timaginary32): eop = OPd_f; goto Leop;
3843 case X(Timaginary64,Timaginary80): eop = OPd_ld; goto Leop;
3844 case X(Timaginary64,Tcomplex32):
3845 case X(Timaginary64,Tcomplex64):
3846 case X(Timaginary64,Tcomplex80):
3847 e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e);
3848 fty = Tcomplex64;
3849 goto Lagain;
3851 /* ============================= */
3853 case X(Timaginary80,Tint8):
3854 case X(Timaginary80,Tuns8):
3855 case X(Timaginary80,Tint16):
3856 case X(Timaginary80,Tuns16):
3857 case X(Timaginary80,Tint32):
3858 case X(Timaginary80,Tuns32):
3859 case X(Timaginary80,Tint64):
3860 case X(Timaginary80,Tuns64):
3861 case X(Timaginary80,Tfloat32):
3862 case X(Timaginary80,Tfloat64):
3863 case X(Timaginary80,Tfloat80): goto Lzero;
3864 case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e);
3865 fty = Timaginary64;
3866 goto Lagain;
3867 case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop;
3868 case X(Timaginary80,Tcomplex32):
3869 case X(Timaginary80,Tcomplex64):
3870 case X(Timaginary80,Tcomplex80):
3871 e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e);
3872 fty = Tcomplex80;
3873 goto Lagain;
3875 /* ============================= */
3877 case X(Tcomplex32,Tint8):
3878 case X(Tcomplex32,Tuns8):
3879 case X(Tcomplex32,Tint16):
3880 case X(Tcomplex32,Tuns16):
3881 case X(Tcomplex32,Tint32):
3882 case X(Tcomplex32,Tuns32):
3883 case X(Tcomplex32,Tint64):
3884 case X(Tcomplex32,Tuns64):
3885 case X(Tcomplex32,Tfloat32):
3886 case X(Tcomplex32,Tfloat64):
3887 case X(Tcomplex32,Tfloat80):
3888 e = el_una(OPc_r, TYfloat, e);
3889 fty = Tfloat32;
3890 goto Lagain;
3891 case X(Tcomplex32,Timaginary32):
3892 case X(Tcomplex32,Timaginary64):
3893 case X(Tcomplex32,Timaginary80):
3894 e = el_una(OPc_i, TYifloat, e);
3895 fty = Timaginary32;
3896 goto Lagain;
3897 case X(Tcomplex32,Tcomplex64):
3898 case X(Tcomplex32,Tcomplex80):
3899 e = el_una(OPf_d, TYcdouble, e);
3900 fty = Tcomplex64;
3901 goto Lagain;
3903 /* ============================= */
3905 case X(Tcomplex64,Tint8):
3906 case X(Tcomplex64,Tuns8):
3907 case X(Tcomplex64,Tint16):
3908 case X(Tcomplex64,Tuns16):
3909 case X(Tcomplex64,Tint32):
3910 case X(Tcomplex64,Tuns32):
3911 case X(Tcomplex64,Tint64):
3912 case X(Tcomplex64,Tuns64):
3913 case X(Tcomplex64,Tfloat32):
3914 case X(Tcomplex64,Tfloat64):
3915 case X(Tcomplex64,Tfloat80):
3916 e = el_una(OPc_r, TYdouble, e);
3917 fty = Tfloat64;
3918 goto Lagain;
3919 case X(Tcomplex64,Timaginary32):
3920 case X(Tcomplex64,Timaginary64):
3921 case X(Tcomplex64,Timaginary80):
3922 e = el_una(OPc_i, TYidouble, e);
3923 fty = Timaginary64;
3924 goto Lagain;
3925 case X(Tcomplex64,Tcomplex32): eop = OPd_f; goto Leop;
3926 case X(Tcomplex64,Tcomplex80): eop = OPd_ld; goto Leop;
3928 /* ============================= */
3930 case X(Tcomplex80,Tint8):
3931 case X(Tcomplex80,Tuns8):
3932 case X(Tcomplex80,Tint16):
3933 case X(Tcomplex80,Tuns16):
3934 case X(Tcomplex80,Tint32):
3935 case X(Tcomplex80,Tuns32):
3936 case X(Tcomplex80,Tint64):
3937 case X(Tcomplex80,Tuns64):
3938 case X(Tcomplex80,Tfloat32):
3939 case X(Tcomplex80,Tfloat64):
3940 case X(Tcomplex80,Tfloat80):
3941 e = el_una(OPc_r, TYldouble, e);
3942 fty = Tfloat80;
3943 goto Lagain;
3944 case X(Tcomplex80,Timaginary32):
3945 case X(Tcomplex80,Timaginary64):
3946 case X(Tcomplex80,Timaginary80):
3947 e = el_una(OPc_i, TYildouble, e);
3948 fty = Timaginary80;
3949 goto Lagain;
3950 case X(Tcomplex80,Tcomplex32):
3951 case X(Tcomplex80,Tcomplex64):
3952 e = el_una(OPld_d, TYcdouble, e);
3953 fty = Tcomplex64;
3954 goto Lagain;
3956 /* ============================= */
3958 default:
3959 if (fty == tty)
3960 goto Lpaint;
3961 //dump(0);
3962 //printf("fty = %d, tty = %d\n", fty, tty);
3963 error("e2ir: cannot cast from %s to %s", e1->type->toChars(), t->toChars());
3964 goto Lzero;
3966 Lzero:
3967 e = el_long(ttym, 0);
3968 break;
3970 Lpaint:
3971 e->Ety = ttym;
3972 break;
3974 Leop:
3975 e = el_una(eop, ttym, e);
3976 break;
3978 Lret:
3979 // Adjust for any type paints
3980 t = type->toBasetype();
3981 e->Ety = t->totym();
3983 el_setLoc(e,loc);
3984 return e;
3987 elem *ArrayLengthExp::toElem(IRState *irs)
3989 elem *e = e1->toElem(irs);
3990 e = el_una(OP64_32, type->totym(), e);
3991 el_setLoc(e,loc);
3992 return e;
3995 elem *SliceExp::toElem(IRState *irs)
3996 { elem *e;
3997 Type *t1;
3999 //printf("SliceExp::toElem()\n");
4000 t1 = e1->type->toBasetype();
4001 e = e1->toElem(irs);
4002 if (lwr)
4003 { elem *elwr;
4004 elem *elwr2;
4005 elem *eupr;
4006 elem *eptr;
4007 elem *einit;
4008 int sz;
4010 einit = resolveLengthVar(lengthVar, &e, t1);
4012 sz = t1->nextOf()->size();
4014 elwr = lwr->toElem(irs);
4015 eupr = upr->toElem(irs);
4017 elwr2 = el_same(&elwr);
4019 // Create an array reference where:
4020 // length is (upr - lwr)
4021 // pointer is (ptr + lwr*sz)
4022 // Combine as (length pair ptr)
4024 if (global.params.useArrayBounds)
4026 // Checks (unsigned compares):
4027 // upr <= array.length
4028 // lwr <= upr
4030 elem *c1;
4031 elem *c2;
4032 elem *ea;
4033 elem *eb;
4034 elem *eupr2;
4035 elem *elength;
4037 if (t1->ty == Tpointer)
4039 // Just do lwr <= upr check
4041 eupr2 = el_same(&eupr);
4042 eupr2->Ety = TYuint; // make sure unsigned comparison
4043 c1 = el_bin(OPle, TYint, elwr2, eupr2);
4044 c1 = el_combine(eupr, c1);
4045 goto L2;
4047 else if (t1->ty == Tsarray)
4048 { TypeSArray *tsa = (TypeSArray *)t1;
4049 integer_t length = tsa->dim->toInteger();
4051 elength = el_long(TYuint, length);
4052 goto L1;
4054 else if (t1->ty == Tarray)
4056 if (lengthVar)
4057 elength = el_var(lengthVar->toSymbol());
4058 else
4060 elength = e;
4061 e = el_same(&elength);
4062 elength = el_una(OP64_32, TYuint, elength);
4065 eupr2 = el_same(&eupr);
4066 c1 = el_bin(OPle, TYint, eupr, elength);
4067 eupr2->Ety = TYuint; // make sure unsigned comparison
4068 c2 = el_bin(OPle, TYint, elwr2, eupr2);
4069 c1 = el_bin(OPandand, TYint, c1, c2); // (c1 && c2)
4072 // Construct: (c1 || ModuleArray(line))
4073 Symbol *sassert;
4075 sassert = irs->blx->module->toModuleArray();
4076 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
4077 eb = el_bin(OPoror,TYvoid,c1,ea);
4078 elwr = el_combine(elwr, eb);
4080 elwr2 = el_copytree(elwr2);
4081 eupr = el_copytree(eupr2);
4085 eptr = array_toPtr(e1->type, e);
4087 elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
4088 eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
4090 e = el_pair(TYullong, elength, eptr);
4091 e = el_combine(elwr, e);
4092 e = el_combine(einit, e);
4094 else if (t1->ty == Tsarray)
4096 e = sarray_toDarray(t1, NULL, e);
4098 el_setLoc(e,loc);
4099 return e;
4102 elem *IndexExp::toElem(IRState *irs)
4103 { elem *e;
4104 elem *n1 = e1->toElem(irs);
4105 elem *n2;
4106 elem *eb = NULL;
4107 Type *t1;
4109 //printf("IndexExp::toElem() %s\n", toChars());
4110 t1 = e1->type->toBasetype();
4111 if (t1->ty == Taarray)
4113 // set to:
4114 // *aaGet(aa, keyti, valuesize, index);
4116 TypeAArray *taa = (TypeAArray *)t1;
4117 elem *keyti;
4118 elem *ep;
4119 int vsize = taa->next->size();
4120 elem *valuesize;
4121 Symbol *s;
4123 // n2 becomes the index, also known as the key
4124 n2 = e2->toElem(irs);
4125 if (n2->Ety == TYstruct || n2->Ety == TYarray)
4127 n2 = el_una(OPstrpar, TYstruct, n2);
4128 n2->Enumbytes = n2->E1->Enumbytes;
4129 //printf("numbytes = %d\n", n2->Enumbytes);
4130 assert(n2->Enumbytes);
4132 valuesize = el_long(TYuint, vsize); // BUG: should be TYsize_t
4133 //printf("valuesize: "); elem_print(valuesize);
4134 if (modifiable)
4136 n1 = el_una(OPaddr, TYnptr, n1);
4137 s = taa->aaGetSymbol("Get", 1);
4139 else
4141 s = taa->aaGetSymbol("GetRvalue", 1);
4143 //printf("taa->index = %s\n", taa->index->toChars());
4144 keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs);
4145 //keyti = taa->index->getTypeInfo(NULL)->toElem(irs);
4146 //printf("keyti:\n");
4147 //elem_print(keyti);
4148 ep = el_params(n2, valuesize, keyti, n1, NULL);
4149 e = el_bin(OPcall, TYnptr, el_var(s), ep);
4150 if (global.params.useArrayBounds)
4152 elem *n;
4153 elem *ea;
4155 n = el_same(&e);
4157 // Construct: ((e || ModuleAssert(line)),n)
4158 Symbol *sassert;
4160 sassert = irs->blx->module->toModuleArray();
4161 ea = el_bin(OPcall,TYvoid,el_var(sassert),
4162 el_long(TYint, loc.linnum));
4163 e = el_bin(OPoror,TYvoid,e,ea);
4164 e = el_bin(OPcomma, TYnptr, e, n);
4166 e = el_una(OPind, type->totym(), e);
4167 if (tybasic(e->Ety) == TYstruct)
4168 e->Enumbytes = type->size();
4170 else
4171 { elem *einit;
4173 einit = resolveLengthVar(lengthVar, &n1, t1);
4174 n2 = e2->toElem(irs);
4176 if (global.params.useArrayBounds)
4178 elem *elength;
4179 elem *n2x;
4180 elem *ea;
4182 if (t1->ty == Tsarray)
4183 { TypeSArray *tsa = (TypeSArray *)t1;
4184 integer_t length = tsa->dim->toInteger();
4186 elength = el_long(TYuint, length);
4187 goto L1;
4189 else if (t1->ty == Tarray)
4191 elength = n1;
4192 n1 = el_same(&elength);
4193 elength = el_una(OP64_32, TYuint, elength);
4195 n2x = n2;
4196 n2 = el_same(&n2x);
4197 n2x = el_bin(OPlt, TYint, n2x, elength);
4199 // Construct: (n2x || ModuleAssert(line))
4200 Symbol *sassert;
4202 sassert = irs->blx->module->toModuleArray();
4203 ea = el_bin(OPcall,TYvoid,el_var(sassert),
4204 el_long(TYint, loc.linnum));
4205 eb = el_bin(OPoror,TYvoid,n2x,ea);
4209 n1 = array_toPtr(t1, n1);
4211 { elem *escale;
4213 escale = el_long(TYint, t1->nextOf()->size());
4214 n2 = el_bin(OPmul, TYint, n2, escale);
4215 e = el_bin(OPadd, TYnptr, n1, n2);
4216 e = el_una(OPind, type->totym(), e);
4217 if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
4218 { e->Ety = TYstruct;
4219 e->Enumbytes = type->size();
4223 eb = el_combine(einit, eb);
4224 e = el_combine(eb, e);
4226 el_setLoc(e,loc);
4227 return e;
4231 elem *TupleExp::toElem(IRState *irs)
4232 { elem *e = NULL;
4234 //printf("TupleExp::toElem() %s\n", toChars());
4235 for (size_t i = 0; i < exps->dim; i++)
4236 { Expression *el = (Expression *)exps->data[i];
4237 elem *ep = el->toElem(irs);
4239 e = el_combine(e, ep);
4241 return e;
4245 elem *ArrayLiteralExp::toElem(IRState *irs)
4246 { elem *e;
4247 size_t dim;
4249 //printf("ArrayLiteralExp::toElem() %s\n", toChars());
4250 if (elements)
4252 dim = elements->dim;
4253 e = el_long(TYint, dim);
4254 for (size_t i = 0; i < dim; i++)
4255 { Expression *el = (Expression *)elements->data[i];
4256 elem *ep = el->toElem(irs);
4258 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
4260 ep = el_una(OPstrpar, TYstruct, ep);
4261 ep->Enumbytes = el->type->size();
4263 e = el_param(ep, e);
4266 else
4267 { dim = 0;
4268 e = el_long(TYint, 0);
4270 Type *tb = type->toBasetype();
4271 #if 1
4272 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4274 // call _d_arrayliteralT(ti, dim, ...)
4275 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
4276 #else
4277 e = el_param(e, el_long(TYint, tb->next->size()));
4279 // call _d_arrayliteral(size, dim, ...)
4280 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e);
4281 #endif
4282 if (tb->ty == Tarray)
4284 e = el_pair(TYullong, el_long(TYint, dim), e);
4286 else if (tb->ty == Tpointer)
4289 else
4291 e = el_una(OPind,TYstruct,e);
4292 e->Enumbytes = type->size();
4295 el_setLoc(e,loc);
4296 return e;
4300 elem *AssocArrayLiteralExp::toElem(IRState *irs)
4301 { elem *e;
4302 size_t dim;
4304 //printf("AssocArrayLiteralExp::toElem() %s\n", toChars());
4305 dim = keys->dim;
4306 e = el_long(TYint, dim);
4307 for (size_t i = 0; i < dim; i++)
4308 { Expression *el = (Expression *)keys->data[i];
4310 for (int j = 0; j < 2; j++)
4312 elem *ep = el->toElem(irs);
4314 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
4316 ep = el_una(OPstrpar, TYstruct, ep);
4317 ep->Enumbytes = el->type->size();
4319 //printf("[%d] %s\n", i, el->toChars());
4320 //elem_print(ep);
4321 e = el_param(ep, e);
4322 el = (Expression *)values->data[i];
4325 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4327 // call _d_assocarrayliteralT(ti, dim, ...)
4328 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e);
4330 el_setLoc(e,loc);
4331 return e;
4335 /*******************************************
4336 * Generate elem to zero fill contents of Symbol stmp
4337 * from *poffset..offset2.
4338 * May store anywhere from 0..maxoff, as this function
4339 * tries to use aligned int stores whereever possible.
4340 * Update *poffset to end of initialized hole; *poffset will be >= offset2.
4343 elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff)
4344 { elem *e = NULL;
4345 int basealign = 1;
4347 while (*poffset < offset2)
4348 { tym_t ty;
4349 elem *e1;
4351 if (tybasic(stmp->Stype->Tty) == TYnptr)
4352 e1 = el_var(stmp);
4353 else
4354 e1 = el_ptr(stmp);
4355 if (basealign)
4356 *poffset &= ~3;
4357 basealign = 1;
4358 size_t sz = maxoff - *poffset;
4359 switch (sz)
4360 { case 1: ty = TYchar; break;
4361 case 2: ty = TYshort; break;
4362 case 3:
4363 ty = TYshort;
4364 basealign = 0;
4365 break;
4366 default:
4367 ty = TYlong;
4368 break;
4370 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
4371 e1 = el_una(OPind, ty, e1);
4372 e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
4373 e = el_combine(e, e1);
4374 *poffset += tysize[ty];
4376 return e;
4379 elem *StructLiteralExp::toElem(IRState *irs)
4380 { elem *e;
4381 size_t dim;
4383 //printf("StructLiteralExp::toElem() %s\n", toChars());
4385 // struct symbol to initialize with the literal
4386 Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype());
4388 e = NULL;
4390 if (fillHoles)
4392 /* Initialize all alignment 'holes' to zero.
4393 * Do before initializing fields, as the hole filling process
4394 * can spill over into the fields.
4396 size_t offset = 0;
4397 for (size_t i = 0; i < sd->fields.dim; i++)
4399 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4400 VarDeclaration *v = s->isVarDeclaration();
4401 assert(v);
4403 e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize));
4404 size_t vend = v->offset + v->type->size();
4405 if (offset < vend)
4406 offset = vend;
4408 e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize));
4411 if (elements)
4413 dim = elements->dim;
4414 assert(dim <= sd->fields.dim);
4415 for (size_t i = 0; i < dim; i++)
4416 { Expression *el = (Expression *)elements->data[i];
4417 if (!el)
4418 continue;
4420 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4421 VarDeclaration *v = s->isVarDeclaration();
4422 assert(v);
4424 elem *e1;
4425 if (tybasic(stmp->Stype->Tty) == TYnptr)
4426 { e1 = el_var(stmp);
4427 e1->EV.sp.Voffset = soffset;
4429 else
4430 { e1 = el_ptr(stmp);
4431 if (soffset)
4432 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
4434 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset));
4436 elem *ep = el->toElem(irs);
4438 Type *t1b = v->type->toBasetype();
4439 Type *t2b = el->type->toBasetype();
4440 if (t1b->ty == Tsarray)
4442 if (t2b->implicitConvTo(t1b))
4443 { elem *esize = el_long(TYsize_t, t1b->size());
4444 ep = array_toPtr(el->type, ep);
4445 e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
4447 else
4449 elem *edim = el_long(TYsize_t, t1b->size() / t2b->size());
4450 e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct);
4453 else
4455 tym_t ty = v->type->totym();
4456 e1 = el_una(OPind, ty, e1);
4457 if (ty == TYstruct)
4458 e1->Enumbytes = v->type->size();
4459 e1 = el_bin(OPeq, ty, e1, ep);
4460 if (ty == TYstruct)
4461 { e1->Eoper = OPstreq;
4462 e1->Enumbytes = v->type->size();
4465 e = el_combine(e, e1);
4469 elem *ev = el_var(stmp);
4470 ev->Enumbytes = sd->structsize;
4471 e = el_combine(e, ev);
4472 el_setLoc(e,loc);
4473 return e;