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