Mercurial > projects > ldc
annotate dmd/optimize.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 44b145be2ef5 |
children |
rev | line source |
---|---|
1587 | 1 |
2 // Compiler implementation of the D programming language | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
3 // Copyright (c) 1999-2010 by Digital Mars |
1587 | 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 // never try to interpret: it could change the semantics by turning | |
198 // const p = &s; into an something like const p = &(Struct()); | |
199 e1 = e1->optimize(result & ~WANTinterpret); | |
200 // Convert &*ex to ex | |
201 if (e1->op == TOKstar) | |
202 { Expression *ex; | |
203 | |
204 ex = ((PtrExp *)e1)->e1; | |
205 if (type->equals(ex->type)) | |
206 e = ex; | |
207 else | |
208 { | |
209 e = ex->copy(); | |
210 e->type = type; | |
211 } | |
212 return e; | |
213 } | |
214 #if !IN_LLVM | |
215 if (e1->op == TOKvar) | |
216 { VarExp *ve = (VarExp *)e1; | |
217 if (!ve->var->isOut() && !ve->var->isRef() && | |
218 !ve->var->isImportedSymbol()) | |
219 { | |
220 e = new SymOffExp(loc, ve->var, 0); | |
221 e->type = type; | |
222 return e; | |
223 } | |
224 } | |
225 if (e1->op == TOKindex) | |
226 { // Convert &array[n] to &array+n | |
227 IndexExp *ae = (IndexExp *)e1; | |
228 | |
229 if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) | |
230 { | |
231 dinteger_t index = ae->e2->toInteger(); | |
232 VarExp *ve = (VarExp *)ae->e1; | |
233 if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit | |
234 && !ve->var->isImportedSymbol()) | |
235 { | |
236 TypeSArray *ts = (TypeSArray *)ve->type; | |
237 dinteger_t dim = ts->dim->toInteger(); | |
238 if (index < 0 || index >= dim) | |
239 error("array index %jd is out of bounds [0..%jd]", index, dim); | |
240 e = new SymOffExp(loc, ve->var, index * ts->next->size()); | |
241 e->type = type; | |
242 return e; | |
243 } | |
244 } | |
245 } | |
246 #endif | |
247 return this; | |
248 } | |
249 | |
250 Expression *PtrExp::optimize(int result) | |
251 { | |
252 //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); | |
253 e1 = e1->optimize(result); | |
254 // Convert *&ex to ex | |
255 if (e1->op == TOKaddress) | |
256 { Expression *e; | |
257 Expression *ex; | |
258 | |
259 ex = ((AddrExp *)e1)->e1; | |
260 if (type->equals(ex->type)) | |
261 e = ex; | |
262 else | |
263 { | |
264 e = ex->copy(); | |
265 e->type = type; | |
266 } | |
267 return e; | |
268 } | |
269 // Constant fold *(&structliteral + offset) | |
270 if (e1->op == TOKadd) | |
271 { | |
272 Expression *e; | |
273 e = Ptr(type, e1); | |
274 if (e != EXP_CANT_INTERPRET) | |
275 return e; | |
276 } | |
277 | |
278 return this; | |
279 } | |
280 | |
281 Expression *DotVarExp::optimize(int result) | |
282 { | |
283 //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); | |
284 e1 = e1->optimize(result); | |
285 | |
286 #if DMDV2 | |
287 if (e1->op == TOKvar) | |
288 { VarExp *ve = (VarExp *)e1; | |
289 VarDeclaration *v = ve->var->isVarDeclaration(); | |
290 Expression *e = expandVar(result, v); | |
291 if (e && e->op == TOKstructliteral) | |
292 { StructLiteralExp *sle = (StructLiteralExp *)e; | |
293 VarDeclaration *vf = var->isVarDeclaration(); | |
294 if (vf) | |
295 { | |
296 e = sle->getField(type, vf->offset); | |
297 if (e && e != EXP_CANT_INTERPRET) | |
298 return e; | |
299 } | |
300 } | |
301 } | |
302 else | |
303 #endif | |
304 if (e1->op == TOKstructliteral) | |
305 { StructLiteralExp *sle = (StructLiteralExp *)e1; | |
306 VarDeclaration *vf = var->isVarDeclaration(); | |
307 if (vf) | |
308 { | |
309 Expression *e = sle->getField(type, vf->offset); | |
310 if (e && e != EXP_CANT_INTERPRET) | |
311 return e; | |
312 } | |
313 } | |
314 | |
315 return this; | |
316 } | |
317 | |
318 Expression *NewExp::optimize(int result) | |
319 { | |
320 if (thisexp) | |
321 thisexp = thisexp->optimize(WANTvalue); | |
322 | |
323 // Optimize parameters | |
324 if (newargs) | |
325 { | |
326 for (size_t i = 0; i < newargs->dim; i++) | |
327 { Expression *e = (Expression *)newargs->data[i]; | |
328 | |
329 e = e->optimize(WANTvalue); | |
330 newargs->data[i] = (void *)e; | |
331 } | |
332 } | |
333 | |
334 if (arguments) | |
335 { | |
336 for (size_t i = 0; i < arguments->dim; i++) | |
337 { Expression *e = (Expression *)arguments->data[i]; | |
338 | |
339 e = e->optimize(WANTvalue); | |
340 arguments->data[i] = (void *)e; | |
341 } | |
342 } | |
343 return this; | |
344 } | |
345 | |
346 Expression *CallExp::optimize(int result) | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
347 { |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
348 //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
349 Expression *e = this; |
1587 | 350 |
351 // Optimize parameters | |
352 if (arguments) | |
353 { | |
354 for (size_t i = 0; i < arguments->dim; i++) | |
355 { Expression *e = (Expression *)arguments->data[i]; | |
356 | |
357 e = e->optimize(WANTvalue); | |
358 arguments->data[i] = (void *)e; | |
359 } | |
360 } | |
361 | |
362 e1 = e1->optimize(result); | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
363 if (result & WANTinterpret) |
1587 | 364 { |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
365 Expression *eresult = interpret(NULL); |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
366 if (eresult == EXP_CANT_INTERPRET) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
367 return e; |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
368 if (eresult && eresult != EXP_VOID_INTERPRET) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
369 e = eresult; |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
370 else |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
371 error("cannot evaluate %s at compile time", toChars()); |
1587 | 372 } |
373 return e; | |
374 } | |
375 | |
376 | |
377 Expression *CastExp::optimize(int result) | |
378 { | |
379 //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); | |
380 //printf("from %s to %s\n", type->toChars(), to->toChars()); | |
381 //printf("from %s\n", type->toChars()); | |
382 //printf("e1->type %s\n", e1->type->toChars()); | |
383 //printf("type = %p\n", type); | |
384 assert(type); | |
385 enum TOK op1 = e1->op; | |
386 | |
387 e1 = e1->optimize(result); | |
388 if (result & WANTinterpret) | |
389 e1 = fromConstInitializer(e1); | |
390 | |
391 if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && | |
392 (type->ty == Tpointer || type->ty == Tarray) && | |
393 type->next->equals(e1->type->next) | |
394 ) | |
395 { | |
396 // make a copy before adjusting type to avoid | |
397 // messing up the type of an existing initializer | |
398 e1 = e1->syntaxCopy(); | |
399 e1->type = type; | |
400 return e1; | |
401 } | |
402 /* The first test here is to prevent infinite loops | |
403 */ | |
404 if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) | |
405 return e1->castTo(NULL, to); | |
406 if (e1->op == TOKnull && | |
407 (type->ty == Tpointer || type->ty == Tclass)) | |
408 { | |
409 e1->type = type; | |
410 return e1; | |
411 } | |
412 | |
413 if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) | |
414 { | |
415 // See if we can remove an unnecessary cast | |
416 ClassDeclaration *cdfrom; | |
417 ClassDeclaration *cdto; | |
418 int offset; | |
419 | |
420 cdfrom = e1->type->isClassHandle(); | |
421 cdto = type->isClassHandle(); | |
422 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) | |
423 { | |
424 e1->type = type; | |
425 return e1; | |
426 } | |
427 } | |
428 | |
429 Expression *e; | |
430 | |
431 if (e1->isConst()) | |
432 { | |
433 if (e1->op == TOKsymoff) | |
434 { | |
435 if (type->size() == e1->type->size() && | |
436 type->toBasetype()->ty != Tsarray) | |
437 { | |
438 e1->type = type; | |
439 return e1; | |
440 } | |
441 return this; | |
442 } | |
443 if (to->toBasetype()->ty == Tvoid) | |
444 e = this; | |
445 else | |
446 e = Cast(type, to, e1); | |
447 } | |
448 else | |
449 e = this; | |
450 return e; | |
451 } | |
452 | |
453 Expression *BinExp::optimize(int result) | |
454 { | |
455 //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); | |
456 e1 = e1->optimize(result); | |
457 e2 = e2->optimize(result); | |
458 if (op == TOKshlass || op == TOKshrass || op == TOKushrass) | |
459 { | |
460 if (e2->isConst() == 1) | |
461 { | |
462 dinteger_t i2 = e2->toInteger(); | |
463 d_uns64 sz = e1->type->size() * 8; | |
464 if (i2 < 0 || i2 > sz) | |
465 { error("shift assign by %jd is outside the range 0..%zu", i2, sz); | |
466 e2 = new IntegerExp(0); | |
467 } | |
468 } | |
469 } | |
470 return this; | |
471 } | |
472 | |
473 Expression *AddExp::optimize(int result) | |
474 { Expression *e; | |
475 | |
476 //printf("AddExp::optimize(%s)\n", toChars()); | |
477 e1 = e1->optimize(result); | |
478 e2 = e2->optimize(result); | |
479 if (e1->isConst() && e2->isConst()) | |
480 { | |
481 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
482 return this; | |
483 e = Add(type, e1, e2); | |
484 } | |
485 else | |
486 e = this; | |
487 return e; | |
488 } | |
489 | |
490 Expression *MinExp::optimize(int result) | |
491 { Expression *e; | |
492 | |
493 e1 = e1->optimize(result); | |
494 e2 = e2->optimize(result); | |
495 if (e1->isConst() && e2->isConst()) | |
496 { | |
497 if (e2->op == TOKsymoff) | |
498 return this; | |
499 e = Min(type, e1, e2); | |
500 } | |
501 else | |
502 e = this; | |
503 return e; | |
504 } | |
505 | |
506 Expression *MulExp::optimize(int result) | |
507 { Expression *e; | |
508 | |
509 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
510 e1 = e1->optimize(result); | |
511 e2 = e2->optimize(result); | |
512 if (e1->isConst() == 1 && e2->isConst() == 1) | |
513 { | |
514 e = Mul(type, e1, e2); | |
515 } | |
516 else | |
517 e = this; | |
518 return e; | |
519 } | |
520 | |
521 Expression *DivExp::optimize(int result) | |
522 { Expression *e; | |
523 | |
524 //printf("DivExp::optimize(%s)\n", toChars()); | |
525 e1 = e1->optimize(result); | |
526 e2 = e2->optimize(result); | |
527 if (e1->isConst() == 1 && e2->isConst() == 1) | |
528 { | |
529 e = Div(type, e1, e2); | |
530 } | |
531 else | |
532 e = this; | |
533 return e; | |
534 } | |
535 | |
536 Expression *ModExp::optimize(int result) | |
537 { Expression *e; | |
538 | |
539 e1 = e1->optimize(result); | |
540 e2 = e2->optimize(result); | |
541 if (e1->isConst() == 1 && e2->isConst() == 1) | |
542 { | |
543 e = Mod(type, e1, e2); | |
544 } | |
545 else | |
546 e = this; | |
547 return e; | |
548 } | |
549 | |
550 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) | |
551 { Expression *ex = e; | |
552 | |
553 e->e1 = e->e1->optimize(result); | |
554 e->e2 = e->e2->optimize(result); | |
555 if (e->e2->isConst() == 1) | |
556 { | |
557 dinteger_t i2 = e->e2->toInteger(); | |
558 d_uns64 sz = e->e1->type->size() * 8; | |
559 if (i2 < 0 || i2 > sz) | |
560 { e->error("shift by %jd is outside the range 0..%zu", i2, sz); | |
561 e->e2 = new IntegerExp(0); | |
562 } | |
563 if (e->e1->isConst() == 1) | |
564 ex = (*shift)(e->type, e->e1, e->e2); | |
565 } | |
566 return ex; | |
567 } | |
568 | |
569 Expression *ShlExp::optimize(int result) | |
570 { | |
571 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); | |
572 return shift_optimize(result, this, Shl); | |
573 } | |
574 | |
575 Expression *ShrExp::optimize(int result) | |
576 { | |
577 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); | |
578 return shift_optimize(result, this, Shr); | |
579 } | |
580 | |
581 Expression *UshrExp::optimize(int result) | |
582 { | |
583 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); | |
584 return shift_optimize(result, this, Ushr); | |
585 } | |
586 | |
587 Expression *AndExp::optimize(int result) | |
588 { Expression *e; | |
589 | |
590 e1 = e1->optimize(result); | |
591 e2 = e2->optimize(result); | |
592 if (e1->isConst() == 1 && e2->isConst() == 1) | |
593 e = And(type, e1, e2); | |
594 else | |
595 e = this; | |
596 return e; | |
597 } | |
598 | |
599 Expression *OrExp::optimize(int result) | |
600 { Expression *e; | |
601 | |
602 e1 = e1->optimize(result); | |
603 e2 = e2->optimize(result); | |
604 if (e1->isConst() == 1 && e2->isConst() == 1) | |
605 e = Or(type, e1, e2); | |
606 else | |
607 e = this; | |
608 return e; | |
609 } | |
610 | |
611 Expression *XorExp::optimize(int result) | |
612 { Expression *e; | |
613 | |
614 e1 = e1->optimize(result); | |
615 e2 = e2->optimize(result); | |
616 if (e1->isConst() == 1 && e2->isConst() == 1) | |
617 e = Xor(type, e1, e2); | |
618 else | |
619 e = this; | |
620 return e; | |
621 } | |
622 | |
623 Expression *CommaExp::optimize(int result) | |
624 { Expression *e; | |
625 | |
626 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
627 // Comma needs special treatment, because it may |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
628 // contain compiler-generated declarations. We can interpret them, but |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
629 // otherwise we must NOT attempt to constant-fold them. |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
630 // In particular, if the comma returns a temporary variable, it needs |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
631 // to be an lvalue (this is particularly important for struct constructors) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
632 |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
633 if (result & WANTinterpret) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
634 { // Interpreting comma needs special treatment, because it may |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
635 // contain compiler-generated declarations. |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
636 e = interpret(NULL); |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
637 return (e == EXP_CANT_INTERPRET) ? this : e; |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
638 } |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
639 // Don't constant fold if it is a compiler-generated temporary. |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
640 if (e1->op == TOKdeclaration) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
641 return this; |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
642 |
1587 | 643 e1 = e1->optimize(result & WANTinterpret); |
644 e2 = e2->optimize(result); | |
645 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
646 { | |
647 e = e2; | |
648 if (e) | |
649 e->type = type; | |
650 } | |
651 else | |
652 e = this; | |
653 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
654 return e; | |
655 } | |
656 | |
657 Expression *ArrayLengthExp::optimize(int result) | |
658 { Expression *e; | |
659 | |
660 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
661 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
662 e = this; | |
663 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
664 { | |
665 e = ArrayLength(type, e1); | |
666 } | |
667 return e; | |
668 } | |
669 | |
670 Expression *EqualExp::optimize(int result) | |
671 { Expression *e; | |
672 | |
673 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
674 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
675 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
676 e = this; | |
677 | |
678 Expression *e1 = fromConstInitializer(this->e1); | |
679 Expression *e2 = fromConstInitializer(this->e2); | |
680 | |
681 e = Equal(op, type, e1, e2); | |
682 if (e == EXP_CANT_INTERPRET) | |
683 e = this; | |
684 return e; | |
685 } | |
686 | |
687 Expression *IdentityExp::optimize(int result) | |
1622
a542ef277a84
Merge DMD r316: bugzilla 3628 can't cast null to int
Leandro Lucarella <llucax@gmail.com>
parents:
1599
diff
changeset
|
688 { |
1587 | 689 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); |
690 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
691 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
1622
a542ef277a84
Merge DMD r316: bugzilla 3628 can't cast null to int
Leandro Lucarella <llucax@gmail.com>
parents:
1599
diff
changeset
|
692 Expression *e = this; |
1587 | 693 |
1622
a542ef277a84
Merge DMD r316: bugzilla 3628 can't cast null to int
Leandro Lucarella <llucax@gmail.com>
parents:
1599
diff
changeset
|
694 if ((this->e1->isConst() && this->e2->isConst()) || |
a542ef277a84
Merge DMD r316: bugzilla 3628 can't cast null to int
Leandro Lucarella <llucax@gmail.com>
parents:
1599
diff
changeset
|
695 (this->e1->op == TOKnull && this->e2->op == TOKnull)) |
1587 | 696 { |
697 e = Identity(op, type, this->e1, this->e2); | |
698 if (e == EXP_CANT_INTERPRET) | |
699 e = this; | |
700 } | |
701 return e; | |
702 } | |
703 | |
704 Expression *IndexExp::optimize(int result) | |
705 { Expression *e; | |
706 | |
707 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
708 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
709 if (result & WANTinterpret) | |
710 e1 = fromConstInitializer(e1); | |
711 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
712 e = Index(type, e1, e2); | |
713 if (e == EXP_CANT_INTERPRET) | |
714 e = this; | |
715 return e; | |
716 } | |
717 | |
718 Expression *SliceExp::optimize(int result) | |
719 { Expression *e; | |
720 | |
721 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
722 e = this; | |
723 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
724 if (!lwr) | |
725 { if (e1->op == TOKstring) | |
726 { // Convert slice of string literal into dynamic array | |
727 Type *t = e1->type->toBasetype(); | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
728 if (t->nextOf()) |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1622
diff
changeset
|
729 e = e1->castTo(NULL, t->nextOf()->arrayOf()); |
1587 | 730 } |
731 return e; | |
732 } | |
733 if (result & WANTinterpret) | |
734 e1 = fromConstInitializer(e1); | |
735 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
736 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
737 e = Slice(type, e1, lwr, upr); | |
738 if (e == EXP_CANT_INTERPRET) | |
739 e = this; | |
740 return e; | |
741 } | |
742 | |
743 Expression *AndAndExp::optimize(int result) | |
744 { Expression *e; | |
745 | |
746 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
747 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
748 e = this; | |
749 if (e1->isBool(FALSE)) | |
750 { | |
751 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
752 e->type = type; | |
753 e = e->optimize(result); | |
754 } | |
755 else | |
756 { | |
757 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
758 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
759 error("void has no value"); | |
760 if (e1->isConst()) | |
761 { | |
762 if (e2->isConst()) | |
763 { int n1 = e1->isBool(1); | |
764 int n2 = e2->isBool(1); | |
765 | |
766 e = new IntegerExp(loc, n1 && n2, type); | |
767 } | |
768 else if (e1->isBool(TRUE)) | |
769 e = new BoolExp(loc, e2, type); | |
770 } | |
771 } | |
772 return e; | |
773 } | |
774 | |
775 Expression *OrOrExp::optimize(int result) | |
776 { Expression *e; | |
777 | |
778 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
779 e = this; | |
780 if (e1->isBool(TRUE)) | |
781 { // Replace with (e1, 1) | |
782 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
783 e->type = type; | |
784 e = e->optimize(result); | |
785 } | |
786 else | |
787 { | |
788 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
789 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
790 error("void has no value"); | |
791 if (e1->isConst()) | |
792 { | |
793 if (e2->isConst()) | |
794 { int n1 = e1->isBool(1); | |
795 int n2 = e2->isBool(1); | |
796 | |
797 e = new IntegerExp(loc, n1 || n2, type); | |
798 } | |
799 else if (e1->isBool(FALSE)) | |
800 e = new BoolExp(loc, e2, type); | |
801 } | |
802 } | |
803 return e; | |
804 } | |
805 | |
806 Expression *CmpExp::optimize(int result) | |
807 { Expression *e; | |
808 | |
809 //printf("CmpExp::optimize() %s\n", toChars()); | |
810 e1 = e1->optimize(result); | |
811 e2 = e2->optimize(result); | |
812 if (e1->isConst() == 1 && e2->isConst() == 1) | |
813 { | |
814 e = Cmp(op, type, this->e1, this->e2); | |
815 } | |
816 else | |
817 e = this; | |
818 return e; | |
819 } | |
820 | |
821 Expression *CatExp::optimize(int result) | |
822 { Expression *e; | |
823 | |
824 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
825 e1 = e1->optimize(result); | |
826 e2 = e2->optimize(result); | |
827 e = Cat(type, e1, e2); | |
828 if (e == EXP_CANT_INTERPRET) | |
829 e = this; | |
830 return e; | |
831 } | |
832 | |
833 | |
834 Expression *CondExp::optimize(int result) | |
835 { Expression *e; | |
836 | |
837 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
838 if (econd->isBool(TRUE)) | |
839 e = e1->optimize(result); | |
840 else if (econd->isBool(FALSE)) | |
841 e = e2->optimize(result); | |
842 else | |
843 { e1 = e1->optimize(result); | |
844 e2 = e2->optimize(result); | |
845 e = this; | |
846 } | |
847 return e; | |
848 } | |
849 | |
850 |