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