root/trunk/src/optimize.c

Revision 685, 27.3 kB (checked in by walter, 2 years ago)

bugzilla 4465 ICE(symbol.c): immutable type inference with 2

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <assert.h>
13 #include <math.h>
14
15 #if __DMC__
16 #include <complex.h>
17 #endif
18
19 #include "lexer.h"
20 #include "mtype.h"
21 #include "expression.h"
22 #include "declaration.h"
23 #include "aggregate.h"
24 #include "init.h"
25
26
27 #ifdef IN_GCC
28 #include "d-gcc-real.h"
29
30 /* %% fix? */
31 extern "C" bool real_isnan (const real_t *);
32 #endif
33
34 static real_t zero;     // work around DMC bug for now
35
36
37 /*************************************
38  * If variable has a const initializer,
39  * return that initializer.
40  */
41
42 Expression *expandVar(int result, VarDeclaration *v)
43 {
44     //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null");
45
46     Expression *e = NULL;
47     if (!v)
48         return e;
49     if (!v->originalType && v->scope)   // semantic() not yet run
50         v->semantic (v->scope);
51
52     if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
53     {
54         if (!v->type)
55         {
56             //error("ICE");
57             return e;
58         }
59
60         Type *tb = v->type->toBasetype();
61         if (result & WANTinterpret ||
62             v->storage_class & STCmanifest ||
63             (tb->ty != Tsarray && tb->ty != Tstruct)
64            )
65         {
66             if (v->init)
67             {
68                 if (v->inuse)
69                 {   if (v->storage_class & STCmanifest)
70                         v->error("recursive initialization of constant");
71                     goto L1;
72                 }
73                 Expression *ei = v->init->toExpression();
74                 if (!ei)
75                     goto L1;
76                 if (ei->op == TOKconstruct || ei->op == TOKblit)
77                 {   AssignExp *ae = (AssignExp *)ei;
78                     ei = ae->e2;
79                     if (ei->isConst() != 1 && ei->op != TOKstring)
80                         goto L1;
81                     if (ei->type != v->type)
82                         goto L1;
83                 }
84                 if (v->scope)
85                 {
86                     v->inuse++;
87                     e = ei->syntaxCopy();
88                     e = e->semantic(v->scope);
89                     e = e->implicitCastTo(v->scope, v->type);
90                     // enabling this line causes test22 in test suite to fail
91                     //ei->type = e->type;
92                     v->scope = NULL;
93                     v->inuse--;
94                 }
95                 else if (!ei->type)
96                 {
97                     goto L1;
98                 }
99                 else
100                     // Should remove the copy() operation by
101                     // making all mods to expressions copy-on-write
102                     e = ei->copy();
103             }
104             else
105             {
106 #if 1
107                 goto L1;
108 #else
109                 // BUG: what if const is initialized in constructor?
110                 e = v->type->defaultInit();
111                 e->loc = e1->loc;
112 #endif
113             }
114             if (e->type != v->type)
115             {
116                 e = e->castTo(NULL, v->type);
117             }
118             v->inuse++;
119             e = e->optimize(result);
120             v->inuse--;
121         }
122     }
123 L1:
124     //if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars());
125     return e;
126 }
127
128
129 Expression *fromConstInitializer(int result, Expression *e1)
130 {
131     //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
132     //static int xx; if (xx++ == 10) assert(0);
133     Expression *e = e1;
134     if (e1->op == TOKvar)
135     {   VarExp *ve = (VarExp *)e1;
136         VarDeclaration *v = ve->var->isVarDeclaration();
137         int fwdref = (v && !v->originalType && v->scope);
138         e = expandVar(result, v);
139         if (e)
140         {
141             // If it is a comma expression involving a declaration, we mustn't
142             // perform a copy -- we'd get two declarations of the same variable.
143             // See bugzilla 4465.
144             if (e->op == TOKcomma && ((CommaExp *)e)->e1->op == TOKdeclaration)
145                  e = e1;
146             else
147
148             if (e->type != e1->type && e1->type && e1->type->ty != Tident)
149             {   // Type 'paint' operation
150                 e = e->copy();
151                 e->type = e1->type;
152             }
153             e->loc = e1->loc;
154         }
155         else
156             e = e1;
157     }
158     return e;
159 }
160
161
162 Expression *Expression::optimize(int result)
163 {
164     //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
165     return this;
166 }
167
168 Expression *VarExp::optimize(int result)
169 {
170     return fromConstInitializer(result, this);
171 }
172
173 Expression *TupleExp::optimize(int result)
174 {
175     for (size_t i = 0; i < exps->dim; i++)
176     {   Expression *e = (Expression *)exps->data[i];
177
178         e = e->optimize(WANTvalue | (result & WANTinterpret));
179         exps->data[i] = (void *)e;
180     }
181     return this;
182 }
183
184 Expression *ArrayLiteralExp::optimize(int result)
185 {
186     if (elements)
187     {
188         for (size_t i = 0; i < elements->dim; i++)
189         {   Expression *e = (Expression *)elements->data[i];
190
191             e = e->optimize(WANTvalue | (result & WANTinterpret));
192             elements->data[i] = (void *)e;
193         }
194     }
195     return this;
196 }
197
198 Expression *AssocArrayLiteralExp::optimize(int result)
199 {
200     assert(keys->dim == values->dim);
201     for (size_t i = 0; i < keys->dim; i++)
202     {   Expression *e = (Expression *)keys->data[i];
203
204         e = e->optimize(WANTvalue | (result & WANTinterpret));
205         keys->data[i] = (void *)e;
206
207         e = (Expression *)values->data[i];
208         e = e->optimize(WANTvalue | (result & WANTinterpret));
209         values->data[i] = (void *)e;
210     }
211     return this;
212 }
213
214 Expression *StructLiteralExp::optimize(int result)
215 {
216     if (elements)
217     {
218         for (size_t i = 0; i < elements->dim; i++)
219         {   Expression *e = (Expression *)elements->data[i];
220             if (!e)
221                 continue;
222             e = e->optimize(WANTvalue | (result & WANTinterpret));
223             elements->data[i] = (void *)e;
224         }
225     }
226     return this;
227 }
228
229 Expression *TypeExp::optimize(int result)
230 {
231     return this;
232 }
233
234 Expression *UnaExp::optimize(int result)
235 {
236     e1 = e1->optimize(result);
237     return this;
238 }
239
240 Expression *NegExp::optimize(int result)
241 {   Expression *e;
242
243     e1 = e1->optimize(result);
244     if (e1->isConst() == 1)
245     {
246         e = Neg(type, e1);
247     }
248     else
249         e = this;
250     return e;
251 }
252
253 Expression *ComExp::optimize(int result)
254 {   Expression *e;
255
256     e1 = e1->optimize(result);
257     if (e1->isConst() == 1)
258     {
259         e = Com(type, e1);
260     }
261     else
262         e = this;
263     return e;
264 }
265
266 Expression *NotExp::optimize(int result)
267 {   Expression *e;
268
269     e1 = e1->optimize(result);
270     if (e1->isConst() == 1)
271     {
272         e = Not(type, e1);
273     }
274     else
275         e = this;
276     return e;
277 }
278
279 Expression *BoolExp::optimize(int result)
280 {   Expression *e;
281
282     e1 = e1->optimize(result);
283     if (e1->isConst() == 1)
284     {
285         e = Bool(type, e1);
286     }
287     else
288         e = this;
289     return e;
290 }
291
292 Expression *AddrExp::optimize(int result)
293 {   Expression *e;
294
295     //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
296
297     /* Rewrite &(a,b) as (a,&b)
298      */
299     if (e1->op == TOKcomma)
300     {   CommaExp *ce = (CommaExp *)e1;
301         AddrExp *ae = new AddrExp(loc, ce->e2);
302         ae->type = type;
303         e = new CommaExp(ce->loc, ce->e1, ae);
304         e->type = type;
305         return e->optimize(result);
306     }
307
308     if (e1->op == TOKvar)
309     {   VarExp *ve = (VarExp *)e1;
310         if (ve->var->storage_class & STCmanifest)
311             e1 = e1->optimize(result);
312     }
313     else
314         e1 = e1->optimize(result);
315
316     // Convert &*ex to ex
317     if (e1->op == TOKstar)
318     {   Expression *ex;
319
320         ex = ((PtrExp *)e1)->e1;
321         if (type->equals(ex->type))
322             e = ex;
323         else
324         {
325             e = ex->copy();
326             e->type = type;
327         }
328         return e;
329     }
330     if (e1->op == TOKvar)
331     {   VarExp *ve = (VarExp *)e1;
332         if (!ve->var->isOut() && !ve->var->isRef() &&
333             !ve->var->isImportedSymbol())
334         {
335             SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
336             se->type = type;
337             return se;
338         }
339     }
340     if (e1->op == TOKindex)
341     {   // Convert &array[n] to &array+n
342         IndexExp *ae = (IndexExp *)e1;
343
344         if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
345         {
346             dinteger_t index = ae->e2->toInteger();
347             VarExp *ve = (VarExp *)ae->e1;
348             if (ve->type->ty == Tsarray
349                 && !ve->var->isImportedSymbol())
350             {
351                 TypeSArray *ts = (TypeSArray *)ve->type;
352                 dinteger_t dim = ts->dim->toInteger();
353                 if (index < 0 || index >= dim)
354                     error("array index %jd is out of bounds [0..%jd]", index, dim);
355                 e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
356                 e->type = type;
357                 return e;
358             }
359         }
360     }
361     return this;
362 }
363
364 Expression *PtrExp::optimize(int result)
365 {
366     //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
367     e1 = e1->optimize(result);
368     // Convert *&ex to ex
369     if (e1->op == TOKaddress)
370     {   Expression *e;
371         Expression *ex;
372
373         ex = ((AddrExp *)e1)->e1;
374         if (type->equals(ex->type))
375             e = ex;
376         else
377         {
378             e = ex->copy();
379             e->type = type;
380         }
381         return e;
382     }
383     // Constant fold *(&structliteral + offset)
384     if (e1->op == TOKadd)
385     {
386         Expression *e;
387         e = Ptr(type, e1);
388         if (e != EXP_CANT_INTERPRET)
389             return e;
390     }
391
392     if (e1->op == TOKsymoff)
393     {   SymOffExp *se = (SymOffExp *)e1;
394         VarDeclaration *v = se->var->isVarDeclaration();
395         Expression *e = expandVar(result, v);
396         if (e && e->op == TOKstructliteral)
397         {   StructLiteralExp *sle = (StructLiteralExp *)e;
398             e = sle->getField(type, se->offset);
399             if (e && e != EXP_CANT_INTERPRET)
400                 return e;
401         }
402     }
403     return this;
404 }
405
406 Expression *DotVarExp::optimize(int result)
407 {
408     //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars());
409     e1 = e1->optimize(result);
410
411     Expression *e = e1;
412
413     if (e1->op == TOKvar)
414     {   VarExp *ve = (VarExp *)e1;
415         VarDeclaration *v = ve->var->isVarDeclaration();
416         e = expandVar(result, v);
417     }
418
419     if (e && e->op == TOKstructliteral)
420     {   StructLiteralExp *sle = (StructLiteralExp *)e;
421         VarDeclaration *vf = var->isVarDeclaration();
422         if (vf)
423         {
424             Expression *e = sle->getField(type, vf->offset);
425             if (e && e != EXP_CANT_INTERPRET)
426                 return e;
427         }
428     }
429
430     return this;
431 }
432
433 Expression *NewExp::optimize(int result)
434 {
435     if (thisexp)
436         thisexp = thisexp->optimize(WANTvalue);
437
438     // Optimize parameters
439     if (newargs)
440     {
441         for (size_t i = 0; i < newargs->dim; i++)
442         {   Expression *e = (Expression *)newargs->data[i];
443
444             e = e->optimize(WANTvalue);
445             newargs->data[i] = (void *)e;
446         }
447     }
448
449     if (arguments)
450     {
451         for (size_t i = 0; i < arguments->dim; i++)
452         {   Expression *e = (Expression *)arguments->data[i];
453
454             e = e->optimize(WANTvalue);
455             arguments->data[i] = (void *)e;
456         }
457     }
458     return this;
459 }
460
461 Expression *CallExp::optimize(int result)
462 {
463     //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
464     Expression *e = this;
465
466     // Optimize parameters
467     if (arguments)
468     {
469         for (size_t i = 0; i < arguments->dim; i++)
470         {   Expression *e = (Expression *)arguments->data[i];
471
472             e = e->optimize(WANTvalue);
473             arguments->data[i] = (void *)e;
474         }
475     }
476
477     e1 = e1->optimize(result);
478 #if 1
479     if (result & WANTinterpret)
480     {
481         Expression *eresult = interpret(NULL);
482         if (eresult == EXP_CANT_INTERPRET)
483             return e;
484         if (eresult && eresult != EXP_VOID_INTERPRET)
485             e = eresult;
486         else
487             error("cannot evaluate %s at compile time", toChars());
488     }
489 #else
490     if (e1->op == TOKvar)
491     {
492         FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
493         if (fd)
494         {
495             enum BUILTIN b = fd->isBuiltin();
496             if (b)
497             {
498                 e = eval_builtin(b, arguments);
499                 if (!e)                 // failed
500                     e = this;           // evaluate at runtime
501             }
502             else if (result & WANTinterpret)
503             {
504                 Expression *eresult = fd->interpret(NULL, arguments);
505                 if (eresult && eresult != EXP_VOID_INTERPRET)
506                     e = eresult;
507                 else
508                     error("cannot evaluate %s at compile time", toChars());
509             }
510         }
511     }
512     else if (e1->op == TOKdotvar && result & WANTinterpret)
513     {   DotVarExp *dve = (DotVarExp *)e1;
514         FuncDeclaration *fd = dve->var->isFuncDeclaration();
515         if (fd)
516         {
517             Expression *eresult = fd->interpret(NULL, arguments, dve->e1);
518             if (eresult && eresult != EXP_VOID_INTERPRET)
519                 e = eresult;
520             else
521                 error("cannot evaluate %s at compile time", toChars());
522         }
523     }
524 #endif
525     return e;
526 }
527
528
529 Expression *CastExp::optimize(int result)
530 {
531     //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
532     //printf("from %s to %s\n", type->toChars(), to->toChars());
533     //printf("from %s\n", type->toChars());
534     //printf("e1->type %s\n", e1->type->toChars());
535     //printf("type = %p\n", type);
536     assert(type);
537     enum TOK op1 = e1->op;
538 #define X 0
539
540     Expression *e1old = e1;
541     e1 = e1->optimize(result);
542     e1 = fromConstInitializer(result, e1);
543
544     if (e1 == e1old &&
545         e1->op == TOKarrayliteral &&
546         type->toBasetype()->ty == Tpointer &&
547         e1->type->toBasetype()->ty != Tsarray)
548     {
549         // Casting this will result in the same expression, and
550         // infinite loop because of Expression::implicitCastTo()
551         return this;            // no change
552     }
553
554     if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
555         (type->ty == Tpointer || type->ty == Tarray) &&
556         e1->type->nextOf()->size() == type->nextOf()->size()
557        )
558     {
559         Expression *e = e1->castTo(NULL, type);
560         if (X) printf(" returning1 %s\n", e->toChars());
561         return e;
562     }
563
564     if (e1->op == TOKstructliteral &&
565         e1->type->implicitConvTo(type) >= MATCHconst)
566     {
567         e1->type = type;
568         if (X) printf(" returning2 %s\n", e1->toChars());
569         return e1;
570     }
571
572     /* The first test here is to prevent infinite loops
573      */
574     if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
575         return e1->castTo(NULL, to);
576     if (e1->op == TOKnull &&
577         (type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray))
578     {
579         e1->type = type;
580         if (X) printf(" returning3 %s\n", e1->toChars());
581         return e1;
582     }
583
584     if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
585     {
586         // See if we can remove an unnecessary cast
587         ClassDeclaration *cdfrom;
588         ClassDeclaration *cdto;
589         int offset;
590
591         cdfrom = e1->type->isClassHandle();
592         cdto   = type->isClassHandle();
593         if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
594         {
595             e1->type = type;
596             if (X) printf(" returning4 %s\n", e1->toChars());
597             return e1;
598         }
599     }
600
601     // We can convert 'head const' to mutable
602     if (to->constOf()->equals(e1->type->constOf()))
603 //    if (to->constConv(e1->type) >= MATCHconst)
604     {
605         e1->type = type;
606         if (X) printf(" returning5 %s\n", e1->toChars());
607         return e1;
608     }
609
610     Expression *e;
611
612     if (e1->isConst())
613     {
614         if (e1->op == TOKsymoff)
615         {
616             if (type->size() == e1->type->size() &&
617                 type->toBasetype()->ty != Tsarray)
618             {
619                 e1->type = type;
620                 return e1;
621             }
622             return this;
623         }
624         if (to->toBasetype()->ty == Tvoid)
625             e = this;
626         else
627             e = Cast(type, to, e1);
628     }
629     else
630         e = this;
631     if (X) printf(" returning6 %s\n", e->toChars());
632     return e;
633 #undef X
634 }
635
636 Expression *BinExp::optimize(int result)
637 {
638     //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
639     if (op != TOKconstruct && op != TOKblit)    // don't replace const variable with its initializer
640         e1 = e1->optimize(result);
641     e2 = e2->optimize(result);
642     if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
643     {
644         if (e2->isConst() == 1)
645         {
646             dinteger_t i2 = e2->toInteger();
647             d_uns64 sz = e1->type->size() * 8;
648             if (i2 < 0 || i2 > sz)
649             {   error("shift assign by %jd is outside the range 0..%zu", i2, sz);
650                 e2 = new IntegerExp(0);
651             }
652         }
653     }
654     return this;
655 }
656
657 Expression *AddExp::optimize(int result)
658 {   Expression *e;
659
660     //printf("AddExp::optimize(%s)\n", toChars());
661     e1 = e1->optimize(result);
662     e2 = e2->optimize(result);
663     if (e1->isConst() && e2->isConst())
664     {
665         if (e1->op == TOKsymoff && e2->op == TOKsymoff)
666             return this;
667         e = Add(type, e1, e2);
668     }
669     else
670         e = this;
671     return e;
672 }
673
674 Expression *MinExp::optimize(int result)
675 {   Expression *e;
676
677     e1 = e1->optimize(result);
678     e2 = e2->optimize(result);
679     if (e1->isConst() && e2->isConst())
680     {
681         if (e2->op == TOKsymoff)
682             return this;
683         e = Min(type, e1, e2);
684     }
685     else
686         e = this;
687     return e;
688 }
689
690 Expression *MulExp::optimize(int result)
691 {   Expression *e;
692
693     //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
694     e1 = e1->optimize(result);
695     e2 = e2->optimize(result);
696     if (e1->isConst() == 1 && e2->isConst() == 1)
697     {
698         e = Mul(type, e1, e2);
699     }
700     else
701         e = this;
702     return e;
703 }
704
705 Expression *DivExp::optimize(int result)
706 {   Expression *e;
707
708     //printf("DivExp::optimize(%s)\n", toChars());
709     e1 = e1->optimize(result);
710     e2 = e2->optimize(result);
711     if (e1->isConst() == 1 && e2->isConst() == 1)
712     {
713         e = Div(type, e1, e2);
714     }
715     else
716         e = this;
717     return e;
718 }
719
720 Expression *ModExp::optimize(int result)
721 {   Expression *e;
722
723     e1 = e1->optimize(result);
724     e2 = e2->optimize(result);
725     if (e1->isConst() == 1 && e2->isConst() == 1)
726     {
727         e = Mod(type, e1, e2);
728     }
729     else
730         e = this;
731     return e;
732 }
733
734 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
735 {   Expression *ex = e;
736
737     e->e1 = e->e1->optimize(result);
738     e->e2 = e->e2->optimize(result);
739     if (e->e2->isConst() == 1)
740     {
741         dinteger_t i2 = e->e2->toInteger();
742         d_uns64 sz = e->e1->type->size() * 8;
743         if (i2 < 0 || i2 > sz)
744         {   e->error("shift by %jd is outside the range 0..%zu", i2, sz);
745             e->e2 = new IntegerExp(0);
746         }
747         if (e->e1->isConst() == 1)
748             ex = (*shift)(e->type, e->e1, e->e2);
749     }
750     return ex;
751 }
752
753 Expression *ShlExp::optimize(int result)
754 {
755     //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
756     return shift_optimize(result, this, Shl);
757 }
758
759 Expression *ShrExp::optimize(int result)
760 {
761     //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
762     return shift_optimize(result, this, Shr);
763 }
764
765 Expression *UshrExp::optimize(int result)
766 {
767     //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
768     return shift_optimize(result, this, Ushr);
769 }
770
771 Expression *AndExp::optimize(int result)
772 {   Expression *e;
773
774     e1 = e1->optimize(result);
775     e2 = e2->optimize(result);
776     if (e1->isConst() == 1 && e2->isConst() == 1)
777         e = And(type, e1, e2);
778     else
779         e = this;
780     return e;
781 }
782
783 Expression *OrExp::optimize(int result)
784 {   Expression *e;
785
786     e1 = e1->optimize(result);
787     e2 = e2->optimize(result);
788     if (e1->isConst() == 1 && e2->isConst() == 1)
789         e = Or(type, e1, e2);
790     else
791         e = this;
792     return e;
793 }
794
795 Expression *XorExp::optimize(int result)
796 {   Expression *e;
797
798     e1 = e1->optimize(result);
799     e2 = e2->optimize(result);
800     if (e1->isConst() == 1 && e2->isConst() == 1)
801         e = Xor(type, e1, e2);
802     else
803         e = this;
804     return e;
805 }
806
807 Expression *CommaExp::optimize(int result)
808 {   Expression *e;
809
810     //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
811     // Comma needs special treatment, because it may
812     // contain compiler-generated declarations. We can interpret them, but
813     // otherwise we must NOT attempt to constant-fold them.
814     // In particular, if the comma returns a temporary variable, it needs
815     // to be an lvalue (this is particularly important for struct constructors)
816
817     if (result & WANTinterpret)
818     {   // Interpreting comma needs special treatment, because it may
819         // contain compiler-generated declarations.
820         e = interpret(NULL);
821         return (e == EXP_CANT_INTERPRET) ?  this : e;
822     }
823     // Don't constant fold if it is a compiler-generated temporary.
824     if (e1->op == TOKdeclaration)
825        return this;
826
827     e1 = e1->optimize(result & WANTinterpret);
828     e2 = e2->optimize(result);
829     if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
830     {
831         e = e2;
832         if (e)
833             e->type = type;
834     }
835     else
836         e = this;
837     //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
838     return e;
839 }
840
841 Expression *ArrayLengthExp::optimize(int result)
842 {   Expression *e;
843
844     //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
845     e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
846     e = this;
847     if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
848     {
849         e = ArrayLength(type, e1);
850     }
851     return e;
852 }
853
854 Expression *EqualExp::optimize(int result)
855 {   Expression *e;
856
857     //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
858     e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
859     e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
860     e = this;
861
862     Expression *e1 = fromConstInitializer(result, this->e1);
863     Expression *e2 = fromConstInitializer(result, this->e2);
864
865     e = Equal(op, type, e1, e2);
866     if (e == EXP_CANT_INTERPRET)
867         e = this;
868     return e;
869 }
870
871 Expression *IdentityExp::optimize(int result)
872 {
873     //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
874     e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
875     e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
876     Expression *e = this;
877
878     if ((this->e1->isConst()     && this->e2->isConst()) ||
879         (this->e1->op == TOKnull && this->e2->op == TOKnull))
880     {
881         e = Identity(op, type, this->e1, this->e2);
882         if (e == EXP_CANT_INTERPRET)
883             e = this;
884     }
885     return e;
886 }
887
888 Expression *IndexExp::optimize(int result)
889 {   Expression *e;
890
891     //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
892     Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
893     e1 = fromConstInitializer(result, e1);
894     if (this->e1->op == TOKvar)
895     {   VarExp *ve = (VarExp *)this->e1;
896         if (ve->var->storage_class & STCmanifest)
897         {   /* We generally don't want to have more than one copy of an
898              * array literal, but if it's an enum we have to because the
899              * enum isn't stored elsewhere. See Bugzilla 2559
900              */
901             this->e1 = e1;
902         }
903     }
904     e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
905     e = Index(type, e1, e2);
906     if (e == EXP_CANT_INTERPRET)
907         e = this;
908     return e;
909 }
910
911 Expression *SliceExp::optimize(int result)
912 {   Expression *e;
913
914     //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
915     e = this;
916     e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
917     if (!lwr)
918     {   if (e1->op == TOKstring)
919         {   // Convert slice of string literal into dynamic array
920             Type *t = e1->type->toBasetype();
921             if (t->nextOf())
922                 e = e1->castTo(NULL, t->nextOf()->arrayOf());
923         }
924         return e;
925     }
926     e1 = fromConstInitializer(result, e1);
927     lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
928     upr = upr->optimize(WANTvalue | (result & WANTinterpret));
929     e = Slice(type, e1, lwr, upr);
930     if (e == EXP_CANT_INTERPRET)
931         e = this;
932     //printf("-SliceExp::optimize() %s\n", e->toChars());
933     return e;
934 }
935
936 Expression *AndAndExp::optimize(int result)
937 {   Expression *e;
938
939     //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
940     e1 = e1->optimize(WANTflags | (result & WANTinterpret));
941     e = this;
942     if (e1->isBool(FALSE))
943     {
944         e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
945         e->type = type;
946         e = e->optimize(result);
947     }
948     else
949     {
950         e2 = e2->optimize(WANTflags | (result & WANTinterpret));
951         if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
952             error("void has no value");
953         if (e1->isConst())
954         {
955             if (e2->isConst())
956             {   int n1 = e1->isBool(1);
957                 int n2 = e2->isBool(1);
958
959                 e = new IntegerExp(loc, n1 && n2, type);
960             }
961             else if (e1->isBool(TRUE))
962                 e = new BoolExp(loc, e2, type);
963         }
964     }
965     return e;
966 }
967
968 Expression *OrOrExp::optimize(int result)
969 {   Expression *e;
970
971     e1 = e1->optimize(WANTflags | (result & WANTinterpret));
972     e = this;
973     if (e1->isBool(TRUE))
974     {   // Replace with (e1, 1)
975         e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
976         e->type = type;
977         e = e->optimize(result);
978     }
979     else
980     {
981         e2 = e2->optimize(WANTflags | (result & WANTinterpret));
982         if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
983             error("void has no value");
984         if (e1->isConst())
985         {
986             if (e2->isConst())
987             {   int n1 = e1->isBool(1);
988                 int n2 = e2->isBool(1);
989
990                 e = new IntegerExp(loc, n1 || n2, type);
991             }
992             else if (e1->isBool(FALSE))
993                 e = new BoolExp(loc, e2, type);
994         }
995     }
996     return e;
997 }
998
999 Expression *CmpExp::optimize(int result)
1000 {   Expression *e;
1001
1002     //printf("CmpExp::optimize() %s\n", toChars());
1003     e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
1004     e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
1005
1006     Expression *e1 = fromConstInitializer(result, this->e1);
1007     Expression *e2 = fromConstInitializer(result, this->e2);
1008
1009     e = Cmp(op, type, e1, e2);
1010     if (e == EXP_CANT_INTERPRET)
1011         e = this;
1012     return e;
1013 }
1014
1015 Expression *CatExp::optimize(int result)
1016 {   Expression *e;
1017
1018     //printf("CatExp::optimize(%d) %s\n", result, toChars());
1019     e1 = e1->optimize(result);
1020     e2 = e2->optimize(result);
1021     e = Cat(type, e1, e2);
1022     if (e == EXP_CANT_INTERPRET)
1023         e = this;
1024     return e;
1025 }
1026
1027
1028 Expression *CondExp::optimize(int result)
1029 {   Expression *e;
1030
1031     econd = econd->optimize(WANTflags | (result & WANTinterpret));
1032     if (econd->isBool(TRUE))
1033         e = e1->optimize(result);
1034     else if (econd->isBool(FALSE))
1035         e = e2->optimize(result);
1036     else
1037     {   e1 = e1->optimize(result);
1038         e2 = e2->optimize(result);
1039         e = this;
1040     }
1041     return e;
1042 }
Note: See TracBrowser for help on using the browser.