Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd / e2ir.c
blobff65ad4fc17fa784bc892c1edae32317ca6c61c4
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)
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;
542 default:
543 r = RTLSYM_MEMSETN;
544 evalue = el_una(OPaddr, TYnptr, evalue);
545 elem *esz = el_long(TYint, sz);
546 e = el_params(esz, edim, evalue, eptr, NULL);
547 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
548 return e;
551 if (sz > 1 && sz <= 8 &&
552 evalue->Eoper == OPconst && el_allbits(evalue, 0))
554 r = RTLSYM_MEMSET8;
555 edim = el_bin(OPmul, TYuint, edim, el_long(TYuint, sz));
558 if (evalue->Ety == TYstruct)
560 evalue = el_una(OPstrpar, TYstruct, evalue);
561 evalue->Enumbytes = evalue->E1->Enumbytes;
562 assert(evalue->Enumbytes);
565 // Be careful about parameter side effect ordering
566 if (r == RTLSYM_MEMSET8)
568 e = el_param(edim, evalue);
569 e = el_bin(OPmemset,TYnptr,eptr,e);
571 else
573 e = el_params(edim, evalue, eptr, NULL);
574 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e);
576 return e;
579 /***************************************
582 elem *Expression::toElem(IRState *irs)
584 print();
585 assert(0);
586 return NULL;
589 /***************************************
592 elem *VarExp::toElem(IRState *irs)
593 { Symbol *s;
594 elem *e;
595 tym_t tym;
596 Type *tb = type->toBasetype();
597 FuncDeclaration *fd;
599 //printf("VarExp::toElem('%s') %p\n", toChars(), this);
600 //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null");
601 if (var->needThis())
603 error("need 'this' to access member %s", toChars());
604 return el_long(TYint, 0);
606 s = var->toSymbol();
607 fd = NULL;
608 if (var->toParent2())
609 fd = var->toParent2()->isFuncDeclaration();
611 int nrvo = 0;
612 if (fd && fd->nrvo_can && fd->nrvo_var == var)
614 s = fd->shidden;
615 nrvo = 1;
618 if (s->Sclass == SCauto || s->Sclass == SCparameter)
620 if (fd && fd != irs->getFunc())
621 { // 'var' is a variable in an enclosing function.
622 elem *ethis;
623 int offset;
625 ethis = getEthis(loc, irs, fd);
626 ethis = el_una(OPaddr, TYnptr, ethis);
628 offset = s->Soffset;
630 /* If fd is a non-static member function of a class or struct,
631 * then ethis isn't the frame pointer.
632 * ethis is the 'this' pointer to the class/struct instance.
633 * We must offset it.
635 if (fd->vthis)
637 offset -= fd->vthis->toSymbol()->Soffset;
639 //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset);
641 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, offset));
642 e = el_una(OPind, 0, ethis);
643 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
644 goto L2;
645 goto L1;
649 if (s->Sclass == SCauto && s->Ssymnum == -1)
651 //printf("\tadding symbol\n");
652 symbol_add(s);
654 if (var->isImportedSymbol())
656 e = el_var(var->toImport());
657 e = el_una(OPind,s->ty(),e);
659 else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
660 { // Static arrays are really passed as pointers to the array
661 // Out parameters are really references
662 e = el_var(s);
664 e->Ety = TYnptr;
665 e = el_una(OPind, s->ty(), e);
667 else
668 e = el_var(s);
670 if (nrvo)
672 e->Ety = TYnptr;
673 e = el_una(OPind, 0, e);
675 if (tb->ty == Tfunction)
677 tym = s->Stype->Tty;
679 else
680 tym = type->totym();
681 e->Ejty = e->Ety = tym;
682 if (tybasic(tym) == TYstruct)
684 e->Enumbytes = type->size();
686 else if (tybasic(tym) == TYarray)
688 e->Ejty = e->Ety = TYstruct;
689 e->Enumbytes = type->size();
691 el_setLoc(e,loc);
692 return e;
695 /*****************************************
698 elem *FuncExp::toElem(IRState *irs)
700 elem *e;
701 Symbol *s;
703 //printf("FuncExp::toElem() %s\n", toChars());
704 s = fd->toSymbol();
705 e = el_ptr(s);
706 if (fd->isNested())
708 elem *ethis = getEthis(loc, irs, fd);
709 e = el_pair(TYullong, ethis, e);
712 irs->deferToObj->push(fd);
713 el_setLoc(e,loc);
714 return e;
717 /**************************************
720 elem *Dsymbol_toElem(Dsymbol *s, IRState *irs)
722 elem *e = NULL;
723 Symbol *sp;
724 AttribDeclaration *ad;
725 VarDeclaration *vd;
726 ClassDeclaration *cd;
727 StructDeclaration *sd;
728 FuncDeclaration *fd;
729 TemplateMixin *tm;
730 TupleDeclaration *td;
731 TypedefDeclaration *tyd;
733 //printf("Dsymbol_toElem() %s\n", s->toChars());
734 ad = s->isAttribDeclaration();
735 if (ad)
737 Array *decl = ad->include(NULL, NULL);
738 if (decl && decl->dim)
740 for (size_t i = 0; i < decl->dim; i++)
742 s = (Dsymbol *)decl->data[i];
743 e = el_combine(e, Dsymbol_toElem(s, irs));
747 else if ((vd = s->isVarDeclaration()) != NULL)
749 s = s->toAlias();
750 if (s != vd)
751 return Dsymbol_toElem(s, irs);
752 if (vd->isStatic() || vd->isConst() || vd->storage_class & STCextern)
753 vd->toObjFile(0);
754 else
756 sp = s->toSymbol();
757 symbol_add(sp);
758 //printf("\tadding symbol '%s'\n", sp->Sident);
759 if (vd->init)
761 ExpInitializer *ie;
763 ie = vd->init->isExpInitializer();
764 if (ie)
765 e = ie->exp->toElem(irs);
769 else if ((cd = s->isClassDeclaration()) != NULL)
771 irs->deferToObj->push(s);
772 //sd->toObjFile();
774 else if ((sd = s->isStructDeclaration()) != NULL)
776 irs->deferToObj->push(sd);
777 //sd->toObjFile();
779 else if ((fd = s->isFuncDeclaration()) != NULL)
781 //printf("function %s\n", fd->toChars());
782 irs->deferToObj->push(fd);
783 //fd->toObjFile();
785 else if ((tm = s->isTemplateMixin()) != NULL)
787 //printf("%s\n", tm->toChars());
788 if (tm->members)
790 for (size_t i = 0; i < tm->members->dim; i++)
792 Dsymbol *sm = (Dsymbol *)tm->members->data[i];
793 e = el_combine(e, Dsymbol_toElem(sm, irs));
797 else if ((td = s->isTupleDeclaration()) != NULL)
799 for (size_t i = 0; i < td->objects->dim; i++)
800 { Object *o = (Object *)td->objects->data[i];
801 if (o->dyncast() == DYNCAST_EXPRESSION)
802 { Expression *eo = (Expression *)o;
803 if (eo->op == TOKdsymbol)
804 { DsymbolExp *se = (DsymbolExp *)eo;
805 e = el_combine(e, Dsymbol_toElem(se->s, irs));
810 else if ((tyd = s->isTypedefDeclaration()) != NULL)
812 irs->deferToObj->push(tyd);
814 return e;
817 elem *DeclarationExp::toElem(IRState *irs)
818 { elem *e;
820 //printf("DeclarationExp::toElem() %s\n", toChars());
821 e = Dsymbol_toElem(declaration, irs);
822 return e;
825 /***************************************
828 elem *ThisExp::toElem(IRState *irs)
829 { elem *ethis;
830 FuncDeclaration *fd;
832 //printf("ThisExp::toElem()\n");
833 assert(irs->sthis);
835 if (var)
837 assert(var->parent);
838 fd = var->toParent2()->isFuncDeclaration();
839 assert(fd);
840 ethis = getEthis(loc, irs, fd);
842 else
843 ethis = el_var(irs->sthis);
845 el_setLoc(ethis,loc);
846 return ethis;
849 /***************************************
852 elem *IntegerExp::toElem(IRState *irs)
853 { elem *e;
855 e = el_long(type->totym(), value);
856 el_setLoc(e,loc);
857 return e;
860 /***************************************
863 elem *RealExp::toElem(IRState *irs)
864 { union eve c;
865 tym_t ty;
867 //printf("RealExp::toElem(%p)\n", this);
868 memset(&c, 0, sizeof(c));
869 ty = type->toBasetype()->totym();
870 switch (ty)
872 case TYfloat:
873 case TYifloat:
874 c.Vfloat = value;
875 break;
877 case TYdouble:
878 case TYidouble:
879 c.Vdouble = value;
880 break;
882 case TYldouble:
883 case TYildouble:
884 c.Vldouble = value;
885 break;
887 default:
888 print();
889 type->print();
890 type->toBasetype()->print();
891 printf("ty = %d, tym = %x\n", type->ty, ty);
892 assert(0);
894 return el_const(ty, &c);
898 /***************************************
901 elem *ComplexExp::toElem(IRState *irs)
902 { union eve c;
903 tym_t ty;
904 real_t re;
905 real_t im;
907 re = creall(value);
908 im = cimagl(value);
910 memset(&c, 0, sizeof(c));
911 ty = type->totym();
912 switch (ty)
914 case TYcfloat:
915 c.Vcfloat.re = (float) re;
916 c.Vcfloat.im = (float) im;
917 break;
919 case TYcdouble:
920 c.Vcdouble.re = (double) re;
921 c.Vcdouble.im = (double) im;
922 break;
924 case TYcldouble:
925 c.Vcldouble.re = re;
926 c.Vcldouble.im = im;
927 break;
929 default:
930 assert(0);
932 return el_const(ty, &c);
935 /***************************************
938 elem *NullExp::toElem(IRState *irs)
940 return el_long(type->totym(), 0);
943 /***************************************
946 struct StringTab
948 Module *m; // module we're generating code for
949 Symbol *si;
950 void *string;
951 size_t sz;
952 size_t len;
955 #define STSIZE 16
956 StringTab stringTab[STSIZE];
957 size_t stidx;
959 static Symbol *assertexp_sfilename = NULL;
960 static char *assertexp_name = NULL;
961 static Module *assertexp_mn = NULL;
963 void clearStringTab()
965 //printf("clearStringTab()\n");
966 memset(stringTab, 0, sizeof(stringTab));
967 stidx = 0;
969 assertexp_sfilename = NULL;
970 assertexp_name = NULL;
971 assertexp_mn = NULL;
974 elem *StringExp::toElem(IRState *irs)
976 elem *e;
977 Type *tb= type->toBasetype();
980 #if 0
981 printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars());
982 #endif
984 if (tb->ty == Tarray)
986 Symbol *si;
987 dt_t *dt;
988 StringTab *st;
990 #if 0
991 printf("irs->m = %p\n", irs->m);
992 printf(" m = %s\n", irs->m->toChars());
993 printf(" len = %d\n", len);
994 printf(" sz = %d\n", sz);
995 #endif
996 for (size_t i = 0; i < STSIZE; i++)
998 st = &stringTab[(stidx + i) % STSIZE];
999 //if (!st->m) continue;
1000 //printf(" st.m = %s\n", st->m->toChars());
1001 //printf(" st.len = %d\n", st->len);
1002 //printf(" st.sz = %d\n", st->sz);
1003 if (st->m == irs->m &&
1004 st->si &&
1005 st->len == len &&
1006 st->sz == sz &&
1007 memcmp(st->string, string, sz * len) == 0)
1009 //printf("use cached value\n");
1010 si = st->si; // use cached value
1011 goto L1;
1015 stidx = (stidx + 1) % STSIZE;
1016 st = &stringTab[stidx];
1018 dt = NULL;
1019 toDt(&dt);
1021 si = symbol_generate(SCstatic,type_fake(TYdarray));
1022 si->Sdt = dt;
1023 si->Sfl = FLdata;
1024 #if ELFOBJ // Burton
1025 si->Sseg = CDATA;
1026 #endif
1027 outdata(si);
1029 st->m = irs->m;
1030 st->si = si;
1031 st->string = string;
1032 st->len = len;
1033 st->sz = sz;
1035 e = el_var(si);
1037 else if (tb->ty == Tsarray)
1039 Symbol *si;
1040 dt_t *dt = NULL;
1042 toDt(&dt);
1043 dtnzeros(&dt, sz); // leave terminating 0
1045 si = symbol_generate(SCstatic,type_allocn(TYarray, tschar));
1046 si->Sdt = dt;
1047 si->Sfl = FLdata;
1049 #if ELFOBJ // Burton
1050 si->Sseg = CDATA;
1051 #endif
1052 outdata(si);
1054 e = el_var(si);
1056 else if (tb->ty == Tpointer)
1058 e = el_calloc();
1059 e->Eoper = OPstring;
1060 #if 1
1061 // Match MEM_PH_FREE for OPstring in ztc\el.c
1062 e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz);
1063 memcpy(e->EV.ss.Vstring, string, (len + 1) * sz);
1064 #else
1065 e->EV.ss.Vstring = (char *)string;
1066 #endif
1067 e->EV.ss.Vstrlen = (len + 1) * sz;
1068 e->Ety = TYnptr;
1070 else
1072 printf("type is %s\n", type->toChars());
1073 assert(0);
1075 el_setLoc(e,loc);
1076 return e;
1079 elem *NewExp::toElem(IRState *irs)
1080 { elem *e;
1081 Type *t;
1082 Type *ectype;
1084 //printf("NewExp::toElem() %s\n", toChars());
1085 t = type->toBasetype();
1086 //printf("\ttype = %s\n", t->toChars());
1087 if (t->ty == Tclass)
1089 Symbol *csym;
1091 t = newtype->toBasetype();
1092 assert(t->ty == Tclass);
1093 TypeClass *tclass = (TypeClass *)(t);
1094 ClassDeclaration *cd = tclass->sym;
1096 /* Things to do:
1097 * 1) ex: call allocator
1098 * 2) ey: set vthis for nested classes
1099 * 3) ez: call constructor
1102 elem *ex = NULL;
1103 elem *ey = NULL;
1104 elem *ez = NULL;
1106 if (allocator || onstack)
1107 { elem *ei;
1108 Symbol *si;
1110 if (onstack)
1112 /* Create an instance of the class on the stack,
1113 * and call it stmp.
1114 * Set ex to be the &stmp.
1116 Symbol *s = symbol_calloc(tclass->sym->toChars());
1117 s->Sclass = SCstruct;
1118 s->Sstruct = struct_calloc();
1119 s->Sstruct->Sflags |= 0;
1120 s->Sstruct->Salignsize = tclass->sym->alignsize;
1121 s->Sstruct->Sstructalign = tclass->sym->structalign;
1122 s->Sstruct->Sstructsize = tclass->sym->structsize;
1124 ::type *tc = type_alloc(TYstruct);
1125 tc->Ttag = (Classsym *)s; // structure tag name
1126 tc->Tcount++;
1127 s->Stype = tc;
1129 Symbol *stmp = symbol_genauto(tc);
1130 ex = el_ptr(stmp);
1132 else
1134 ex = el_var(allocator->toSymbol());
1135 ex = callfunc(loc, irs, 1, type, ex, allocator->type,
1136 allocator, allocator->type, NULL, newargs);
1139 si = tclass->sym->toInitializer();
1140 ei = el_var(si);
1142 if (cd->isNested())
1144 ey = el_same(&ex);
1145 ez = el_copytree(ey);
1147 else if (member)
1148 ez = el_same(&ex);
1150 ex = el_una(OPind, TYstruct, ex);
1151 ex = el_bin(OPstreq, TYnptr, ex, ei);
1152 ex->Enumbytes = cd->size(loc);
1153 ex = el_una(OPaddr, TYnptr, ex);
1154 ectype = tclass;
1156 else
1158 csym = cd->toSymbol();
1159 ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym));
1160 ectype = NULL;
1162 if (cd->isNested())
1164 ey = el_same(&ex);
1165 ez = el_copytree(ey);
1167 else if (member)
1168 ez = el_same(&ex);
1169 //elem_print(ex);
1170 //elem_print(ey);
1171 //elem_print(ez);
1174 if (thisexp)
1175 { ClassDeclaration *cdthis = thisexp->type->isClassHandle();
1176 assert(cdthis);
1177 //printf("cd = %s\n", cd->toChars());
1178 //printf("cdthis = %s\n", cdthis->toChars());
1179 assert(cd->isNested());
1180 int offset = 0;
1181 Dsymbol *cdp = cd->toParent2(); // class we're nested in
1182 elem *ethis;
1184 //printf("member = %p\n", member);
1185 //printf("cdp = %s\n", cdp->toChars());
1186 //printf("cdthis = %s\n", cdthis->toChars());
1187 if (cdp != cdthis)
1188 { int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset);
1189 assert(i);
1191 ethis = thisexp->toElem(irs);
1192 if (offset)
1193 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset));
1195 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
1196 ey = el_una(OPind, TYnptr, ey);
1197 ey = el_bin(OPeq, TYnptr, ey, ethis);
1199 //printf("ex: "); elem_print(ex);
1200 //printf("ey: "); elem_print(ey);
1201 //printf("ez: "); elem_print(ez);
1203 else if (cd->isNested())
1204 { /* Initialize cd->vthis:
1205 * *(ey + cd.vthis.offset) = this;
1207 elem *ethis;
1208 FuncDeclaration *thisfd = irs->getFunc();
1209 int offset = 0;
1210 Dsymbol *cdp = cd->toParent2(); // class/func we're nested in
1212 if (cdp == thisfd)
1213 { /* Class we're new'ing is a local class in this function:
1214 * void thisfd() { class cd { } }
1216 if (irs->sthis)
1218 #if V2
1219 if (thisfd->closureVars.dim)
1220 #else
1221 if (thisfd->nestedFrameRef)
1222 #endif
1224 ethis = el_ptr(irs->sthis);
1226 else
1227 ethis = el_var(irs->sthis);
1229 else
1231 ethis = el_long(TYnptr, 0);
1232 #if V2
1233 if (thisfd->closureVars.dim)
1234 #else
1235 if (thisfd->nestedFrameRef)
1236 #endif
1238 ethis->Eoper = OPframeptr;
1242 else if (thisfd->vthis &&
1243 (cdp == thisfd->toParent2() ||
1244 (cdp->isClassDeclaration() &&
1245 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset)
1249 { /* Class we're new'ing is at the same level as thisfd
1251 assert(offset == 0); // BUG: should handle this case
1252 ethis = el_var(irs->sthis);
1254 else
1256 ethis = getEthis(loc, irs, cd->toParent2());
1257 ethis = el_una(OPaddr, TYnptr, ethis);
1260 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset));
1261 ey = el_una(OPind, TYnptr, ey);
1262 ey = el_bin(OPeq, TYnptr, ey, ethis);
1266 if (member)
1267 // Call constructor
1268 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments);
1270 e = el_combine(ex, ey);
1271 e = el_combine(e, ez);
1273 else if (t->ty == Tarray)
1275 TypeDArray *tda = (TypeDArray *)(t);
1277 assert(arguments && arguments->dim >= 1);
1278 if (arguments->dim == 1)
1279 { // Single dimension array allocations
1280 Expression *arg = (Expression *)arguments->data[0]; // gives array length
1281 e = arg->toElem(irs);
1282 d_uns64 elemsize = tda->next->size();
1284 // call _d_newT(ti, arg)
1285 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1286 int rtl = t->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1287 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1289 else
1290 { // Multidimensional array allocations
1291 e = el_long(TYint, arguments->dim);
1292 for (size_t i = 0; i < arguments->dim; i++)
1294 Expression *arg = (Expression *)arguments->data[i]; // gives array length
1295 e = el_param(arg->toElem(irs), e);
1296 assert(t->ty == Tarray);
1297 t = t->nextOf();
1298 assert(t);
1301 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1303 int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
1304 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1307 else if (t->ty == Tpointer)
1309 d_uns64 elemsize = t->next->size();
1310 Expression *di = t->next->defaultInit();
1311 d_uns64 disize = di->type->size();
1313 // call _d_newarrayT(ti, 1)
1314 e = el_long(TYsize_t, 1);
1315 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
1317 int rtl = t->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
1318 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
1320 // The new functions return an array, so convert to a pointer
1321 // e -> (unsigned)(e >> 32)
1322 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
1323 e = el_una(OP64_32, t->totym(), e);
1325 else
1327 assert(0);
1330 el_setLoc(e,loc);
1331 return e;
1334 elem *SymOffExp::toElem(IRState *irs)
1335 { Symbol *s;
1336 elem *e;
1337 Type *tb = var->type->toBasetype();
1338 FuncDeclaration *fd = NULL;
1339 if (var->toParent2())
1340 fd = var->toParent2()->isFuncDeclaration();
1342 //printf("SymOffExp::toElem(): %s\n", toChars());
1343 s = var->toSymbol();
1345 int nrvo = 0;
1346 if (fd && fd->nrvo_can && fd->nrvo_var == var)
1347 { s = fd->shidden;
1348 nrvo = 1;
1351 if (s->Sclass == SCauto && s->Ssymnum == -1)
1352 symbol_add(s);
1353 assert(!var->isImportedSymbol());
1355 // This code closely parallels that in VarExp::toElem()
1356 if (s->Sclass == SCauto || s->Sclass == SCparameter)
1358 if (fd && fd != irs->getFunc())
1359 { // 'var' is a variable in an enclosing function.
1360 elem *ethis;
1361 int soffset;
1363 ethis = getEthis(loc, irs, fd);
1364 ethis = el_una(OPaddr, TYnptr, ethis);
1366 soffset = s->Soffset;
1368 // If fd is a non-static member function, then ethis isn't the
1369 // frame pointer. We must offset it.
1370 if (fd->vthis)
1372 soffset -= fd->vthis->toSymbol()->Soffset;
1375 if (!nrvo)
1376 soffset += offset;
1377 e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset));
1378 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
1379 e = el_una(OPind, s->ty(), e);
1380 else if (nrvo)
1381 { e = el_una(OPind, TYnptr, e);
1382 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
1384 goto L1;
1387 if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef())
1388 { // Static arrays are really passed as pointers to the array
1389 // Out parameters are really references
1390 e = el_var(s);
1391 e->Ety = TYnptr;
1392 if (offset)
1393 e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
1395 else
1396 { e = nrvo ? el_var(s) : el_ptr(s);
1397 e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset));
1401 el_setLoc(e,loc);
1402 return e;
1405 //////////////////////////// Unary ///////////////////////////////
1407 /***************************************
1410 elem *NegExp::toElem(IRState *irs)
1412 elem *e = el_una(OPneg, type->totym(), e1->toElem(irs));
1413 el_setLoc(e,loc);
1414 return e;
1417 /***************************************
1420 elem *ComExp::toElem(IRState *irs)
1421 { elem *e;
1423 elem *e1 = this->e1->toElem(irs);
1424 tym_t ty = type->totym();
1425 if (this->e1->type->toBasetype()->ty == Tbool)
1426 e = el_bin(OPxor, ty, e1, el_long(ty, 1));
1427 else
1428 e = el_una(OPcom,ty,e1);
1429 el_setLoc(e,loc);
1430 return e;
1433 /***************************************
1436 elem *NotExp::toElem(IRState *irs)
1438 elem *e = el_una(OPnot, type->totym(), e1->toElem(irs));
1439 el_setLoc(e,loc);
1440 return e;
1444 /***************************************
1447 elem *HaltExp::toElem(IRState *irs)
1448 { elem *e;
1450 e = el_calloc();
1451 e->Ety = TYvoid;
1452 e->Eoper = OPhalt;
1453 el_setLoc(e,loc);
1454 return e;
1457 /********************************************
1460 elem *AssertExp::toElem(IRState *irs)
1461 { elem *e;
1462 elem *ea;
1463 Type *t1 = e1->type->toBasetype();
1465 //printf("AssertExp::toElem() %s\n", toChars());
1466 if (global.params.useAssert)
1468 e = e1->toElem(irs);
1470 InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1;
1472 // If e1 is a class object, call the class invariant on it
1473 if (global.params.useInvariants && t1->ty == Tclass &&
1474 !((TypeClass *)t1)->sym->isInterfaceDeclaration())
1476 #if TARGET_LINUX
1477 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
1478 #else
1479 e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
1480 #endif
1482 // If e1 is a struct object, call the struct invariant on it
1483 else if (global.params.useInvariants &&
1484 t1->ty == Tpointer &&
1485 t1->nextOf()->ty == Tstruct &&
1486 (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL)
1488 e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL);
1490 else
1492 // Construct: (e1 || ModuleAssert(line))
1493 Symbol *sassert;
1494 Module *m = irs->blx->module;
1495 char *mname = m->srcfile->toChars();
1497 //printf("filename = '%s'\n", loc.filename);
1498 //printf("module = '%s'\n", m->srcfile->toChars());
1500 /* If the source file name has changed, probably due
1501 * to a #line directive.
1503 if (loc.filename && (msg || strcmp(loc.filename, mname) != 0))
1504 { elem *efilename;
1506 /* Cache values.
1508 //static Symbol *assertexp_sfilename = NULL;
1509 //static char *assertexp_name = NULL;
1510 //static Module *assertexp_mn = NULL;
1512 if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m)
1514 dt_t *dt = NULL;
1515 char *id;
1516 int len;
1518 id = loc.filename;
1519 len = strlen(id);
1520 dtdword(&dt, len);
1521 dtabytes(&dt,TYnptr, 0, len + 1, id);
1523 assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
1524 assertexp_sfilename->Sdt = dt;
1525 assertexp_sfilename->Sfl = FLdata;
1526 #if ELFOBJ
1527 assertexp_sfilename->Sseg = CDATA;
1528 #endif
1529 outdata(assertexp_sfilename);
1531 assertexp_mn = m;
1532 assertexp_name = id;
1535 efilename = el_var(assertexp_sfilename);
1537 if (msg)
1538 { elem *emsg = msg->toElem(irs);
1539 ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]);
1540 ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL));
1542 else
1544 ea = el_var(rtlsym[RTLSYM_DASSERT]);
1545 ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename));
1548 else
1550 sassert = m->toModuleAssert();
1551 ea = el_bin(OPcall,TYvoid,el_var(sassert),
1552 el_long(TYint, loc.linnum));
1554 e = el_bin(OPoror,TYvoid,e,ea);
1557 else
1558 { // BUG: should replace assert(0); with a HLT instruction
1559 e = el_long(TYint, 0);
1561 el_setLoc(e,loc);
1562 return e;
1565 elem *PostExp::toElem(IRState *irs)
1566 { elem *e;
1567 elem *einc;
1569 e = e1->toElem(irs);
1570 einc = e2->toElem(irs);
1571 e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec,
1572 e->Ety,e,einc);
1573 el_setLoc(e,loc);
1574 return e;
1577 //////////////////////////// Binary ///////////////////////////////
1579 /********************************************
1582 elem *BinExp::toElemBin(IRState *irs,int op)
1584 //printf("toElemBin() '%s'\n", toChars());
1586 tym_t tym = type->totym();
1588 elem *el = e1->toElem(irs);
1589 elem *er = e2->toElem(irs);
1590 elem *e = el_bin(op,tym,el,er);
1591 el_setLoc(e,loc);
1592 return e;
1595 /****************************************
1598 elem *CommaExp::toElem(IRState *irs)
1600 assert(e1 && e2);
1601 elem *eleft = e1->toElem(irs);
1602 elem *eright = e2->toElem(irs);
1603 elem *e = el_combine(eleft, eright);
1604 if (e)
1605 el_setLoc(e, loc);
1606 return e;
1610 /***************************************
1613 elem *CondExp::toElem(IRState *irs)
1614 { elem *eleft;
1615 elem *eright;
1617 elem *ec = econd->toElem(irs);
1619 eleft = e1->toElem(irs);
1620 tym_t ty = eleft->Ety;
1621 if (global.params.cov && e1->loc.linnum)
1622 eleft = el_combine(incUsageElem(irs, e1->loc), eleft);
1624 eright = e2->toElem(irs);
1625 if (global.params.cov && e2->loc.linnum)
1626 eright = el_combine(incUsageElem(irs, e2->loc), eright);
1628 elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright));
1629 if (tybasic(ty) == TYstruct)
1630 e->Enumbytes = e1->type->size();
1631 el_setLoc(e, loc);
1632 return e;
1635 /***************************************
1638 elem *AddExp::toElem(IRState *irs)
1639 { elem *e;
1640 Type *tb1 = e1->type->toBasetype();
1641 Type *tb2 = e2->type->toBasetype();
1643 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1644 (tb2->ty == Tarray || tb2->ty == Tsarray)
1647 error("Array operations not implemented");
1649 else
1650 e = toElemBin(irs,OPadd);
1651 return e;
1654 /***************************************
1657 elem *MinExp::toElem(IRState *irs)
1659 return toElemBin(irs,OPmin);
1662 /***************************************
1665 elem *CatExp::toElem(IRState *irs)
1666 { elem *e;
1668 #if 0
1669 printf("CatExp::toElem()\n");
1670 print();
1671 #endif
1673 Type *tb1 = e1->type->toBasetype();
1674 Type *tb2 = e2->type->toBasetype();
1675 Type *tn;
1677 #if 0
1678 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1679 (tb2->ty == Tarray || tb2->ty == Tsarray)
1681 #endif
1683 Type *ta = tb1->nextOf() ? e1->type : e2->type;
1684 tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf();
1686 if (e1->op == TOKcat)
1688 elem *ep;
1689 CatExp *ce = this;
1690 int n = 2;
1692 ep = eval_Darray(irs, ce->e2);
1695 n++;
1696 ce = (CatExp *)ce->e1;
1697 ep = el_param(ep, eval_Darray(irs, ce->e2));
1698 } while (ce->e1->op == TOKcat);
1699 ep = el_param(ep, eval_Darray(irs, ce->e1));
1700 #if 1
1701 ep = el_params(
1703 el_long(TYint, n),
1704 ta->getTypeInfo(NULL)->toElem(irs),
1705 NULL);
1706 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep);
1707 #else
1708 ep = el_params(
1710 el_long(TYint, n),
1711 el_long(TYint, tn->size()),
1712 NULL);
1713 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep);
1714 #endif
1716 else
1718 elem *e1;
1719 elem *e2;
1720 elem *ep;
1722 e1 = eval_Darray(irs, this->e1);
1723 e2 = eval_Darray(irs, this->e2);
1724 #if 1
1725 ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL);
1726 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep);
1727 #else
1728 ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL);
1729 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep);
1730 #endif
1732 el_setLoc(e,loc);
1734 #if 0
1735 else if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
1736 e2->type->equals(tb1->next))
1738 error("array cat with element not implemented");
1739 e = el_long(TYint, 0);
1741 else
1742 assert(0);
1743 #endif
1744 return e;
1747 /***************************************
1750 elem *MulExp::toElem(IRState *irs)
1752 return toElemBin(irs,OPmul);
1755 /************************************
1758 elem *DivExp::toElem(IRState *irs)
1760 return toElemBin(irs,OPdiv);
1763 /***************************************
1766 elem *ModExp::toElem(IRState *irs)
1768 elem *e;
1769 elem *e1;
1770 elem *e2;
1771 tym_t tym;
1773 tym = type->totym();
1775 e1 = this->e1->toElem(irs);
1776 e2 = this->e2->toElem(irs);
1778 #if 0 // Now inlined
1779 if (this->e1->type->isfloating())
1780 { elem *ep;
1782 switch (this->e1->type->ty)
1784 case Tfloat32:
1785 case Timaginary32:
1786 e1 = el_una(OPf_d, TYdouble, e1);
1787 e2 = el_una(OPf_d, TYdouble, e2);
1788 case Tfloat64:
1789 case Timaginary64:
1790 e1 = el_una(OPd_ld, TYldouble, e1);
1791 e2 = el_una(OPd_ld, TYldouble, e2);
1792 break;
1793 case Tfloat80:
1794 case Timaginary80:
1795 break;
1796 default:
1797 assert(0);
1798 break;
1800 ep = el_param(e2,e1);
1801 e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep);
1803 else
1804 #endif
1805 e = el_bin(OPmod,tym,e1,e2);
1806 el_setLoc(e,loc);
1807 return e;
1810 /***************************************
1813 elem *CmpExp::toElem(IRState *irs)
1815 elem *e;
1816 enum OPER eop;
1817 Type *t1 = e1->type->toBasetype();
1818 Type *t2 = e2->type->toBasetype();
1820 switch (op)
1822 case TOKlt: eop = OPlt; break;
1823 case TOKgt: eop = OPgt; break;
1824 case TOKle: eop = OPle; break;
1825 case TOKge: eop = OPge; break;
1826 case TOKequal: eop = OPeqeq; break;
1827 case TOKnotequal: eop = OPne; break;
1829 // NCEG floating point compares
1830 case TOKunord: eop = OPunord; break;
1831 case TOKlg: eop = OPlg; break;
1832 case TOKleg: eop = OPleg; break;
1833 case TOKule: eop = OPule; break;
1834 case TOKul: eop = OPul; break;
1835 case TOKuge: eop = OPuge; break;
1836 case TOKug: eop = OPug; break;
1837 case TOKue: eop = OPue; break;
1838 default:
1839 dump(0);
1840 assert(0);
1842 if (!t1->isfloating())
1844 // Convert from floating point compare to equivalent
1845 // integral compare
1846 eop = (enum OPER)rel_integral(eop);
1848 if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass)
1850 #if 1
1851 assert(0);
1852 #else
1853 elem *ec1;
1854 elem *ec2;
1856 ec1 = e1->toElem(irs);
1857 ec2 = e2->toElem(irs);
1858 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2));
1859 e = el_bin(eop, TYint, e, el_long(TYint, 0));
1860 #endif
1862 else if ((int)eop > 1 &&
1863 (t1->ty == Tarray || t1->ty == Tsarray) &&
1864 (t2->ty == Tarray || t2->ty == Tsarray))
1866 elem *ea1;
1867 elem *ea2;
1868 elem *ep;
1869 Type *telement = t1->nextOf()->toBasetype();
1870 int rtlfunc;
1872 ea1 = e1->toElem(irs);
1873 ea1 = array_toDarray(t1, ea1);
1874 ea2 = e2->toElem(irs);
1875 ea2 = array_toDarray(t2, ea2);
1877 ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
1878 rtlfunc = RTLSYM_ARRAYCMP;
1879 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
1880 e = el_bin(eop, TYint, e, el_long(TYint, 0));
1881 el_setLoc(e,loc);
1883 else
1885 if ((int)eop <= 1)
1887 /* The result is determinate, create:
1888 * (e1 , e2) , eop
1890 e = toElemBin(irs,OPcomma);
1891 e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop));
1893 else
1894 e = toElemBin(irs,eop);
1896 return e;
1899 elem *EqualExp::toElem(IRState *irs)
1901 //printf("EqualExp::toElem() %s\n", toChars());
1903 elem *e;
1904 enum OPER eop;
1905 Type *t1 = e1->type->toBasetype();
1906 Type *t2 = e2->type->toBasetype();
1908 switch (op)
1910 case TOKequal: eop = OPeqeq; break;
1911 case TOKnotequal: eop = OPne; break;
1912 default:
1913 dump(0);
1914 assert(0);
1917 //printf("EqualExp::toElem()\n");
1918 if (t1->ty == Tstruct)
1919 { // Do bit compare of struct's
1920 elem *es1;
1921 elem *es2;
1922 elem *ecount;
1924 es1 = e1->toElem(irs);
1925 es2 = e2->toElem(irs);
1926 #if 1
1927 es1 = addressElem(es1, t1);
1928 es2 = addressElem(es2, t2);
1929 #else
1930 es1 = el_una(OPaddr, TYnptr, es1);
1931 es2 = el_una(OPaddr, TYnptr, es2);
1932 #endif
1933 e = el_param(es1, es2);
1934 ecount = el_long(TYint, t1->size());
1935 e = el_bin(OPmemcmp, TYint, e, ecount);
1936 e = el_bin(eop, TYint, e, el_long(TYint, 0));
1937 el_setLoc(e,loc);
1939 #if 0
1940 else if (t1->ty == Tclass && t2->ty == Tclass)
1942 elem *ec1;
1943 elem *ec2;
1945 ec1 = e1->toElem(irs);
1946 ec2 = e2->toElem(irs);
1947 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
1949 #endif
1950 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
1951 (t2->ty == Tarray || t2->ty == Tsarray))
1953 elem *ea1;
1954 elem *ea2;
1955 elem *ep;
1956 Type *telement = t1->nextOf()->toBasetype();
1957 int rtlfunc;
1959 ea1 = e1->toElem(irs);
1960 ea1 = array_toDarray(t1, ea1);
1961 ea2 = e2->toElem(irs);
1962 ea2 = array_toDarray(t2, ea2);
1964 ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
1965 rtlfunc = RTLSYM_ARRAYEQ;
1966 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
1967 if (op == TOKnotequal)
1968 e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
1969 el_setLoc(e,loc);
1971 else
1972 e = toElemBin(irs, eop);
1973 return e;
1976 elem *IdentityExp::toElem(IRState *irs)
1978 elem *e;
1979 enum OPER eop;
1980 Type *t1 = e1->type->toBasetype();
1981 Type *t2 = e2->type->toBasetype();
1983 switch (op)
1985 case TOKidentity: eop = OPeqeq; break;
1986 case TOKnotidentity: eop = OPne; break;
1987 default:
1988 dump(0);
1989 assert(0);
1992 //printf("IdentityExp::toElem() %s\n", toChars());
1994 if (t1->ty == Tstruct)
1995 { // Do bit compare of struct's
1996 elem *es1;
1997 elem *es2;
1998 elem *ecount;
2000 es1 = e1->toElem(irs);
2001 es1 = addressElem(es1, e1->type);
2002 //es1 = el_una(OPaddr, TYnptr, es1);
2003 es2 = e2->toElem(irs);
2004 es2 = addressElem(es2, e2->type);
2005 //es2 = el_una(OPaddr, TYnptr, es2);
2006 e = el_param(es1, es2);
2007 ecount = el_long(TYint, t1->size());
2008 e = el_bin(OPmemcmp, TYint, e, ecount);
2009 e = el_bin(eop, TYint, e, el_long(TYint, 0));
2010 el_setLoc(e,loc);
2012 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
2013 (t2->ty == Tarray || t2->ty == Tsarray))
2015 elem *ea1;
2016 elem *ea2;
2018 ea1 = e1->toElem(irs);
2019 ea1 = array_toDarray(t1, ea1);
2020 ea2 = e2->toElem(irs);
2021 ea2 = array_toDarray(t2, ea2);
2023 e = el_bin(eop, type->totym(), ea1, ea2);
2024 el_setLoc(e,loc);
2026 else
2027 e = toElemBin(irs, eop);
2029 return e;
2033 /***************************************
2036 elem *InExp::toElem(IRState *irs)
2037 { elem *e;
2038 elem *key = e1->toElem(irs);
2039 elem *aa = e2->toElem(irs);
2040 elem *ep;
2041 elem *keyti;
2042 TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
2045 // set to:
2046 // aaIn(aa, keyti, key);
2048 if (key->Ety == TYstruct)
2050 key = el_una(OPstrpar, TYstruct, key);
2051 key->Enumbytes = key->E1->Enumbytes;
2052 assert(key->Enumbytes);
2055 Symbol *s = taa->aaGetSymbol("In", 0);
2056 keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
2057 ep = el_params(key, keyti, aa, NULL);
2058 e = el_bin(OPcall, type->totym(), el_var(s), ep);
2060 el_setLoc(e,loc);
2061 return e;
2064 /***************************************
2067 elem *RemoveExp::toElem(IRState *irs)
2068 { elem *e;
2069 Type *tb = e1->type->toBasetype();
2070 assert(tb->ty == Taarray);
2071 TypeAArray *taa = (TypeAArray *)tb;
2072 elem *ea = e1->toElem(irs);
2073 elem *ekey = e2->toElem(irs);
2074 elem *ep;
2075 elem *keyti;
2077 if (ekey->Ety == TYstruct)
2079 ekey = el_una(OPstrpar, TYstruct, ekey);
2080 ekey->Enumbytes = ekey->E1->Enumbytes;
2081 assert(ekey->Enumbytes);
2084 Symbol *s = taa->aaGetSymbol("Del", 0);
2085 keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
2086 ep = el_params(ekey, keyti, ea, NULL);
2087 e = el_bin(OPcall, TYnptr, el_var(s), ep);
2089 el_setLoc(e,loc);
2090 return e;
2093 /***************************************
2096 elem *AssignExp::toElem(IRState *irs)
2097 { elem *e;
2098 IndexExp *ae;
2099 int r;
2100 Type *t1b;
2102 //printf("AssignExp::toElem('%s')\n", toChars());
2103 t1b = e1->type->toBasetype();
2105 // Look for array.length = n
2106 if (e1->op == TOKarraylength)
2108 // Generate:
2109 // _d_arraysetlength(e2, sizeelem, &ale->e1);
2111 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
2112 elem *p1;
2113 elem *p2;
2114 elem *p3;
2115 elem *ep;
2116 Type *t1;
2118 p1 = e2->toElem(irs);
2119 p3 = ale->e1->toElem(irs);
2120 p3 = addressElem(p3, NULL);
2121 t1 = ale->e1->type->toBasetype();
2123 #if 1
2124 // call _d_arraysetlengthT(ti, e2, &ale->e1);
2125 p2 = t1->getTypeInfo(NULL)->toElem(irs);
2126 ep = el_params(p3, p1, p2, NULL); // c function
2127 r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT;
2128 #else
2129 if (t1->next->isZeroInit())
2130 { p2 = t1->getTypeInfo(NULL)->toElem(irs);
2131 ep = el_params(p3, p1, p2, NULL); // c function
2132 r = RTLSYM_ARRAYSETLENGTHT;
2134 else
2136 p2 = el_long(TYint, t1->next->size());
2137 ep = el_params(p3, p2, p1, NULL); // c function
2138 Expression *init = t1->next->defaultInit();
2139 ep = el_param(el_long(TYint, init->type->size()), ep);
2140 elem *ei = init->toElem(irs);
2141 ep = el_param(ei, ep);
2142 r = RTLSYM_ARRAYSETLENGTH3;
2144 #endif
2146 e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep);
2147 el_setLoc(e, loc);
2148 return e;
2151 // Look for array[]=n
2152 if (e1->op == TOKslice)
2154 SliceExp *are = (SliceExp *)(e1);
2155 Type *t1 = t1b;
2156 Type *t2 = e2->type->toBasetype();
2158 // which we do if the 'next' types match
2159 if (ismemset)
2160 { // Do a memset for array[]=n
2161 //printf("Lpair %s\n", toChars());
2162 SliceExp *are = (SliceExp *)e1;
2163 elem *elwr;
2164 elem *eupr;
2165 elem *n1;
2166 elem *evalue;
2167 elem *enbytes;
2168 elem *elength;
2169 elem *einit;
2170 integer_t value;
2171 Type *ta = are->e1->type->toBasetype();
2172 Type *tb = ta->nextOf()->toBasetype();
2173 int sz = tb->size();
2174 tym_t tym = type->totym();
2176 n1 = are->e1->toElem(irs);
2177 elwr = are->lwr ? are->lwr->toElem(irs) : NULL;
2178 eupr = are->upr ? are->upr->toElem(irs) : NULL;
2180 elem *n1x = n1;
2182 // Look for array[]=n
2183 if (ta->ty == Tsarray)
2185 TypeSArray *ts;
2187 ts = (TypeSArray *) ta;
2188 n1 = array_toPtr(ta, n1);
2189 enbytes = ts->dim->toElem(irs);
2190 n1x = n1;
2191 n1 = el_same(&n1x);
2192 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2194 else if (ta->ty == Tarray)
2196 n1 = el_same(&n1x);
2197 einit = resolveLengthVar(are->lengthVar, &n1, ta);
2198 enbytes = el_copytree(n1);
2199 n1 = array_toPtr(ta, n1);
2200 enbytes = el_una(OP64_32, TYint, enbytes);
2202 else if (ta->ty == Tpointer)
2204 n1 = el_same(&n1x);
2205 enbytes = el_long(TYint, -1); // largest possible index
2206 einit = NULL;
2209 // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr
2210 elem *elwrx = elwr;
2211 if (elwr) elwr = el_same(&elwrx);
2212 elem *euprx = eupr;
2213 if (eupr) eupr = el_same(&euprx);
2215 #if 0
2216 printf("sz = %d\n", sz);
2217 printf("n1x\n");
2218 elem_print(n1x);
2219 printf("einit\n");
2220 elem_print(einit);
2221 printf("elwrx\n");
2222 elem_print(elwrx);
2223 printf("euprx\n");
2224 elem_print(euprx);
2225 printf("n1\n");
2226 elem_print(n1);
2227 printf("elwr\n");
2228 elem_print(elwr);
2229 printf("eupr\n");
2230 elem_print(eupr);
2231 printf("enbytes\n");
2232 elem_print(enbytes);
2233 #endif
2234 einit = el_combine(n1x, einit);
2235 einit = el_combine(einit, elwrx);
2236 einit = el_combine(einit, euprx);
2238 evalue = this->e2->toElem(irs);
2240 #if 0
2241 printf("n1\n");
2242 elem_print(n1);
2243 printf("enbytes\n");
2244 elem_print(enbytes);
2245 #endif
2247 if (global.params.useArrayBounds && eupr && ta->ty != Tpointer)
2249 elem *c1;
2250 elem *c2;
2251 elem *ea;
2252 elem *eb;
2253 elem *enbytesx;
2255 assert(elwr);
2256 enbytesx = enbytes;
2257 enbytes = el_same(&enbytesx);
2258 c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx);
2259 c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr));
2260 c1 = el_bin(OPandand, TYint, c1, c2);
2262 // Construct: (c1 || ModuleArray(line))
2263 Symbol *sassert;
2265 sassert = irs->blx->module->toModuleArray();
2266 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
2267 eb = el_bin(OPoror,TYvoid,c1,ea);
2268 einit = el_combine(einit, eb);
2271 if (elwr)
2272 { elem *elwr2;
2274 el_free(enbytes);
2275 elwr2 = el_copytree(elwr);
2276 elwr2 = el_bin(OPmul, TYint, elwr2, el_long(TYint, sz));
2277 n1 = el_bin(OPadd, TYnptr, n1, elwr2);
2278 enbytes = el_bin(OPmin, TYint, eupr, elwr);
2279 elength = el_copytree(enbytes);
2281 else
2282 elength = el_copytree(enbytes);
2283 e = setArray(n1, enbytes, tb, evalue);
2284 Lpair:
2285 e = el_pair(TYullong, elength, e);
2286 Lret2:
2287 e = el_combine(einit, e);
2288 //elem_print(e);
2289 goto Lret;
2291 else
2293 /* It's array1[]=array2[]
2294 * which is a memcpy
2296 elem *eto;
2297 elem *efrom;
2298 elem *esize;
2299 elem *ep;
2301 eto = e1->toElem(irs);
2302 efrom = e2->toElem(irs);
2304 unsigned size;
2306 size = t1->nextOf()->size();
2307 esize = el_long(TYint, size);
2309 if (e2->type->ty == Tpointer || !global.params.useArrayBounds)
2310 { elem *epto;
2311 elem *epfr;
2312 elem *elen;
2313 elem *ex;
2315 ex = el_same(&eto);
2317 // Determine if elen is a constant
2318 if (eto->Eoper == OPpair &&
2319 eto->E1->Eoper == OPconst)
2321 elen = el_copytree(eto->E1);
2323 else
2325 // It's not a constant, so pull it from the dynamic array
2326 elen = el_una(OP64_32, TYint, el_copytree(ex));
2329 esize = el_bin(OPmul, TYint, elen, esize);
2330 epto = array_toPtr(e1->type, ex);
2331 epfr = array_toPtr(e2->type, efrom);
2332 e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize));
2333 e = el_pair(eto->Ety, el_copytree(elen), e);
2334 e = el_combine(eto, e);
2336 else
2338 // Generate:
2339 // _d_arraycopy(eto, efrom, esize)
2341 // If eto is a static array, need to convert it to
2342 // a dynamic array.
2343 //if (are->e1->type->ty == Tsarray)
2344 // eto = sarray_toDarray(are->e1->type, eto);
2346 ep = el_params(eto, efrom, esize, NULL);
2347 e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep);
2349 el_setLoc(e, loc);
2350 return e;
2354 if (e1->op == TOKindex)
2356 elem *eb;
2357 elem *ei;
2358 elem *ev;
2359 TY ty;
2360 Type *ta;
2362 ae = (IndexExp *)(e1);
2363 ta = ae->e1->type->toBasetype();
2364 ty = ta->ty;
2366 #if 1
2367 /* This will work if we can distinguish an assignment from
2368 * an initialization of the lvalue. It'll work if the latter.
2369 * If the former, because of aliasing of the return value with
2370 * function arguments, it'll fail.
2372 if (op == TOKconstruct && e2->op == TOKcall)
2373 { CallExp *ce = (CallExp *)e2;
2375 TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype();
2376 if (tf->ty == Tfunction && tf->retStyle() == RETstack)
2378 elem *ehidden = e1->toElem(irs);
2379 ehidden = el_una(OPaddr, TYnptr, ehidden);
2380 assert(!irs->ehidden);
2381 irs->ehidden = ehidden;
2382 e = e2->toElem(irs);
2383 goto Lret;
2386 #endif
2387 if (t1b->ty == Tstruct)
2389 if (e2->op == TOKint64)
2390 { /* Implement:
2391 * (struct = 0)
2392 * with:
2393 * memset(&struct, 0, struct.sizeof)
2395 elem *el = e1->toElem(irs);
2396 elem *enbytes = el_long(TYint, e1->type->size());
2397 elem *evalue = el_long(TYint, 0);
2399 el = el_una(OPaddr, TYnptr, el);
2400 e = el_param(enbytes, evalue);
2401 e = el_bin(OPmemset,TYnptr,el,e);
2402 el_setLoc(e, loc);
2403 //e = el_una(OPind, TYstruct, e);
2405 else
2407 elem *e1;
2408 elem *e2;
2409 tym_t tym;
2411 //printf("toElemBin() '%s'\n", toChars());
2413 tym = type->totym();
2415 e1 = this->e1->toElem(irs);
2416 elem *ex = e1;
2417 if (e1->Eoper == OPind)
2418 ex = e1->E1;
2419 if (this->e2->op == TOKstructliteral &&
2420 ex->Eoper == OPvar && ex->EV.sp.Voffset == 0)
2421 { StructLiteralExp *se = (StructLiteralExp *)this->e2;
2423 Symbol *symSave = se->sym;
2424 size_t soffsetSave = se->soffset;
2425 int fillHolesSave = se->fillHoles;
2427 se->sym = ex->EV.sp.Vsym;
2428 se->soffset = 0;
2429 se->fillHoles = (op == TOKconstruct) ? 1 : 0;
2431 el_free(e1);
2432 e = this->e2->toElem(irs);
2434 se->sym = symSave;
2435 se->soffset = soffsetSave;
2436 se->fillHoles = fillHolesSave;
2438 else
2440 e2 = this->e2->toElem(irs);
2441 e = el_bin(OPstreq,tym,e1,e2);
2442 e->Enumbytes = this->e1->type->size();
2444 goto Lret;
2447 else
2448 e = toElemBin(irs,OPeq);
2449 return e;
2451 Lret:
2452 el_setLoc(e,loc);
2453 return e;
2456 /***************************************
2459 elem *AddAssignExp::toElem(IRState *irs)
2461 //printf("AddAssignExp::toElem() %s\n", toChars());
2462 elem *e;
2463 Type *tb1 = e1->type->toBasetype();
2464 Type *tb2 = e2->type->toBasetype();
2466 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
2467 (tb2->ty == Tarray || tb2->ty == Tsarray)
2470 error("Array operations not implemented");
2472 else
2473 e = toElemBin(irs,OPaddass);
2474 return e;
2478 /***************************************
2481 elem *MinAssignExp::toElem(IRState *irs)
2483 return toElemBin(irs,OPminass);
2486 /***************************************
2489 elem *CatAssignExp::toElem(IRState *irs)
2491 //printf("CatAssignExp::toElem('%s')\n", toChars());
2492 elem *e;
2493 Type *tb1 = e1->type->toBasetype();
2494 Type *tb2 = e2->type->toBasetype();
2496 if (tb1->ty == Tarray || tb2->ty == Tsarray)
2497 { elem *e1;
2498 elem *e2;
2499 elem *ep;
2501 e1 = this->e1->toElem(irs);
2502 e1 = el_una(OPaddr, TYnptr, e1);
2504 e2 = this->e2->toElem(irs);
2505 if (e2->Ety == TYstruct)
2507 e2 = el_una(OPstrpar, TYstruct, e2);
2508 e2->Enumbytes = e2->E1->Enumbytes;
2509 assert(e2->Enumbytes);
2512 Type *tb1n = tb1->nextOf()->toBasetype();
2513 if ((tb2->ty == Tarray || tb2->ty == Tsarray) &&
2514 tb1n->equals(tb2->nextOf()->toBasetype()))
2515 { // Append array
2516 #if 1
2517 ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
2518 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep);
2519 #else
2520 ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL);
2521 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep);
2522 #endif
2524 else
2525 { // Append element
2526 #if 1
2527 ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL);
2528 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep);
2529 #else
2530 ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL);
2531 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep);
2532 #endif
2534 el_setLoc(e,loc);
2536 else
2537 assert(0);
2538 return e;
2542 /***************************************
2545 elem *DivAssignExp::toElem(IRState *irs)
2547 return toElemBin(irs,OPdivass);
2551 /***************************************
2554 elem *ModAssignExp::toElem(IRState *irs)
2556 return toElemBin(irs,OPmodass);
2560 /***************************************
2563 elem *MulAssignExp::toElem(IRState *irs)
2565 return toElemBin(irs,OPmulass);
2569 /***************************************
2572 elem *ShlAssignExp::toElem(IRState *irs)
2573 { elem *e;
2575 e = toElemBin(irs,OPshlass);
2576 return e;
2580 /***************************************
2583 elem *ShrAssignExp::toElem(IRState *irs)
2585 return toElemBin(irs,OPshrass);
2589 /***************************************
2592 elem *UshrAssignExp::toElem(IRState *irs)
2594 elem *eleft = e1->toElem(irs);
2595 eleft->Ety = touns(eleft->Ety);
2596 elem *eright = e2->toElem(irs);
2597 elem *e = el_bin(OPshrass, type->totym(), eleft, eright);
2598 el_setLoc(e, loc);
2599 return e;
2603 /***************************************
2606 elem *AndAssignExp::toElem(IRState *irs)
2608 return toElemBin(irs,OPandass);
2612 /***************************************
2615 elem *OrAssignExp::toElem(IRState *irs)
2617 return toElemBin(irs,OPorass);
2621 /***************************************
2624 elem *XorAssignExp::toElem(IRState *irs)
2626 return toElemBin(irs,OPxorass);
2630 /***************************************
2633 elem *AndAndExp::toElem(IRState *irs)
2635 elem *e = toElemBin(irs,OPandand);
2636 if (global.params.cov && e2->loc.linnum)
2637 e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
2638 return e;
2642 /***************************************
2645 elem *OrOrExp::toElem(IRState *irs)
2647 elem *e = toElemBin(irs,OPoror);
2648 if (global.params.cov && e2->loc.linnum)
2649 e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2);
2650 return e;
2654 /***************************************
2657 elem *XorExp::toElem(IRState *irs)
2659 return toElemBin(irs,OPxor);
2663 /***************************************
2666 elem *AndExp::toElem(IRState *irs)
2668 return toElemBin(irs,OPand);
2672 /***************************************
2675 elem *OrExp::toElem(IRState *irs)
2677 return toElemBin(irs,OPor);
2681 /***************************************
2684 elem *ShlExp::toElem(IRState *irs)
2686 return toElemBin(irs, OPshl);
2690 /***************************************
2693 elem *ShrExp::toElem(IRState *irs)
2695 return toElemBin(irs,OPshr);
2699 /***************************************
2702 elem *UshrExp::toElem(IRState *irs)
2704 elem *eleft = e1->toElem(irs);
2705 eleft->Ety = touns(eleft->Ety);
2706 elem *eright = e2->toElem(irs);
2707 elem *e = el_bin(OPshr, type->totym(), eleft, eright);
2708 el_setLoc(e, loc);
2709 return e;
2712 elem *TypeDotIdExp::toElem(IRState *irs)
2714 print();
2715 assert(0);
2716 return NULL;
2719 elem *TypeExp::toElem(IRState *irs)
2721 #ifdef DEBUG
2722 printf("TypeExp::toElem()\n");
2723 #endif
2724 error("type %s is not an expression", toChars());
2725 return el_long(TYint, 0);
2728 elem *ScopeExp::toElem(IRState *irs)
2730 error("%s is not an expression", sds->toChars());
2731 return el_long(TYint, 0);
2734 elem *DotVarExp::toElem(IRState *irs)
2736 // *(&e + offset)
2738 //printf("DotVarExp::toElem('%s')\n", toChars());
2740 VarDeclaration *v = var->isVarDeclaration();
2741 if (!v)
2743 error("%s is not a field", var->toChars());
2746 elem *e = e1->toElem(irs);
2747 Type *tb1 = e1->type->toBasetype();
2748 if (tb1->ty != Tclass && tb1->ty != Tpointer)
2749 e = el_una(OPaddr, TYnptr, e);
2750 e = el_bin(OPadd, TYnptr, e, el_long(TYint, v ? v->offset : 0));
2751 e = el_una(OPind, type->totym(), e);
2752 if (tybasic(e->Ety) == TYstruct)
2754 e->Enumbytes = type->size();
2756 el_setLoc(e,loc);
2757 return e;
2760 elem *DelegateExp::toElem(IRState *irs)
2762 elem *e;
2763 elem *ethis;
2764 elem *ep;
2765 Symbol *sfunc;
2766 int directcall = 0;
2768 //printf("DelegateExp::toElem() '%s'\n", toChars());
2769 sfunc = func->toSymbol();
2770 if (func->isNested())
2772 ep = el_ptr(sfunc);
2773 ethis = getEthis(loc, irs, func);
2775 else
2777 ethis = e1->toElem(irs);
2778 if (e1->type->ty != Tclass && e1->type->ty != Tpointer)
2779 ethis = el_una(OPaddr, TYnptr, ethis);
2781 if (e1->op == TOKsuper)
2782 directcall = 1;
2784 if (!func->isThis())
2785 error("delegates are only for non-static functions");
2787 if (!func->isVirtual() ||
2788 directcall ||
2789 func->isFinal())
2791 ep = el_ptr(sfunc);
2793 else
2795 // Get pointer to function out of virtual table
2796 unsigned vindex;
2798 assert(ethis);
2799 ep = el_same(&ethis);
2800 ep = el_una(OPind, TYnptr, ep);
2801 vindex = func->vtblIndex;
2803 // Build *(ep + vindex * 4)
2804 ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4));
2805 ep = el_una(OPind,TYnptr,ep);
2808 // if (func->tintro)
2809 // func->error(loc, "cannot form delegate due to covariant return type");
2811 if (ethis->Eoper == OPcomma)
2813 ethis->E2 = el_pair(TYullong, ethis->E2, ep);
2814 ethis->Ety = TYullong;
2815 e = ethis;
2817 else
2818 e = el_pair(TYullong, ethis, ep);
2819 el_setLoc(e,loc);
2820 return e;
2823 elem *DotTypeExp::toElem(IRState *irs)
2825 // Just a pass-thru to e1
2826 elem *e;
2828 //printf("DotTypeExp::toElem() %s\n", toChars());
2829 e = e1->toElem(irs);
2830 el_setLoc(e,loc);
2831 return e;
2834 elem *CallExp::toElem(IRState *irs)
2836 //printf("CallExp::toElem('%s')\n", toChars());
2837 assert(e1->type);
2838 elem *ec;
2839 int directcall;
2840 FuncDeclaration *fd;
2841 Type *t1 = e1->type->toBasetype();
2842 Type *ectype = t1;
2844 elem *ehidden = irs->ehidden;
2845 irs->ehidden = NULL;
2847 directcall = 0;
2848 fd = NULL;
2849 if (e1->op == TOKdotvar && t1->ty != Tdelegate)
2850 { DotVarExp *dve = (DotVarExp *)e1;
2852 fd = dve->var->isFuncDeclaration();
2853 Expression *ex = dve->e1;
2854 while (1)
2856 switch (ex->op)
2858 case TOKsuper: // super.member() calls directly
2859 case TOKdottype: // type.member() calls directly
2860 directcall = 1;
2861 break;
2863 case TOKcast:
2864 ex = ((CastExp *)ex)->e1;
2865 continue;
2867 default:
2868 //ex->dump(0);
2869 break;
2871 break;
2873 ec = dve->e1->toElem(irs);
2874 ectype = dve->e1->type->toBasetype();
2876 else if (e1->op == TOKvar)
2878 fd = ((VarExp *)e1)->var->isFuncDeclaration();
2880 if (fd && fd->ident == Id::alloca &&
2881 !fd->fbody && fd->linkage == LINKc &&
2882 arguments && arguments->dim == 1)
2883 { Expression *arg = (Expression *)arguments->data[0];
2884 arg = arg->optimize(WANTvalue);
2885 if (arg->isConst() && arg->type->isintegral())
2886 { integer_t sz = arg->toInteger();
2887 if (sz > 0 && sz < 0x40000)
2889 // It's an alloca(sz) of a fixed amount.
2890 // Replace with an array allocated on the stack
2891 // of the same size: char[sz] tmp;
2893 Symbol *stmp;
2894 ::type *t;
2896 assert(!ehidden);
2897 t = type_allocn(TYarray, tschar);
2898 t->Tdim = sz;
2899 stmp = symbol_genauto(t);
2900 ec = el_ptr(stmp);
2901 el_setLoc(ec,loc);
2902 return ec;
2907 ec = e1->toElem(irs);
2909 else
2911 ec = e1->toElem(irs);
2913 ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments);
2914 el_setLoc(ec,loc);
2915 return ec;
2918 elem *AddrExp::toElem(IRState *irs)
2919 { elem *e;
2920 elem **pe;
2922 //printf("AddrExp::toElem('%s')\n", toChars());
2924 e = e1->toElem(irs);
2925 e = addressElem(e, e1->type);
2927 e->Ety = type->totym();
2928 el_setLoc(e,loc);
2929 return e;
2932 elem *PtrExp::toElem(IRState *irs)
2933 { elem *e;
2935 //printf("PtrExp::toElem() %s\n", toChars());
2936 e = e1->toElem(irs);
2937 e = el_una(OPind,type->totym(),e);
2938 if (tybasic(e->Ety) == TYstruct)
2940 e->Enumbytes = type->size();
2942 el_setLoc(e,loc);
2943 return e;
2946 elem *BoolExp::toElem(IRState *irs)
2947 { elem *e1;
2949 e1 = this->e1->toElem(irs);
2950 return el_una(OPbool,type->totym(),e1);
2953 elem *DeleteExp::toElem(IRState *irs)
2954 { elem *e;
2955 int rtl;
2956 Type *tb;
2958 //printf("DeleteExp::toElem()\n");
2959 if (e1->op == TOKindex)
2961 IndexExp *ae = (IndexExp *)(e1);
2962 tb = ae->e1->type->toBasetype();
2963 if (tb->ty == Taarray)
2965 TypeAArray *taa = (TypeAArray *)tb;
2966 elem *ea = ae->e1->toElem(irs);
2967 elem *ekey = ae->e2->toElem(irs);
2968 elem *ep;
2969 elem *keyti;
2971 if (ekey->Ety == TYstruct)
2973 ekey = el_una(OPstrpar, TYstruct, ekey);
2974 ekey->Enumbytes = ekey->E1->Enumbytes;
2975 assert(ekey->Enumbytes);
2978 Symbol *s = taa->aaGetSymbol("Del", 0);
2979 keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
2980 ep = el_params(ekey, keyti, ea, NULL);
2981 e = el_bin(OPcall, TYnptr, el_var(s), ep);
2982 goto Lret;
2985 //e1->type->print();
2986 e = e1->toElem(irs);
2987 rtl = RTLSYM_DELCLASS;
2988 tb = e1->type->toBasetype();
2989 switch (tb->ty)
2991 case Tarray:
2992 e = addressElem(e, e1->type);
2993 rtl = RTLSYM_DELARRAY;
2994 break;
2996 case Tclass:
2997 if (e1->op == TOKvar)
2998 { VarExp *ve = (VarExp *)e1;
2999 if (ve->var->isVarDeclaration() &&
3000 ve->var->isVarDeclaration()->onstack)
3002 rtl = RTLSYM_CALLFINALIZER;
3003 if (tb->isClassHandle()->isInterfaceDeclaration())
3004 rtl = RTLSYM_CALLINTERFACEFINALIZER;
3005 break;
3008 e = addressElem(e, e1->type);
3009 rtl = RTLSYM_DELCLASS;
3010 if (tb->isClassHandle()->isInterfaceDeclaration())
3011 rtl = RTLSYM_DELINTERFACE;
3012 break;
3014 case Tpointer:
3015 e = addressElem(e, e1->type);
3016 rtl = RTLSYM_DELMEMORY;
3017 break;
3019 default:
3020 assert(0);
3021 break;
3023 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
3025 Lret:
3026 el_setLoc(e,loc);
3027 return e;
3030 elem *CastExp::toElem(IRState *irs)
3031 { elem *e;
3032 TY fty;
3033 TY tty;
3034 tym_t ftym;
3035 tym_t ttym;
3036 enum OPER eop;
3037 Type *t;
3038 Type *tfrom;
3040 #if 0
3041 printf("CastExp::toElem()\n");
3042 print();
3043 printf("\tfrom: %s\n", e1->type->toChars());
3044 printf("\tto : %s\n", to->toChars());
3045 #endif
3047 e = e1->toElem(irs);
3048 tfrom = e1->type->toBasetype();
3049 t = to->toBasetype(); // skip over typedef's
3050 if (t->equals(tfrom))
3051 goto Lret;
3053 fty = tfrom->ty;
3054 //printf("fty = %d\n", fty);
3055 tty = t->ty;
3057 if (tty == Tpointer && fty == Tarray
3058 #if 0
3059 && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3060 #endif
3063 if (e->Eoper == OPvar)
3065 // e1 -> *(&e1 + 4)
3066 e = el_una(OPaddr, TYnptr, e);
3067 e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4));
3068 e = el_una(OPind,t->totym(),e);
3070 else
3072 // e1 -> (unsigned)(e1 >> 32)
3073 e = el_bin(OPshr, TYullong, e, el_long(TYint, 32));
3074 e = el_una(OP64_32, t->totym(), e);
3076 goto Lret;
3079 if (tty == Tpointer && fty == Tsarray
3080 #if 0
3081 && (t->next->ty == Tvoid || t->next->equals(e1->type->next))
3082 #endif
3085 // e1 -> &e1
3086 e = el_una(OPaddr, TYnptr, e);
3087 goto Lret;
3090 // Convert from static array to dynamic array
3091 if (tty == Tarray && fty == Tsarray)
3093 e = sarray_toDarray(tfrom, t, e);
3094 goto Lret;
3097 // Convert from dynamic array to dynamic array
3098 if (tty == Tarray && fty == Tarray)
3100 unsigned fsize = tfrom->nextOf()->size();
3101 unsigned tsize = t->nextOf()->size();
3103 if (fsize != tsize)
3105 elem *ep;
3107 ep = el_params(e, el_long(TYint, fsize), el_long(TYint, tsize), NULL);
3108 e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep);
3110 goto Lret;
3113 // Casting from base class to derived class requires a runtime check
3114 if (fty == Tclass && tty == Tclass)
3116 // Casting from derived class to base class is a no-op
3117 ClassDeclaration *cdfrom;
3118 ClassDeclaration *cdto;
3119 int offset;
3120 int rtl = RTLSYM_DYNAMIC_CAST;
3122 cdfrom = e1->type->isClassHandle();
3123 cdto = t->isClassHandle();
3124 if (cdfrom->isInterfaceDeclaration())
3126 rtl = RTLSYM_INTERFACE_CAST;
3127 if (cdfrom->isCOMinterface())
3129 if (cdto->isCOMinterface())
3131 /* Casting from a com interface to a com interface
3132 * is always a 'paint' operation
3134 goto Lret; // no-op
3137 /* Casting from a COM interface to a class
3138 * always results in null because there is no runtime
3139 * information available to do it.
3141 * Casting from a COM interface to a non-COM interface
3142 * always results in null because there's no way one
3143 * can be derived from the other.
3145 e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0));
3146 goto Lret;
3149 if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME)
3151 /* The offset from cdfrom=>cdto is known at compile time.
3154 //printf("offset = %d\n", offset);
3155 if (offset)
3156 { /* Rewrite cast as (e ? e + offset : null)
3158 elem *etmp;
3159 elem *ex;
3161 if (e1->op == TOKthis)
3162 { // Assume 'this' is never null, so skip null check
3163 e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset));
3165 else
3167 etmp = el_same(&e);
3168 ex = el_bin(OPadd, TYnptr, etmp, el_long(TYint, offset));
3169 ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0));
3170 e = el_bin(OPcond, TYnptr, e, ex);
3173 goto Lret; // no-op
3176 /* The offset from cdfrom=>cdto can only be determined at runtime.
3178 elem *ep;
3180 ep = el_param(el_ptr(cdto->toSymbol()), e);
3181 e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep);
3182 goto Lret;
3185 ftym = e->Ety;
3186 ttym = t->totym();
3187 if (ftym == ttym)
3188 goto Lret;
3190 switch (tty)
3192 case Tpointer:
3193 if (fty == Tdelegate)
3194 goto Lpaint;
3195 tty = Tuns32;
3196 break;
3198 case Tchar: tty = Tuns8; break;
3199 case Twchar: tty = Tuns16; break;
3200 case Tdchar: tty = Tuns32; break;
3201 case Tvoid: goto Lpaint;
3203 case Tbool:
3205 // Construct e?true:false
3206 elem *eq;
3208 e = el_una(OPbool, ttym, e);
3209 goto Lret;
3213 switch (fty)
3215 case Tpointer: fty = Tuns32; break;
3216 case Tchar: fty = Tuns8; break;
3217 case Twchar: fty = Tuns16; break;
3218 case Tdchar: fty = Tuns32; break;
3221 #define X(fty, tty) ((fty) * TMAX + (tty))
3222 Lagain:
3223 switch (X(fty,tty))
3225 #if 0
3226 case X(Tbit,Tint8):
3227 case X(Tbit,Tuns8):
3228 goto Lpaint;
3229 case X(Tbit,Tint16):
3230 case X(Tbit,Tuns16):
3231 case X(Tbit,Tint32):
3232 case X(Tbit,Tuns32): eop = OPu8_16; goto Leop;
3233 case X(Tbit,Tint64):
3234 case X(Tbit,Tuns64):
3235 case X(Tbit,Tfloat32):
3236 case X(Tbit,Tfloat64):
3237 case X(Tbit,Tfloat80):
3238 case X(Tbit,Tcomplex32):
3239 case X(Tbit,Tcomplex64):
3240 case X(Tbit,Tcomplex80):
3241 e = el_una(OPu8_16, TYuint, e);
3242 fty = Tuns32;
3243 goto Lagain;
3244 case X(Tbit,Timaginary32):
3245 case X(Tbit,Timaginary64):
3246 case X(Tbit,Timaginary80): goto Lzero;
3247 #endif
3248 /* ============================= */
3250 case X(Tbool,Tint8):
3251 case X(Tbool,Tuns8):
3252 goto Lpaint;
3253 case X(Tbool,Tint16):
3254 case X(Tbool,Tuns16):
3255 case X(Tbool,Tint32):
3256 case X(Tbool,Tuns32): eop = OPu8_16; goto Leop;
3257 case X(Tbool,Tint64):
3258 case X(Tbool,Tuns64):
3259 case X(Tbool,Tfloat32):
3260 case X(Tbool,Tfloat64):
3261 case X(Tbool,Tfloat80):
3262 case X(Tbool,Tcomplex32):
3263 case X(Tbool,Tcomplex64):
3264 case X(Tbool,Tcomplex80):
3265 e = el_una(OPu8_16, TYuint, e);
3266 fty = Tuns32;
3267 goto Lagain;
3268 case X(Tbool,Timaginary32):
3269 case X(Tbool,Timaginary64):
3270 case X(Tbool,Timaginary80): goto Lzero;
3272 /* ============================= */
3274 case X(Tint8,Tuns8): goto Lpaint;
3275 case X(Tint8,Tint16):
3276 case X(Tint8,Tuns16):
3277 case X(Tint8,Tint32):
3278 case X(Tint8,Tuns32): eop = OPs8_16; goto Leop;
3279 case X(Tint8,Tint64):
3280 case X(Tint8,Tuns64):
3281 case X(Tint8,Tfloat32):
3282 case X(Tint8,Tfloat64):
3283 case X(Tint8,Tfloat80):
3284 case X(Tint8,Tcomplex32):
3285 case X(Tint8,Tcomplex64):
3286 case X(Tint8,Tcomplex80):
3287 e = el_una(OPs8_16, TYint, e);
3288 fty = Tint32;
3289 goto Lagain;
3290 case X(Tint8,Timaginary32):
3291 case X(Tint8,Timaginary64):
3292 case X(Tint8,Timaginary80): goto Lzero;
3294 /* ============================= */
3296 case X(Tuns8,Tint8): goto Lpaint;
3297 case X(Tuns8,Tint16):
3298 case X(Tuns8,Tuns16):
3299 case X(Tuns8,Tint32):
3300 case X(Tuns8,Tuns32): eop = OPu8_16; goto Leop;
3301 case X(Tuns8,Tint64):
3302 case X(Tuns8,Tuns64):
3303 case X(Tuns8,Tfloat32):
3304 case X(Tuns8,Tfloat64):
3305 case X(Tuns8,Tfloat80):
3306 case X(Tuns8,Tcomplex32):
3307 case X(Tuns8,Tcomplex64):
3308 case X(Tuns8,Tcomplex80):
3309 e = el_una(OPu8_16, TYuint, e);
3310 fty = Tuns32;
3311 goto Lagain;
3312 case X(Tuns8,Timaginary32):
3313 case X(Tuns8,Timaginary64):
3314 case X(Tuns8,Timaginary80): goto Lzero;
3316 /* ============================= */
3318 case X(Tint16,Tint8):
3319 case X(Tint16,Tuns8): eop = OP16_8; goto Leop;
3320 case X(Tint16,Tuns16): goto Lpaint;
3321 case X(Tint16,Tint32):
3322 case X(Tint16,Tuns32): eop = OPs16_32; goto Leop;
3323 case X(Tint16,Tint64):
3324 case X(Tint16,Tuns64): e = el_una(OPs16_32, TYint, e);
3325 fty = Tint32;
3326 goto Lagain;
3327 case X(Tint16,Tfloat32):
3328 case X(Tint16,Tfloat64):
3329 case X(Tint16,Tfloat80):
3330 case X(Tint16,Tcomplex32):
3331 case X(Tint16,Tcomplex64):
3332 case X(Tint16,Tcomplex80):
3333 e = el_una(OPs16_d, TYdouble, e);
3334 fty = Tfloat64;
3335 goto Lagain;
3336 case X(Tint16,Timaginary32):
3337 case X(Tint16,Timaginary64):
3338 case X(Tint16,Timaginary80): goto Lzero;
3340 /* ============================= */
3342 case X(Tuns16,Tint8):
3343 case X(Tuns16,Tuns8): eop = OP16_8; goto Leop;
3344 case X(Tuns16,Tint16): goto Lpaint;
3345 case X(Tuns16,Tint32):
3346 case X(Tuns16,Tuns32): eop = OPu16_32; goto Leop;
3347 case X(Tuns16,Tint64):
3348 case X(Tuns16,Tuns64):
3349 case X(Tuns16,Tfloat64):
3350 case X(Tuns16,Tfloat32):
3351 case X(Tuns16,Tfloat80):
3352 case X(Tuns16,Tcomplex32):
3353 case X(Tuns16,Tcomplex64):
3354 case X(Tuns16,Tcomplex80):
3355 e = el_una(OPu16_32, TYuint, e);
3356 fty = Tuns32;
3357 goto Lagain;
3358 case X(Tuns16,Timaginary32):
3359 case X(Tuns16,Timaginary64):
3360 case X(Tuns16,Timaginary80): goto Lzero;
3362 /* ============================= */
3364 case X(Tint32,Tint8):
3365 case X(Tint32,Tuns8): e = el_una(OP32_16, TYshort, e);
3366 fty = Tint16;
3367 goto Lagain;
3368 case X(Tint32,Tint16):
3369 case X(Tint32,Tuns16): eop = OP32_16; goto Leop;
3370 case X(Tint32,Tuns32): goto Lpaint;
3371 case X(Tint32,Tint64):
3372 case X(Tint32,Tuns64): eop = OPs32_64; goto Leop;
3373 case X(Tint32,Tfloat32):
3374 case X(Tint32,Tfloat64):
3375 case X(Tint32,Tfloat80):
3376 case X(Tint32,Tcomplex32):
3377 case X(Tint32,Tcomplex64):
3378 case X(Tint32,Tcomplex80):
3379 e = el_una(OPs32_d, TYdouble, e);
3380 fty = Tfloat64;
3381 goto Lagain;
3382 case X(Tint32,Timaginary32):
3383 case X(Tint32,Timaginary64):
3384 case X(Tint32,Timaginary80): goto Lzero;
3386 /* ============================= */
3388 case X(Tuns32,Tint8):
3389 case X(Tuns32,Tuns8): e = el_una(OP32_16, TYshort, e);
3390 fty = Tuns16;
3391 goto Lagain;
3392 case X(Tuns32,Tint16):
3393 case X(Tuns32,Tuns16): eop = OP32_16; goto Leop;
3394 case X(Tuns32,Tint32): goto Lpaint;
3395 case X(Tuns32,Tint64):
3396 case X(Tuns32,Tuns64): eop = OPu32_64; goto Leop;
3397 case X(Tuns32,Tfloat32):
3398 case X(Tuns32,Tfloat64):
3399 case X(Tuns32,Tfloat80):
3400 case X(Tuns32,Tcomplex32):
3401 case X(Tuns32,Tcomplex64):
3402 case X(Tuns32,Tcomplex80):
3403 e = el_una(OPu32_d, TYdouble, e);
3404 fty = Tfloat64;
3405 goto Lagain;
3406 case X(Tuns32,Timaginary32):
3407 case X(Tuns32,Timaginary64):
3408 case X(Tuns32,Timaginary80): goto Lzero;
3410 /* ============================= */
3412 case X(Tint64,Tint8):
3413 case X(Tint64,Tuns8):
3414 case X(Tint64,Tint16):
3415 case X(Tint64,Tuns16): e = el_una(OP64_32, TYint, e);
3416 fty = Tint32;
3417 goto Lagain;
3418 case X(Tint64,Tint32):
3419 case X(Tint64,Tuns32): eop = OP64_32; goto Leop;
3420 case X(Tint64,Tuns64): goto Lpaint;
3421 case X(Tint64,Tfloat32):
3422 case X(Tint64,Tfloat64):
3423 case X(Tint64,Tfloat80):
3424 case X(Tint64,Tcomplex32):
3425 case X(Tint64,Tcomplex64):
3426 case X(Tint64,Tcomplex80):
3427 e = el_una(OPs64_d, TYdouble, e);
3428 fty = Tfloat64;
3429 goto Lagain;
3430 case X(Tint64,Timaginary32):
3431 case X(Tint64,Timaginary64):
3432 case X(Tint64,Timaginary80): goto Lzero;
3434 /* ============================= */
3436 case X(Tuns64,Tint8):
3437 case X(Tuns64,Tuns8):
3438 case X(Tuns64,Tint16):
3439 case X(Tuns64,Tuns16): e = el_una(OP64_32, TYint, e);
3440 fty = Tint32;
3441 goto Lagain;
3442 case X(Tuns64,Tint32):
3443 case X(Tuns64,Tuns32): eop = OP64_32; goto Leop;
3444 case X(Tuns64,Tint64): goto Lpaint;
3445 case X(Tuns64,Tfloat32):
3446 case X(Tuns64,Tfloat64):
3447 case X(Tuns64,Tfloat80):
3448 case X(Tuns64,Tcomplex32):
3449 case X(Tuns64,Tcomplex64):
3450 case X(Tuns64,Tcomplex80):
3451 e = el_una(OPu64_d, TYdouble, e);
3452 fty = Tfloat64;
3453 goto Lagain;
3454 case X(Tuns64,Timaginary32):
3455 case X(Tuns64,Timaginary64):
3456 case X(Tuns64,Timaginary80): goto Lzero;
3458 /* ============================= */
3460 case X(Tfloat32,Tint8):
3461 case X(Tfloat32,Tuns8):
3462 case X(Tfloat32,Tint16):
3463 case X(Tfloat32,Tuns16):
3464 case X(Tfloat32,Tint32):
3465 case X(Tfloat32,Tuns32):
3466 case X(Tfloat32,Tint64):
3467 case X(Tfloat32,Tuns64):
3468 case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e);
3469 fty = Tfloat64;
3470 goto Lagain;
3471 case X(Tfloat32,Tfloat64): eop = OPf_d; goto Leop;
3472 case X(Tfloat32,Timaginary32): goto Lzero;
3473 case X(Tfloat32,Timaginary64): goto Lzero;
3474 case X(Tfloat32,Timaginary80): goto Lzero;
3475 case X(Tfloat32,Tcomplex32):
3476 case X(Tfloat32,Tcomplex64):
3477 case X(Tfloat32,Tcomplex80):
3478 e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e);
3479 fty = Tcomplex32;
3480 goto Lagain;
3482 /* ============================= */
3484 case X(Tfloat64,Tint8):
3485 case X(Tfloat64,Tuns8): e = el_una(OPd_s16, TYshort, e);
3486 fty = Tint16;
3487 goto Lagain;
3488 case X(Tfloat64,Tint16): eop = OPd_s16; goto Leop;
3489 case X(Tfloat64,Tuns16): eop = OPd_u16; goto Leop;
3490 case X(Tfloat64,Tint32): eop = OPd_s32; goto Leop;
3491 case X(Tfloat64,Tuns32): eop = OPd_u32; goto Leop;
3492 case X(Tfloat64,Tint64): eop = OPd_s64; goto Leop;
3493 case X(Tfloat64,Tuns64): eop = OPd_u64; goto Leop;
3494 case X(Tfloat64,Tfloat32): eop = OPd_f; goto Leop;
3495 case X(Tfloat64,Tfloat80): eop = OPd_ld; goto Leop;
3496 case X(Tfloat64,Timaginary32): goto Lzero;
3497 case X(Tfloat64,Timaginary64): goto Lzero;
3498 case X(Tfloat64,Timaginary80): goto Lzero;
3499 case X(Tfloat64,Tcomplex32):
3500 case X(Tfloat64,Tcomplex64):
3501 case X(Tfloat64,Tcomplex80):
3502 e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e);
3503 fty = Tcomplex64;
3504 goto Lagain;
3506 /* ============================= */
3508 case X(Tfloat80,Tint8):
3509 case X(Tfloat80,Tuns8):
3510 case X(Tfloat80,Tint16):
3511 case X(Tfloat80,Tuns16):
3512 case X(Tfloat80,Tint32):
3513 case X(Tfloat80,Tuns32):
3514 case X(Tfloat80,Tint64):
3515 case X(Tfloat80,Tuns64):
3516 case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e);
3517 fty = Tfloat64;
3518 goto Lagain;
3519 case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop;
3520 case X(Tfloat80,Timaginary32): goto Lzero;
3521 case X(Tfloat80,Timaginary64): goto Lzero;
3522 case X(Tfloat80,Timaginary80): goto Lzero;
3523 case X(Tfloat80,Tcomplex32):
3524 case X(Tfloat80,Tcomplex64):
3525 case X(Tfloat80,Tcomplex80):
3526 e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0));
3527 fty = Tcomplex80;
3528 goto Lagain;
3530 /* ============================= */
3532 case X(Timaginary32,Tint8):
3533 case X(Timaginary32,Tuns8):
3534 case X(Timaginary32,Tint16):
3535 case X(Timaginary32,Tuns16):
3536 case X(Timaginary32,Tint32):
3537 case X(Timaginary32,Tuns32):
3538 case X(Timaginary32,Tint64):
3539 case X(Timaginary32,Tuns64):
3540 case X(Timaginary32,Tfloat32):
3541 case X(Timaginary32,Tfloat64):
3542 case X(Timaginary32,Tfloat80): goto Lzero;
3543 case X(Timaginary32,Timaginary64): eop = OPf_d; goto Leop;
3544 case X(Timaginary32,Timaginary80):
3545 e = el_una(OPf_d, TYidouble, e);
3546 fty = Timaginary64;
3547 goto Lagain;
3548 case X(Timaginary32,Tcomplex32):
3549 case X(Timaginary32,Tcomplex64):
3550 case X(Timaginary32,Tcomplex80):
3551 e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e);
3552 fty = Tcomplex32;
3553 goto Lagain;
3555 /* ============================= */
3557 case X(Timaginary64,Tint8):
3558 case X(Timaginary64,Tuns8):
3559 case X(Timaginary64,Tint16):
3560 case X(Timaginary64,Tuns16):
3561 case X(Timaginary64,Tint32):
3562 case X(Timaginary64,Tuns32):
3563 case X(Timaginary64,Tint64):
3564 case X(Timaginary64,Tuns64):
3565 case X(Timaginary64,Tfloat32):
3566 case X(Timaginary64,Tfloat64):
3567 case X(Timaginary64,Tfloat80): goto Lzero;
3568 case X(Timaginary64,Timaginary32): eop = OPd_f; goto Leop;
3569 case X(Timaginary64,Timaginary80): eop = OPd_ld; goto Leop;
3570 case X(Timaginary64,Tcomplex32):
3571 case X(Timaginary64,Tcomplex64):
3572 case X(Timaginary64,Tcomplex80):
3573 e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e);
3574 fty = Tcomplex64;
3575 goto Lagain;
3577 /* ============================= */
3579 case X(Timaginary80,Tint8):
3580 case X(Timaginary80,Tuns8):
3581 case X(Timaginary80,Tint16):
3582 case X(Timaginary80,Tuns16):
3583 case X(Timaginary80,Tint32):
3584 case X(Timaginary80,Tuns32):
3585 case X(Timaginary80,Tint64):
3586 case X(Timaginary80,Tuns64):
3587 case X(Timaginary80,Tfloat32):
3588 case X(Timaginary80,Tfloat64):
3589 case X(Timaginary80,Tfloat80): goto Lzero;
3590 case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e);
3591 fty = Timaginary64;
3592 goto Lagain;
3593 case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop;
3594 case X(Timaginary80,Tcomplex32):
3595 case X(Timaginary80,Tcomplex64):
3596 case X(Timaginary80,Tcomplex80):
3597 e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e);
3598 fty = Tcomplex80;
3599 goto Lagain;
3601 /* ============================= */
3603 case X(Tcomplex32,Tint8):
3604 case X(Tcomplex32,Tuns8):
3605 case X(Tcomplex32,Tint16):
3606 case X(Tcomplex32,Tuns16):
3607 case X(Tcomplex32,Tint32):
3608 case X(Tcomplex32,Tuns32):
3609 case X(Tcomplex32,Tint64):
3610 case X(Tcomplex32,Tuns64):
3611 case X(Tcomplex32,Tfloat32):
3612 case X(Tcomplex32,Tfloat64):
3613 case X(Tcomplex32,Tfloat80):
3614 e = el_una(OPc_r, TYfloat, e);
3615 fty = Tfloat32;
3616 goto Lagain;
3617 case X(Tcomplex32,Timaginary32):
3618 case X(Tcomplex32,Timaginary64):
3619 case X(Tcomplex32,Timaginary80):
3620 e = el_una(OPc_i, TYifloat, e);
3621 fty = Timaginary32;
3622 goto Lagain;
3623 case X(Tcomplex32,Tcomplex64):
3624 case X(Tcomplex32,Tcomplex80):
3625 e = el_una(OPf_d, TYcdouble, e);
3626 fty = Tcomplex64;
3627 goto Lagain;
3629 /* ============================= */
3631 case X(Tcomplex64,Tint8):
3632 case X(Tcomplex64,Tuns8):
3633 case X(Tcomplex64,Tint16):
3634 case X(Tcomplex64,Tuns16):
3635 case X(Tcomplex64,Tint32):
3636 case X(Tcomplex64,Tuns32):
3637 case X(Tcomplex64,Tint64):
3638 case X(Tcomplex64,Tuns64):
3639 case X(Tcomplex64,Tfloat32):
3640 case X(Tcomplex64,Tfloat64):
3641 case X(Tcomplex64,Tfloat80):
3642 e = el_una(OPc_r, TYdouble, e);
3643 fty = Tfloat64;
3644 goto Lagain;
3645 case X(Tcomplex64,Timaginary32):
3646 case X(Tcomplex64,Timaginary64):
3647 case X(Tcomplex64,Timaginary80):
3648 e = el_una(OPc_i, TYidouble, e);
3649 fty = Timaginary64;
3650 goto Lagain;
3651 case X(Tcomplex64,Tcomplex32): eop = OPd_f; goto Leop;
3652 case X(Tcomplex64,Tcomplex80): eop = OPd_ld; goto Leop;
3654 /* ============================= */
3656 case X(Tcomplex80,Tint8):
3657 case X(Tcomplex80,Tuns8):
3658 case X(Tcomplex80,Tint16):
3659 case X(Tcomplex80,Tuns16):
3660 case X(Tcomplex80,Tint32):
3661 case X(Tcomplex80,Tuns32):
3662 case X(Tcomplex80,Tint64):
3663 case X(Tcomplex80,Tuns64):
3664 case X(Tcomplex80,Tfloat32):
3665 case X(Tcomplex80,Tfloat64):
3666 case X(Tcomplex80,Tfloat80):
3667 e = el_una(OPc_r, TYldouble, e);
3668 fty = Tfloat80;
3669 goto Lagain;
3670 case X(Tcomplex80,Timaginary32):
3671 case X(Tcomplex80,Timaginary64):
3672 case X(Tcomplex80,Timaginary80):
3673 e = el_una(OPc_i, TYildouble, e);
3674 fty = Timaginary80;
3675 goto Lagain;
3676 case X(Tcomplex80,Tcomplex32):
3677 case X(Tcomplex80,Tcomplex64):
3678 e = el_una(OPld_d, TYcdouble, e);
3679 fty = Tcomplex64;
3680 goto Lagain;
3682 /* ============================= */
3684 default:
3685 if (fty == tty)
3686 goto Lpaint;
3687 //dump(0);
3688 //printf("fty = %d, tty = %d\n", fty, tty);
3689 error("e2ir: cannot cast from %s to %s", e1->type->toChars(), t->toChars());
3690 goto Lzero;
3692 Lzero:
3693 e = el_long(ttym, 0);
3694 break;
3696 Lpaint:
3697 e->Ety = ttym;
3698 break;
3700 Leop:
3701 e = el_una(eop, ttym, e);
3702 break;
3704 Lret:
3705 // Adjust for any type paints
3706 t = type->toBasetype();
3707 e->Ety = t->totym();
3709 el_setLoc(e,loc);
3710 return e;
3713 elem *ArrayLengthExp::toElem(IRState *irs)
3715 elem *e = e1->toElem(irs);
3716 e = el_una(OP64_32, type->totym(), e);
3717 el_setLoc(e,loc);
3718 return e;
3721 elem *SliceExp::toElem(IRState *irs)
3722 { elem *e;
3723 Type *t1;
3725 //printf("SliceExp::toElem()\n");
3726 t1 = e1->type->toBasetype();
3727 e = e1->toElem(irs);
3728 if (lwr)
3729 { elem *elwr;
3730 elem *elwr2;
3731 elem *eupr;
3732 elem *eptr;
3733 elem *einit;
3734 int sz;
3736 einit = resolveLengthVar(lengthVar, &e, t1);
3738 sz = t1->nextOf()->size();
3740 elwr = lwr->toElem(irs);
3741 eupr = upr->toElem(irs);
3743 elwr2 = el_same(&elwr);
3745 // Create an array reference where:
3746 // length is (upr - lwr)
3747 // pointer is (ptr + lwr*sz)
3748 // Combine as (length pair ptr)
3750 if (global.params.useArrayBounds)
3752 // Checks (unsigned compares):
3753 // upr <= array.length
3754 // lwr <= upr
3756 elem *c1;
3757 elem *c2;
3758 elem *ea;
3759 elem *eb;
3760 elem *eupr2;
3761 elem *elength;
3763 if (t1->ty == Tpointer)
3765 // Just do lwr <= upr check
3767 eupr2 = el_same(&eupr);
3768 eupr2->Ety = TYuint; // make sure unsigned comparison
3769 c1 = el_bin(OPle, TYint, elwr2, eupr2);
3770 c1 = el_combine(eupr, c1);
3771 goto L2;
3773 else if (t1->ty == Tsarray)
3774 { TypeSArray *tsa = (TypeSArray *)t1;
3775 integer_t length = tsa->dim->toInteger();
3777 elength = el_long(TYuint, length);
3778 goto L1;
3780 else if (t1->ty == Tarray)
3782 if (lengthVar)
3783 elength = el_var(lengthVar->toSymbol());
3784 else
3786 elength = e;
3787 e = el_same(&elength);
3788 elength = el_una(OP64_32, TYuint, elength);
3791 eupr2 = el_same(&eupr);
3792 c1 = el_bin(OPle, TYint, eupr, elength);
3793 eupr2->Ety = TYuint; // make sure unsigned comparison
3794 c2 = el_bin(OPle, TYint, elwr2, eupr2);
3795 c1 = el_bin(OPandand, TYint, c1, c2); // (c1 && c2)
3798 // Construct: (c1 || ModuleArray(line))
3799 Symbol *sassert;
3801 sassert = irs->blx->module->toModuleArray();
3802 ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
3803 eb = el_bin(OPoror,TYvoid,c1,ea);
3804 elwr = el_combine(elwr, eb);
3806 elwr2 = el_copytree(elwr2);
3807 eupr = el_copytree(eupr2);
3811 eptr = array_toPtr(e1->type, e);
3813 elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
3814 eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
3816 e = el_pair(TYullong, elength, eptr);
3817 e = el_combine(elwr, e);
3818 e = el_combine(einit, e);
3820 else if (t1->ty == Tsarray)
3822 e = sarray_toDarray(t1, NULL, e);
3824 el_setLoc(e,loc);
3825 return e;
3828 elem *IndexExp::toElem(IRState *irs)
3829 { elem *e;
3830 elem *n1 = e1->toElem(irs);
3831 elem *n2;
3832 elem *eb = NULL;
3833 Type *t1;
3835 //printf("IndexExp::toElem() %s\n", toChars());
3836 t1 = e1->type->toBasetype();
3837 if (t1->ty == Taarray)
3839 // set to:
3840 // *aaGet(aa, keyti, valuesize, index);
3842 TypeAArray *taa = (TypeAArray *)t1;
3843 elem *keyti;
3844 elem *ep;
3845 int vsize = taa->next->size();
3846 elem *valuesize;
3847 Symbol *s;
3849 // n2 becomes the index, also known as the key
3850 n2 = e2->toElem(irs);
3851 if (n2->Ety == TYstruct || n2->Ety == TYarray)
3853 n2 = el_una(OPstrpar, TYstruct, n2);
3854 n2->Enumbytes = n2->E1->Enumbytes;
3855 //printf("numbytes = %d\n", n2->Enumbytes);
3856 assert(n2->Enumbytes);
3858 valuesize = el_long(TYuint, vsize); // BUG: should be TYsize_t
3859 //printf("valuesize: "); elem_print(valuesize);
3860 if (modifiable)
3862 n1 = el_una(OPaddr, TYnptr, n1);
3863 s = taa->aaGetSymbol("Get", 1);
3865 else
3867 s = taa->aaGetSymbol("GetRvalue", 1);
3869 //printf("taa->key = %s\n", taa->key->toChars());
3870 keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
3871 //keyti = taa->key->getTypeInfo(NULL)->toElem(irs);
3872 //printf("keyti:\n");
3873 //elem_print(keyti);
3874 ep = el_params(n2, valuesize, keyti, n1, NULL);
3875 e = el_bin(OPcall, TYnptr, el_var(s), ep);
3876 if (global.params.useArrayBounds)
3878 elem *n;
3879 elem *ea;
3881 n = el_same(&e);
3883 // Construct: ((e || ModuleAssert(line)),n)
3884 Symbol *sassert;
3886 sassert = irs->blx->module->toModuleArray();
3887 ea = el_bin(OPcall,TYvoid,el_var(sassert),
3888 el_long(TYint, loc.linnum));
3889 e = el_bin(OPoror,TYvoid,e,ea);
3890 e = el_bin(OPcomma, TYnptr, e, n);
3892 e = el_una(OPind, type->totym(), e);
3893 if (tybasic(e->Ety) == TYstruct)
3894 e->Enumbytes = type->size();
3896 else
3897 { elem *einit;
3899 einit = resolveLengthVar(lengthVar, &n1, t1);
3900 n2 = e2->toElem(irs);
3902 if (global.params.useArrayBounds)
3904 elem *elength;
3905 elem *n2x;
3906 elem *ea;
3908 if (t1->ty == Tsarray)
3909 { TypeSArray *tsa = (TypeSArray *)t1;
3910 integer_t length = tsa->dim->toInteger();
3912 elength = el_long(TYuint, length);
3913 goto L1;
3915 else if (t1->ty == Tarray)
3917 elength = n1;
3918 n1 = el_same(&elength);
3919 elength = el_una(OP64_32, TYuint, elength);
3921 n2x = n2;
3922 n2 = el_same(&n2x);
3923 n2x = el_bin(OPlt, TYint, n2x, elength);
3925 // Construct: (n2x || ModuleAssert(line))
3926 Symbol *sassert;
3928 sassert = irs->blx->module->toModuleArray();
3929 ea = el_bin(OPcall,TYvoid,el_var(sassert),
3930 el_long(TYint, loc.linnum));
3931 eb = el_bin(OPoror,TYvoid,n2x,ea);
3935 n1 = array_toPtr(t1, n1);
3937 { elem *escale;
3939 escale = el_long(TYint, t1->nextOf()->size());
3940 n2 = el_bin(OPmul, TYint, n2, escale);
3941 e = el_bin(OPadd, TYnptr, n1, n2);
3942 e = el_una(OPind, type->totym(), e);
3943 if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray)
3944 { e->Ety = TYstruct;
3945 e->Enumbytes = type->size();
3949 eb = el_combine(einit, eb);
3950 e = el_combine(eb, e);
3952 el_setLoc(e,loc);
3953 return e;
3957 elem *TupleExp::toElem(IRState *irs)
3958 { elem *e = NULL;
3960 //printf("TupleExp::toElem() %s\n", toChars());
3961 for (size_t i = 0; i < exps->dim; i++)
3962 { Expression *el = (Expression *)exps->data[i];
3963 elem *ep = el->toElem(irs);
3965 e = el_combine(e, ep);
3967 return e;
3971 elem *ArrayLiteralExp::toElem(IRState *irs)
3972 { elem *e;
3973 size_t dim;
3975 //printf("ArrayLiteralExp::toElem() %s\n", toChars());
3976 if (elements)
3978 dim = elements->dim;
3979 e = el_long(TYint, dim);
3980 for (size_t i = 0; i < dim; i++)
3981 { Expression *el = (Expression *)elements->data[i];
3982 elem *ep = el->toElem(irs);
3984 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
3986 ep = el_una(OPstrpar, TYstruct, ep);
3987 ep->Enumbytes = el->type->size();
3989 e = el_param(ep, e);
3992 else
3993 { dim = 0;
3994 e = el_long(TYint, 0);
3996 Type *tb = type->toBasetype();
3997 #if 1
3998 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4000 // call _d_arrayliteralT(ti, dim, ...)
4001 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e);
4002 #else
4003 e = el_param(e, el_long(TYint, tb->next->size()));
4005 // call _d_arrayliteral(size, dim, ...)
4006 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e);
4007 #endif
4008 if (tb->ty == Tarray)
4010 e = el_pair(TYullong, el_long(TYint, dim), e);
4012 else if (tb->ty == Tpointer)
4015 else
4017 e = el_una(OPind,TYstruct,e);
4018 e->Enumbytes = type->size();
4021 el_setLoc(e,loc);
4022 return e;
4026 elem *AssocArrayLiteralExp::toElem(IRState *irs)
4027 { elem *e;
4028 size_t dim;
4030 //printf("AssocArrayLiteralExp::toElem() %s\n", toChars());
4031 dim = keys->dim;
4032 e = el_long(TYint, dim);
4033 for (size_t i = 0; i < dim; i++)
4034 { Expression *el = (Expression *)keys->data[i];
4036 for (int j = 0; j < 2; j++)
4038 elem *ep = el->toElem(irs);
4040 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray)
4042 ep = el_una(OPstrpar, TYstruct, ep);
4043 ep->Enumbytes = el->type->size();
4045 //printf("[%d] %s\n", i, el->toChars());
4046 //elem_print(ep);
4047 e = el_param(ep, e);
4048 el = (Expression *)values->data[i];
4051 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs));
4053 // call _d_assocarrayliteralT(ti, dim, ...)
4054 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e);
4056 el_setLoc(e,loc);
4057 return e;
4061 /*******************************************
4062 * Generate elem to zero fill contents of Symbol stmp
4063 * from *poffset..offset2.
4064 * May store anywhere from 0..maxoff, as this function
4065 * tries to use aligned int stores whereever possible.
4066 * Update *poffset to end of initialized hole; *poffset will be >= offset2.
4069 elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff)
4070 { elem *e = NULL;
4071 int basealign = 1;
4073 while (*poffset < offset2)
4074 { tym_t ty;
4075 elem *e1;
4077 if (tybasic(stmp->Stype->Tty) == TYnptr)
4078 e1 = el_var(stmp);
4079 else
4080 e1 = el_ptr(stmp);
4081 if (basealign)
4082 *poffset &= ~3;
4083 basealign = 1;
4084 size_t sz = maxoff - *poffset;
4085 switch (sz)
4086 { case 1: ty = TYchar; break;
4087 case 2: ty = TYshort; break;
4088 case 3:
4089 ty = TYshort;
4090 basealign = 0;
4091 break;
4092 default:
4093 ty = TYlong;
4094 break;
4096 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
4097 e1 = el_una(OPind, ty, e1);
4098 e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
4099 e = el_combine(e, e1);
4100 *poffset += tysize[ty];
4102 return e;
4105 elem *StructLiteralExp::toElem(IRState *irs)
4106 { elem *e;
4107 size_t dim;
4109 //printf("StructLiteralExp::toElem() %s\n", toChars());
4111 // struct symbol to initialize with the literal
4112 Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype());
4114 e = NULL;
4116 if (fillHoles)
4118 /* Initialize all alignment 'holes' to zero.
4119 * Do before initializing fields, as the hole filling process
4120 * can spill over into the fields.
4122 size_t offset = 0;
4123 for (size_t i = 0; i < sd->fields.dim; i++)
4125 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4126 VarDeclaration *v = s->isVarDeclaration();
4127 assert(v);
4129 e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize));
4130 size_t vend = v->offset + v->type->size();
4131 if (offset < vend)
4132 offset = vend;
4134 e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize));
4137 if (elements)
4139 dim = elements->dim;
4140 assert(dim <= sd->fields.dim);
4141 for (size_t i = 0; i < dim; i++)
4142 { Expression *el = (Expression *)elements->data[i];
4143 if (!el)
4144 continue;
4146 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
4147 VarDeclaration *v = s->isVarDeclaration();
4148 assert(v);
4150 elem *e1;
4151 if (tybasic(stmp->Stype->Tty) == TYnptr)
4152 { e1 = el_var(stmp);
4153 e1->EV.sp.Voffset = soffset;
4155 else
4156 { e1 = el_ptr(stmp);
4157 if (soffset)
4158 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
4160 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset));
4162 elem *ep = el->toElem(irs);
4164 Type *t1b = v->type->toBasetype();
4165 Type *t2b = el->type->toBasetype();
4166 if (t1b->ty == Tsarray)
4168 if (t2b->implicitConvTo(t1b))
4169 { elem *esize = el_long(TYsize_t, t1b->size());
4170 ep = array_toPtr(el->type, ep);
4171 e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
4173 else
4175 elem *edim = el_long(TYsize_t, t1b->size() / t2b->size());
4176 e1 = setArray(e1, edim, t2b, ep);
4179 else
4181 tym_t ty = v->type->totym();
4182 e1 = el_una(OPind, ty, e1);
4183 if (ty == TYstruct)
4184 e1->Enumbytes = v->type->size();
4185 e1 = el_bin(OPeq, ty, e1, ep);
4186 if (ty == TYstruct)
4187 { e1->Eoper = OPstreq;
4188 e1->Enumbytes = v->type->size();
4191 e = el_combine(e, e1);
4195 elem *ev = el_var(stmp);
4196 ev->Enumbytes = sd->structsize;
4197 e = el_combine(e, ev);
4198 el_setLoc(e,loc);
4199 return e;