comparison dmd2/e2ir.c.nolink @ 758:f04dde6e882c

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