Mercurial > projects > ldc
annotate dmd/optimize.c @ 650:aa6a0b7968f7
Added test case for bug #100
Removed dubious check for not emitting static private global in other modules without access. This should be handled properly somewhere else, it's causing unresolved global errors for stuff that should work (in MiniD)
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 05 Oct 2008 17:28:15 +0200 |
parents | 870652a9af23 |
children | 330f999ade44 |
rev | line source |
---|---|
336 | 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 !IN_LLVM | |
213 if (e1->op == TOKvar) | |
214 { VarExp *ve = (VarExp *)e1; | |
215 if (!ve->var->isOut() && !ve->var->isRef() && | |
216 !ve->var->isImportedSymbol()) | |
217 { | |
218 e = new SymOffExp(loc, ve->var, 0); | |
219 e->type = type; | |
220 return e; | |
221 } | |
222 } | |
223 if (e1->op == TOKindex) | |
224 { // Convert &array[n] to &array+n | |
225 IndexExp *ae = (IndexExp *)e1; | |
226 | |
227 if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) | |
228 { | |
229 integer_t index = ae->e2->toInteger(); | |
230 VarExp *ve = (VarExp *)ae->e1; | |
231 if (ve->type->ty == Tsarray && ve->type->next->ty != Tbit | |
232 && !ve->var->isImportedSymbol()) | |
233 { | |
234 TypeSArray *ts = (TypeSArray *)ve->type; | |
235 integer_t dim = ts->dim->toInteger(); | |
236 if (index < 0 || index >= dim) | |
237 error("array index %lld is out of bounds [0..%lld]", index, dim); | |
238 e = new SymOffExp(loc, ve->var, index * ts->next->size()); | |
239 e->type = type; | |
240 return e; | |
241 } | |
242 } | |
243 } | |
244 #endif | |
245 return this; | |
246 } | |
247 | |
248 Expression *PtrExp::optimize(int result) | |
249 { | |
250 //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); | |
251 e1 = e1->optimize(result); | |
252 // Convert *&ex to ex | |
253 if (e1->op == TOKaddress) | |
254 { Expression *e; | |
255 Expression *ex; | |
256 | |
257 ex = ((AddrExp *)e1)->e1; | |
258 if (type->equals(ex->type)) | |
259 e = ex; | |
260 else | |
261 { | |
262 e = ex->copy(); | |
263 e->type = type; | |
264 } | |
265 return e; | |
266 } | |
267 // Constant fold *(&structliteral + offset) | |
268 if (e1->op == TOKadd) | |
269 { | |
270 Expression *e; | |
271 e = Ptr(type, e1); | |
272 if (e != EXP_CANT_INTERPRET) | |
273 return e; | |
274 } | |
275 | |
276 return this; | |
277 } | |
278 | |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
279 Expression *DotVarExp::optimize(int result) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
280 { |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
281 e1 = e1->optimize(result); |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
282 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
283 // Constant fold structliteral.member |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
284 if (e1->op == TOKstructliteral) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
285 { StructLiteralExp *se = (StructLiteralExp *)e1; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
286 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
287 VarDeclaration* v; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
288 if (v = var->isVarDeclaration()) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
289 { |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
290 Expression *e = se->getField(type, v->offset); |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
291 if (!e) |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
292 e = EXP_CANT_INTERPRET; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
293 return e; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
294 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
295 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
296 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
297 return this; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
298 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
299 |
336 | 300 Expression *CallExp::optimize(int result) |
301 { Expression *e = this; | |
302 | |
303 e1 = e1->optimize(result); | |
304 if (e1->op == TOKvar && result & WANTinterpret) | |
305 { | |
306 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
307 if (fd) | |
308 { | |
309 Expression *eresult = fd->interpret(NULL, arguments); | |
310 if (eresult && eresult != EXP_VOID_INTERPRET) | |
311 e = eresult; | |
312 else if (result & WANTinterpret) | |
313 error("cannot evaluate %s at compile time", toChars()); | |
314 } | |
315 } | |
316 return e; | |
317 } | |
318 | |
319 | |
320 Expression *CastExp::optimize(int result) | |
321 { | |
322 //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); | |
323 //printf("from %s to %s\n", type->toChars(), to->toChars()); | |
324 //printf("from %s\n", type->toChars()); | |
325 //printf("type = %p\n", type); | |
326 assert(type); | |
327 enum TOK op1 = e1->op; | |
328 | |
329 e1 = e1->optimize(result); | |
330 if (result & WANTinterpret) | |
331 e1 = fromConstInitializer(e1); | |
332 | |
333 if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && | |
334 (type->ty == Tpointer || type->ty == Tarray) && | |
335 type->next->equals(e1->type->next) | |
336 ) | |
337 { | |
338 e1->type = type; | |
339 return e1; | |
340 } | |
341 /* The first test here is to prevent infinite loops | |
342 */ | |
343 if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) | |
344 return e1->castTo(NULL, to); | |
345 if (e1->op == TOKnull && | |
346 (type->ty == Tpointer || type->ty == Tclass)) | |
347 { | |
348 e1->type = type; | |
349 return e1; | |
350 } | |
351 | |
352 if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) | |
353 { | |
354 // See if we can remove an unnecessary cast | |
355 ClassDeclaration *cdfrom; | |
356 ClassDeclaration *cdto; | |
357 int offset; | |
358 | |
359 cdfrom = e1->type->isClassHandle(); | |
360 cdto = type->isClassHandle(); | |
361 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) | |
362 { | |
363 e1->type = type; | |
364 return e1; | |
365 } | |
366 } | |
367 | |
368 Expression *e; | |
369 | |
370 if (e1->isConst()) | |
371 { | |
372 if (e1->op == TOKsymoff) | |
373 { | |
374 if (type->size() == e1->type->size() && | |
375 type->toBasetype()->ty != Tsarray) | |
376 { | |
377 e1->type = type; | |
378 return e1; | |
379 } | |
380 return this; | |
381 } | |
382 if (to->toBasetype()->ty == Tvoid) | |
383 e = this; | |
384 else | |
385 e = Cast(type, to, e1); | |
386 } | |
387 else | |
388 e = this; | |
389 return e; | |
390 } | |
391 | |
392 Expression *BinExp::optimize(int result) | |
393 { | |
394 //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); | |
395 e1 = e1->optimize(result); | |
396 e2 = e2->optimize(result); | |
397 if (op == TOKshlass || op == TOKshrass || op == TOKushrass) | |
398 { | |
399 if (e2->isConst() == 1) | |
400 { | |
401 integer_t i2 = e2->toInteger(); | |
402 d_uns64 sz = e1->type->size() * 8; | |
403 if (i2 < 0 || i2 > sz) | |
404 { | |
405 error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz); | |
406 e2 = new IntegerExp(0); | |
407 } | |
408 } | |
409 } | |
410 return this; | |
411 } | |
412 | |
413 Expression *AddExp::optimize(int result) | |
414 { Expression *e; | |
415 | |
416 //printf("AddExp::optimize(%s)\n", toChars()); | |
417 e1 = e1->optimize(result); | |
418 e2 = e2->optimize(result); | |
419 if (e1->isConst() && e2->isConst()) | |
420 { | |
421 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
422 return this; | |
423 e = Add(type, e1, e2); | |
424 } | |
425 else | |
426 e = this; | |
427 return e; | |
428 } | |
429 | |
430 Expression *MinExp::optimize(int result) | |
431 { Expression *e; | |
432 | |
433 e1 = e1->optimize(result); | |
434 e2 = e2->optimize(result); | |
435 if (e1->isConst() && e2->isConst()) | |
436 { | |
437 if (e2->op == TOKsymoff) | |
438 return this; | |
439 e = Min(type, e1, e2); | |
440 } | |
441 else | |
442 e = this; | |
443 return e; | |
444 } | |
445 | |
446 Expression *MulExp::optimize(int result) | |
447 { Expression *e; | |
448 | |
449 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
450 e1 = e1->optimize(result); | |
451 e2 = e2->optimize(result); | |
452 if (e1->isConst() == 1 && e2->isConst() == 1) | |
453 { | |
454 e = Mul(type, e1, e2); | |
455 } | |
456 else | |
457 e = this; | |
458 return e; | |
459 } | |
460 | |
461 Expression *DivExp::optimize(int result) | |
462 { Expression *e; | |
463 | |
464 //printf("DivExp::optimize(%s)\n", toChars()); | |
465 e1 = e1->optimize(result); | |
466 e2 = e2->optimize(result); | |
467 if (e1->isConst() == 1 && e2->isConst() == 1) | |
468 { | |
469 e = Div(type, e1, e2); | |
470 } | |
471 else | |
472 e = this; | |
473 return e; | |
474 } | |
475 | |
476 Expression *ModExp::optimize(int result) | |
477 { Expression *e; | |
478 | |
479 e1 = e1->optimize(result); | |
480 e2 = e2->optimize(result); | |
481 if (e1->isConst() == 1 && e2->isConst() == 1) | |
482 { | |
483 e = Mod(type, e1, e2); | |
484 } | |
485 else | |
486 e = this; | |
487 return e; | |
488 } | |
489 | |
490 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) | |
491 { Expression *ex = e; | |
492 | |
493 e->e1 = e->e1->optimize(result); | |
494 e->e2 = e->e2->optimize(result); | |
495 if (e->e2->isConst() == 1) | |
496 { | |
497 integer_t i2 = e->e2->toInteger(); | |
498 d_uns64 sz = e->e1->type->size() * 8; | |
499 if (i2 < 0 || i2 > sz) | |
500 { | |
501 error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz); | |
502 e->e2 = new IntegerExp(0); | |
503 } | |
504 if (e->e1->isConst() == 1) | |
505 ex = (*shift)(e->type, e->e1, e->e2); | |
506 } | |
507 return ex; | |
508 } | |
509 | |
510 Expression *ShlExp::optimize(int result) | |
511 { | |
512 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); | |
513 return shift_optimize(result, this, Shl); | |
514 } | |
515 | |
516 Expression *ShrExp::optimize(int result) | |
517 { | |
518 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); | |
519 return shift_optimize(result, this, Shr); | |
520 } | |
521 | |
522 Expression *UshrExp::optimize(int result) | |
523 { | |
524 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); | |
525 return shift_optimize(result, this, Ushr); | |
526 } | |
527 | |
528 Expression *AndExp::optimize(int result) | |
529 { Expression *e; | |
530 | |
531 e1 = e1->optimize(result); | |
532 e2 = e2->optimize(result); | |
533 if (e1->isConst() == 1 && e2->isConst() == 1) | |
534 e = And(type, e1, e2); | |
535 else | |
536 e = this; | |
537 return e; | |
538 } | |
539 | |
540 Expression *OrExp::optimize(int result) | |
541 { Expression *e; | |
542 | |
543 e1 = e1->optimize(result); | |
544 e2 = e2->optimize(result); | |
545 if (e1->isConst() == 1 && e2->isConst() == 1) | |
546 e = Or(type, e1, e2); | |
547 else | |
548 e = this; | |
549 return e; | |
550 } | |
551 | |
552 Expression *XorExp::optimize(int result) | |
553 { Expression *e; | |
554 | |
555 e1 = e1->optimize(result); | |
556 e2 = e2->optimize(result); | |
557 if (e1->isConst() == 1 && e2->isConst() == 1) | |
558 e = Xor(type, e1, e2); | |
559 else | |
560 e = this; | |
561 return e; | |
562 } | |
563 | |
564 Expression *CommaExp::optimize(int result) | |
565 { Expression *e; | |
566 | |
567 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
568 e1 = e1->optimize(result & WANTinterpret); | |
569 e2 = e2->optimize(result); | |
570 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
571 { | |
572 e = e2; | |
573 if (e) | |
574 e->type = type; | |
575 } | |
576 else | |
577 e = this; | |
578 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
579 return e; | |
580 } | |
581 | |
582 Expression *ArrayLengthExp::optimize(int result) | |
583 { Expression *e; | |
584 | |
585 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
586 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
587 e = this; | |
588 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
589 { | |
590 e = ArrayLength(type, e1); | |
591 } | |
592 return e; | |
593 } | |
594 | |
595 Expression *EqualExp::optimize(int result) | |
596 { Expression *e; | |
597 | |
598 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
599 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
600 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
601 e = this; | |
602 | |
603 Expression *e1 = fromConstInitializer(this->e1); | |
604 Expression *e2 = fromConstInitializer(this->e2); | |
605 | |
606 e = Equal(op, type, e1, e2); | |
607 if (e == EXP_CANT_INTERPRET) | |
608 e = this; | |
609 return e; | |
610 } | |
611 | |
612 Expression *IdentityExp::optimize(int result) | |
613 { Expression *e; | |
614 | |
615 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); | |
616 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
617 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
618 e = this; | |
619 | |
620 if (this->e1->isConst() && this->e2->isConst()) | |
621 { | |
622 e = Identity(op, type, this->e1, this->e2); | |
623 } | |
624 return e; | |
625 } | |
626 | |
627 Expression *IndexExp::optimize(int result) | |
628 { Expression *e; | |
629 | |
630 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
631 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
632 if (result & WANTinterpret) | |
633 e1 = fromConstInitializer(e1); | |
634 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
635 e = Index(type, e1, e2); | |
636 if (e == EXP_CANT_INTERPRET) | |
637 e = this; | |
638 return e; | |
639 } | |
640 | |
641 Expression *SliceExp::optimize(int result) | |
642 { Expression *e; | |
643 | |
644 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
645 e = this; | |
646 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
647 if (!lwr) | |
648 { if (e1->op == TOKstring) | |
649 { // Convert slice of string literal into dynamic array | |
650 Type *t = e1->type->toBasetype(); | |
651 if (t->next) | |
652 e = e1->castTo(NULL, t->next->arrayOf()); | |
653 } | |
654 return e; | |
655 } | |
656 if (result & WANTinterpret) | |
657 e1 = fromConstInitializer(e1); | |
658 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
659 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
660 e = Slice(type, e1, lwr, upr); | |
661 if (e == EXP_CANT_INTERPRET) | |
662 e = this; | |
663 return e; | |
664 } | |
665 | |
666 Expression *AndAndExp::optimize(int result) | |
667 { Expression *e; | |
668 | |
669 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
670 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
671 e = this; | |
672 if (e1->isBool(FALSE)) | |
673 { | |
674 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
675 e->type = type; | |
676 e = e->optimize(result); | |
677 } | |
678 else | |
679 { | |
680 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
681 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
682 error("void has no value"); | |
683 if (e1->isConst()) | |
684 { | |
685 if (e2->isConst()) | |
686 { int n1 = e1->isBool(1); | |
687 int n2 = e2->isBool(1); | |
688 | |
689 e = new IntegerExp(loc, n1 && n2, type); | |
690 } | |
691 else if (e1->isBool(TRUE)) | |
692 e = new BoolExp(loc, e2, type); | |
693 } | |
694 } | |
695 return e; | |
696 } | |
697 | |
698 Expression *OrOrExp::optimize(int result) | |
699 { Expression *e; | |
700 | |
701 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
702 e = this; | |
703 if (e1->isBool(TRUE)) | |
704 { // Replace with (e1, 1) | |
705 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
706 e->type = type; | |
707 e = e->optimize(result); | |
708 } | |
709 else | |
710 { | |
711 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
712 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
713 error("void has no value"); | |
714 if (e1->isConst()) | |
715 { | |
716 if (e2->isConst()) | |
717 { int n1 = e1->isBool(1); | |
718 int n2 = e2->isBool(1); | |
719 | |
720 e = new IntegerExp(loc, n1 || n2, type); | |
721 } | |
722 else if (e1->isBool(FALSE)) | |
723 e = new BoolExp(loc, e2, type); | |
724 } | |
725 } | |
726 return e; | |
727 } | |
728 | |
729 Expression *CmpExp::optimize(int result) | |
730 { Expression *e; | |
731 | |
732 //printf("CmpExp::optimize() %s\n", toChars()); | |
733 e1 = e1->optimize(result); | |
734 e2 = e2->optimize(result); | |
735 if (e1->isConst() == 1 && e2->isConst() == 1) | |
736 { | |
737 e = Cmp(op, type, this->e1, this->e2); | |
738 } | |
739 else | |
740 e = this; | |
741 return e; | |
742 } | |
743 | |
744 Expression *CatExp::optimize(int result) | |
745 { Expression *e; | |
746 | |
747 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
748 e1 = e1->optimize(result); | |
749 e2 = e2->optimize(result); | |
750 e = Cat(type, e1, e2); | |
751 if (e == EXP_CANT_INTERPRET) | |
752 e = this; | |
753 return e; | |
754 } | |
755 | |
756 | |
757 Expression *CondExp::optimize(int result) | |
758 { Expression *e; | |
759 | |
760 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
761 if (econd->isBool(TRUE)) | |
762 e = e1->optimize(result); | |
763 else if (econd->isBool(FALSE)) | |
764 e = e2->optimize(result); | |
765 else | |
766 { e1 = e1->optimize(result); | |
767 e2 = e2->optimize(result); | |
768 e = this; | |
769 } | |
770 return e; | |
771 } | |
772 | |
773 |