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