comparison dmd/optimize.c @ 1:c53b6e3fe49a trunk

[svn r5] Initial commit. Most things are very rough.
author lindquist
date Sat, 01 Sep 2007 21:43:27 +0200
parents
children 3cfcb944304e
comparison
equal deleted inserted replaced
0:a9e71648e74d 1:c53b6e3fe49a
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 expression is a variable with a const initializer,
40 * return that initializer.
41 */
42
43 Expression *fromConstInitializer(Expression *e1)
44 {
45 //printf("fromConstInitializer(%s)\n", e1->toChars());
46 if (e1->op == TOKvar)
47 { VarExp *ve = (VarExp *)e1;
48 VarDeclaration *v = ve->var->isVarDeclaration();
49 if (v && v->isConst() && v->init)
50 { Expression *ei = v->init->toExpression();
51 if (ei && ei->type)
52 e1 = ei;
53 }
54 }
55 return e1;
56 }
57
58
59 Expression *Expression::optimize(int result)
60 {
61 //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
62 return this;
63 }
64
65 Expression *VarExp::optimize(int result)
66 {
67 if (result & WANTinterpret)
68 {
69 return fromConstInitializer(this);
70 }
71 return this;
72 }
73
74 Expression *TupleExp::optimize(int result)
75 {
76 for (size_t i = 0; i < exps->dim; i++)
77 { Expression *e = (Expression *)exps->data[i];
78
79 e = e->optimize(WANTvalue | (result & WANTinterpret));
80 exps->data[i] = (void *)e;
81 }
82 return this;
83 }
84
85 Expression *ArrayLiteralExp::optimize(int result)
86 {
87 if (elements)
88 {
89 for (size_t i = 0; i < elements->dim; i++)
90 { Expression *e = (Expression *)elements->data[i];
91
92 e = e->optimize(WANTvalue | (result & WANTinterpret));
93 elements->data[i] = (void *)e;
94 }
95 }
96 return this;
97 }
98
99 Expression *AssocArrayLiteralExp::optimize(int result)
100 {
101 assert(keys->dim == values->dim);
102 for (size_t i = 0; i < keys->dim; i++)
103 { Expression *e = (Expression *)keys->data[i];
104
105 e = e->optimize(WANTvalue | (result & WANTinterpret));
106 keys->data[i] = (void *)e;
107
108 e = (Expression *)values->data[i];
109 e = e->optimize(WANTvalue | (result & WANTinterpret));
110 values->data[i] = (void *)e;
111 }
112 return this;
113 }
114
115 Expression *StructLiteralExp::optimize(int result)
116 {
117 if (elements)
118 {
119 for (size_t i = 0; i < elements->dim; i++)
120 { Expression *e = (Expression *)elements->data[i];
121 if (!e)
122 continue;
123 e = e->optimize(WANTvalue | (result & WANTinterpret));
124 elements->data[i] = (void *)e;
125 }
126 }
127 return this;
128 }
129
130 Expression *TypeExp::optimize(int result)
131 {
132 return this;
133 }
134
135 Expression *UnaExp::optimize(int result)
136 {
137 e1 = e1->optimize(result);
138 return this;
139 }
140
141 Expression *NegExp::optimize(int result)
142 { Expression *e;
143
144 e1 = e1->optimize(result);
145 if (e1->isConst() == 1)
146 {
147 e = Neg(type, e1);
148 }
149 else
150 e = this;
151 return e;
152 }
153
154 Expression *ComExp::optimize(int result)
155 { Expression *e;
156
157 e1 = e1->optimize(result);
158 if (e1->isConst() == 1)
159 {
160 e = Com(type, e1);
161 }
162 else
163 e = this;
164 return e;
165 }
166
167 Expression *NotExp::optimize(int result)
168 { Expression *e;
169
170 e1 = e1->optimize(result);
171 if (e1->isConst() == 1)
172 {
173 e = Not(type, e1);
174 }
175 else
176 e = this;
177 return e;
178 }
179
180 Expression *BoolExp::optimize(int result)
181 { Expression *e;
182
183 e1 = e1->optimize(result);
184 if (e1->isConst() == 1)
185 {
186 e = Bool(type, e1);
187 }
188 else
189 e = this;
190 return e;
191 }
192
193 Expression *AddrExp::optimize(int result)
194 { Expression *e;
195
196 //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
197 e1 = e1->optimize(result);
198 // Convert &*ex to ex
199 if (e1->op == TOKstar)
200 { Expression *ex;
201
202 ex = ((PtrExp *)e1)->e1;
203 if (type->equals(ex->type))
204 e = ex;
205 else
206 {
207 e = ex->copy();
208 e->type = type;
209 }
210 return e;
211 }
212 if (e1->op == TOKvar)
213 { VarExp *ve = (VarExp *)e1;
214 if (!ve->var->isOut() && !ve->var->isRef() &&
215 !ve->var->isImportedSymbol())
216 {
217 e = new SymOffExp(loc, ve->var, 0);
218 e->type = type;
219 return e;
220 }
221 }
222 if (e1->op == TOKindex)
223 { // Convert &array[n] to &array+n
224 IndexExp *ae = (IndexExp *)e1;
225
226 if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
227 {
228 integer_t index = ae->e2->toInteger();
229 VarExp *ve = (VarExp *)ae->e1;
230 if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit
231 && !ve->var->isImportedSymbol())
232 {
233 TypeSArray *ts = (TypeSArray *)ve->type;
234 integer_t dim = ts->dim->toInteger();
235 if (index < 0 || index >= dim)
236 error("array index %jd is out of bounds [0..%jd]", index, dim);
237 e = new SymOffExp(loc, ve->var, index * ts->next->size());
238 e->type = type;
239 return e;
240 }
241 }
242 }
243 return this;
244 }
245
246 Expression *PtrExp::optimize(int result)
247 {
248 //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
249 e1 = e1->optimize(result);
250 // Convert *&ex to ex
251 if (e1->op == TOKaddress)
252 { Expression *e;
253 Expression *ex;
254
255 ex = ((AddrExp *)e1)->e1;
256 if (type->equals(ex->type))
257 e = ex;
258 else
259 {
260 e = ex->copy();
261 e->type = type;
262 }
263 return e;
264 }
265 // Constant fold *(&structliteral + offset)
266 if (e1->op == TOKadd)
267 {
268 Expression *e;
269 e = Ptr(type, e1);
270 if (e != EXP_CANT_INTERPRET)
271 return e;
272 }
273
274 return this;
275 }
276
277 Expression *CallExp::optimize(int result)
278 { Expression *e = this;
279
280 e1 = e1->optimize(result);
281 if (e1->op == TOKvar && result & WANTinterpret)
282 {
283 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
284 if (fd)
285 {
286 Expression *eresult = fd->interpret(NULL, arguments);
287 if (eresult)
288 e = eresult;
289 else if (result & WANTinterpret)
290 error("cannot evaluate %s at compile time", toChars());
291 }
292 }
293 return e;
294 }
295
296
297 Expression *CastExp::optimize(int result)
298 {
299 //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
300 //printf("from %s to %s\n", type->toChars(), to->toChars());
301 //printf("from %s\n", type->toChars());
302 //printf("type = %p\n", type);
303 assert(type);
304 enum TOK op1 = e1->op;
305
306 e1 = e1->optimize(result);
307 if (result & WANTinterpret)
308 e1 = fromConstInitializer(e1);
309
310 if ((e1->op == TOKstring || e1->op == TOKarrayliteral) &&
311 (type->ty == Tpointer || type->ty == Tarray) &&
312 type->next->equals(e1->type->next)
313 )
314 {
315 e1->type = type;
316 return e1;
317 }
318 /* The first test here is to prevent infinite loops
319 */
320 if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral)
321 return e1->castTo(NULL, to);
322 if (e1->op == TOKnull &&
323 (type->ty == Tpointer || type->ty == Tclass))
324 {
325 e1->type = type;
326 return e1;
327 }
328
329 if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass)
330 {
331 // See if we can remove an unnecessary cast
332 ClassDeclaration *cdfrom;
333 ClassDeclaration *cdto;
334 int offset;
335
336 cdfrom = e1->type->isClassHandle();
337 cdto = type->isClassHandle();
338 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0)
339 {
340 e1->type = type;
341 return e1;
342 }
343 }
344
345 Expression *e;
346
347 if (e1->isConst())
348 {
349 if (e1->op == TOKsymoff)
350 {
351 if (type->size() == e1->type->size() &&
352 type->toBasetype()->ty != Tsarray)
353 {
354 e1->type = type;
355 return e1;
356 }
357 return this;
358 }
359 if (to->toBasetype()->ty == Tvoid)
360 e = this;
361 else
362 e = Cast(type, to, e1);
363 }
364 else
365 e = this;
366 return e;
367 }
368
369 Expression *BinExp::optimize(int result)
370 {
371 //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
372 e1 = e1->optimize(result);
373 e2 = e2->optimize(result);
374 return this;
375 }
376
377 Expression *AddExp::optimize(int result)
378 { Expression *e;
379
380 //printf("AddExp::optimize(%s)\n", toChars());
381 e1 = e1->optimize(result);
382 e2 = e2->optimize(result);
383 if (e1->isConst() && e2->isConst())
384 {
385 if (e1->op == TOKsymoff && e2->op == TOKsymoff)
386 return this;
387 e = Add(type, e1, e2);
388 }
389 else
390 e = this;
391 return e;
392 }
393
394 Expression *MinExp::optimize(int result)
395 { Expression *e;
396
397 e1 = e1->optimize(result);
398 e2 = e2->optimize(result);
399 if (e1->isConst() && e2->isConst())
400 {
401 if (e2->op == TOKsymoff)
402 return this;
403 e = Min(type, e1, e2);
404 }
405 else
406 e = this;
407 return e;
408 }
409
410 Expression *MulExp::optimize(int result)
411 { Expression *e;
412
413 //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
414 e1 = e1->optimize(result);
415 e2 = e2->optimize(result);
416 if (e1->isConst() == 1 && e2->isConst() == 1)
417 {
418 e = Mul(type, e1, e2);
419 }
420 else
421 e = this;
422 return e;
423 }
424
425 Expression *DivExp::optimize(int result)
426 { Expression *e;
427
428 //printf("DivExp::optimize(%s)\n", toChars());
429 e1 = e1->optimize(result);
430 e2 = e2->optimize(result);
431 if (e1->isConst() == 1 && e2->isConst() == 1)
432 {
433 e = Div(type, e1, e2);
434 }
435 else
436 e = this;
437 return e;
438 }
439
440 Expression *ModExp::optimize(int result)
441 { Expression *e;
442
443 e1 = e1->optimize(result);
444 e2 = e2->optimize(result);
445 if (e1->isConst() == 1 && e2->isConst() == 1)
446 {
447 e = Mod(type, e1, e2);
448 }
449 else
450 e = this;
451 return e;
452 }
453
454 Expression *ShlExp::optimize(int result)
455 { Expression *e;
456
457 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
458 e1 = e1->optimize(result);
459 e2 = e2->optimize(result);
460 e = this;
461 if (e2->isConst() == 1)
462 {
463 integer_t i2 = e2->toInteger();
464 if (i2 < 0 || i2 > e1->type->size() * 8)
465 { error("shift left by %jd exceeds %zu", i2, e2->type->size() * 8);
466 e2 = new IntegerExp(0);
467 }
468 if (e1->isConst() == 1)
469 e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
470 }
471 return e;
472 }
473
474 Expression *ShrExp::optimize(int result)
475 { Expression *e;
476
477 e1 = e1->optimize(result);
478 e2 = e2->optimize(result);
479
480 if (e1->isConst() == 1 && e2->isConst() == 1)
481 {
482 e = Shr(type, e1, e2);
483 }
484 else
485 e = this;
486 return e;
487 }
488
489 Expression *UshrExp::optimize(int result)
490 { Expression *e;
491
492 //printf("UshrExp::optimize() %s\n", toChars());
493 e1 = e1->optimize(result);
494 e2 = e2->optimize(result);
495
496 if (e1->isConst() == 1 && e2->isConst() == 1)
497 {
498 e = Ushr(type, e1, e2);
499 }
500 else
501 e = this;
502 return e;
503 }
504
505 Expression *AndExp::optimize(int result)
506 { Expression *e;
507
508 e1 = e1->optimize(result);
509 e2 = e2->optimize(result);
510 if (e1->isConst() == 1 && e2->isConst() == 1)
511 e = And(type, e1, e2);
512 else
513 e = this;
514 return e;
515 }
516
517 Expression *OrExp::optimize(int result)
518 { Expression *e;
519
520 e1 = e1->optimize(result);
521 e2 = e2->optimize(result);
522 if (e1->isConst() == 1 && e2->isConst() == 1)
523 e = Or(type, e1, e2);
524 else
525 e = this;
526 return e;
527 }
528
529 Expression *XorExp::optimize(int result)
530 { Expression *e;
531
532 e1 = e1->optimize(result);
533 e2 = e2->optimize(result);
534 if (e1->isConst() == 1 && e2->isConst() == 1)
535 e = Xor(type, e1, e2);
536 else
537 e = this;
538 return e;
539 }
540
541 Expression *CommaExp::optimize(int result)
542 { Expression *e;
543
544 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
545 e1 = e1->optimize(result & WANTinterpret);
546 e2 = e2->optimize(result);
547 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2))
548 {
549 e = e2;
550 if (e)
551 e->type = type;
552 }
553 else
554 e = this;
555 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
556 return e;
557 }
558
559 Expression *ArrayLengthExp::optimize(int result)
560 { Expression *e;
561
562 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
563 e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
564 e = this;
565 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral)
566 {
567 e = ArrayLength(type, e1);
568 }
569 return e;
570 }
571
572 Expression *EqualExp::optimize(int result)
573 { Expression *e;
574
575 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
576 e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
577 e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
578 e = this;
579
580 Expression *e1 = fromConstInitializer(this->e1);
581 Expression *e2 = fromConstInitializer(this->e2);
582
583 e = Equal(op, type, e1, e2);
584 if (e == EXP_CANT_INTERPRET)
585 e = this;
586 return e;
587 }
588
589 Expression *IdentityExp::optimize(int result)
590 { Expression *e;
591
592 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
593 e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
594 e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
595 e = this;
596
597 if (this->e1->isConst() && this->e2->isConst())
598 {
599 e = Identity(op, type, this->e1, this->e2);
600 }
601 return e;
602 }
603
604 Expression *IndexExp::optimize(int result)
605 { Expression *e;
606
607 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
608 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret));
609 if (result & WANTinterpret)
610 e1 = fromConstInitializer(e1);
611 e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
612 e = Index(type, e1, e2);
613 if (e == EXP_CANT_INTERPRET)
614 e = this;
615 return e;
616 }
617
618 Expression *SliceExp::optimize(int result)
619 { Expression *e;
620
621 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
622 e = this;
623 e1 = e1->optimize(WANTvalue | (result & WANTinterpret));
624 if (!lwr)
625 { if (e1->op == TOKstring)
626 { // Convert slice of string literal into dynamic array
627 Type *t = e1->type->toBasetype();
628 if (t->next)
629 e = e1->castTo(NULL, t->next->arrayOf());
630 }
631 return e;
632 }
633 if (result & WANTinterpret)
634 e1 = fromConstInitializer(e1);
635 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret));
636 upr = upr->optimize(WANTvalue | (result & WANTinterpret));
637 e = Slice(type, e1, lwr, upr);
638 if (e == EXP_CANT_INTERPRET)
639 e = this;
640 return e;
641 }
642
643 Expression *AndAndExp::optimize(int result)
644 { Expression *e;
645
646 //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
647 e1 = e1->optimize(WANTflags | (result & WANTinterpret));
648 e = this;
649 if (e1->isBool(FALSE))
650 {
651 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
652 e->type = type;
653 e = e->optimize(result);
654 }
655 else
656 {
657 e2 = e2->optimize(WANTflags | (result & WANTinterpret));
658 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
659 error("void has no value");
660 if (e1->isConst())
661 {
662 if (e2->isConst())
663 { int n1 = e1->isBool(1);
664 int n2 = e2->isBool(1);
665
666 e = new IntegerExp(loc, n1 && n2, type);
667 }
668 else if (e1->isBool(TRUE))
669 e = new BoolExp(loc, e2, type);
670 }
671 }
672 return e;
673 }
674
675 Expression *OrOrExp::optimize(int result)
676 { Expression *e;
677
678 e1 = e1->optimize(WANTflags | (result & WANTinterpret));
679 e = this;
680 if (e1->isBool(TRUE))
681 { // Replace with (e1, 1)
682 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
683 e->type = type;
684 e = e->optimize(result);
685 }
686 else
687 {
688 e2 = e2->optimize(WANTflags | (result & WANTinterpret));
689 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors)
690 error("void has no value");
691 if (e1->isConst())
692 {
693 if (e2->isConst())
694 { int n1 = e1->isBool(1);
695 int n2 = e2->isBool(1);
696
697 e = new IntegerExp(loc, n1 || n2, type);
698 }
699 else if (e1->isBool(FALSE))
700 e = new BoolExp(loc, e2, type);
701 }
702 }
703 return e;
704 }
705
706 Expression *CmpExp::optimize(int result)
707 { Expression *e;
708
709 //printf("CmpExp::optimize() %s\n", toChars());
710 e1 = e1->optimize(result);
711 e2 = e2->optimize(result);
712 if (e1->isConst() == 1 && e2->isConst() == 1)
713 {
714 e = Cmp(op, type, this->e1, this->e2);
715 }
716 else
717 e = this;
718 return e;
719 }
720
721 Expression *CatExp::optimize(int result)
722 { Expression *e;
723
724 //printf("CatExp::optimize(%d) %s\n", result, toChars());
725 e1 = e1->optimize(result);
726 e2 = e2->optimize(result);
727 e = Cat(type, e1, e2);
728 if (e == EXP_CANT_INTERPRET)
729 e = this;
730 return e;
731 }
732
733
734 Expression *CondExp::optimize(int result)
735 { Expression *e;
736
737 econd = econd->optimize(WANTflags | (result & WANTinterpret));
738 if (econd->isBool(TRUE))
739 e = e1->optimize(result);
740 else if (econd->isBool(FALSE))
741 e = e2->optimize(result);
742 else
743 { e1 = e1->optimize(result);
744 e2 = e2->optimize(result);
745 e = this;
746 }
747 return e;
748 }
749
750