Mercurial > projects > ldc
annotate dmd/optimize.c @ 54:28e99b04a132 trunk
[svn r58] Fixed cond expression resulting in a non-basic type.
Fixed identity expression for dynamic arrays.
Revamped the system to keep track of lvalues and rvalues and their relations.
Typedef declaration now generate the custom typeinfo.
Other bugfixes.
author | lindquist |
---|---|
date | Wed, 24 Oct 2007 01:37:34 +0200 |
parents | 3cfcb944304e |
children | 70d6113eeb8c |
rev | line source |
---|---|
1 | 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); | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
374 if (op == TOKshlass || op == TOKshrass || op == TOKushrass) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
375 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
376 if (e2->isConst() == 1) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
377 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
378 integer_t i2 = e2->toInteger(); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
379 d_uns64 sz = e1->type->size() * 8; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
380 if (i2 < 0 || i2 > sz) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
381 { error("shift assign by %jd is outside the range 0..%zu", i2, sz); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
382 e2 = new IntegerExp(0); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
383 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
384 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
385 } |
1 | 386 return this; |
387 } | |
388 | |
389 Expression *AddExp::optimize(int result) | |
390 { Expression *e; | |
391 | |
392 //printf("AddExp::optimize(%s)\n", toChars()); | |
393 e1 = e1->optimize(result); | |
394 e2 = e2->optimize(result); | |
395 if (e1->isConst() && e2->isConst()) | |
396 { | |
397 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
398 return this; | |
399 e = Add(type, e1, e2); | |
400 } | |
401 else | |
402 e = this; | |
403 return e; | |
404 } | |
405 | |
406 Expression *MinExp::optimize(int result) | |
407 { Expression *e; | |
408 | |
409 e1 = e1->optimize(result); | |
410 e2 = e2->optimize(result); | |
411 if (e1->isConst() && e2->isConst()) | |
412 { | |
413 if (e2->op == TOKsymoff) | |
414 return this; | |
415 e = Min(type, e1, e2); | |
416 } | |
417 else | |
418 e = this; | |
419 return e; | |
420 } | |
421 | |
422 Expression *MulExp::optimize(int result) | |
423 { Expression *e; | |
424 | |
425 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
426 e1 = e1->optimize(result); | |
427 e2 = e2->optimize(result); | |
428 if (e1->isConst() == 1 && e2->isConst() == 1) | |
429 { | |
430 e = Mul(type, e1, e2); | |
431 } | |
432 else | |
433 e = this; | |
434 return e; | |
435 } | |
436 | |
437 Expression *DivExp::optimize(int result) | |
438 { Expression *e; | |
439 | |
440 //printf("DivExp::optimize(%s)\n", toChars()); | |
441 e1 = e1->optimize(result); | |
442 e2 = e2->optimize(result); | |
443 if (e1->isConst() == 1 && e2->isConst() == 1) | |
444 { | |
445 e = Div(type, e1, e2); | |
446 } | |
447 else | |
448 e = this; | |
449 return e; | |
450 } | |
451 | |
452 Expression *ModExp::optimize(int result) | |
453 { Expression *e; | |
454 | |
455 e1 = e1->optimize(result); | |
456 e2 = e2->optimize(result); | |
457 if (e1->isConst() == 1 && e2->isConst() == 1) | |
458 { | |
459 e = Mod(type, e1, e2); | |
460 } | |
461 else | |
462 e = this; | |
463 return e; | |
464 } | |
465 | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
466 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
467 { Expression *ex = e; |
1 | 468 |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
469 e->e1 = e->e1->optimize(result); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
470 e->e2 = e->e2->optimize(result); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
471 if (e->e2->isConst() == 1) |
1 | 472 { |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
473 integer_t i2 = e->e2->toInteger(); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
474 d_uns64 sz = e->e1->type->size() * 8; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
475 if (i2 < 0 || i2 > sz) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
476 { error("shift by %jd is outside the range 0..%zu", i2, sz); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
477 e->e2 = new IntegerExp(0); |
1 | 478 } |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
479 if (e->e1->isConst() == 1) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
480 ex = (*shift)(e->type, e->e1, e->e2); |
1 | 481 } |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
482 return ex; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
483 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
484 |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
485 Expression *ShlExp::optimize(int result) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
486 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
487 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
488 return shift_optimize(result, this, Shl); |
1 | 489 } |
490 | |
491 Expression *ShrExp::optimize(int result) | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
492 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
493 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
494 return shift_optimize(result, this, Shr); |
1 | 495 } |
496 | |
497 Expression *UshrExp::optimize(int result) | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
498 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
499 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
500 return shift_optimize(result, this, Ushr); |
1 | 501 } |
502 | |
503 Expression *AndExp::optimize(int result) | |
504 { Expression *e; | |
505 | |
506 e1 = e1->optimize(result); | |
507 e2 = e2->optimize(result); | |
508 if (e1->isConst() == 1 && e2->isConst() == 1) | |
509 e = And(type, e1, e2); | |
510 else | |
511 e = this; | |
512 return e; | |
513 } | |
514 | |
515 Expression *OrExp::optimize(int result) | |
516 { Expression *e; | |
517 | |
518 e1 = e1->optimize(result); | |
519 e2 = e2->optimize(result); | |
520 if (e1->isConst() == 1 && e2->isConst() == 1) | |
521 e = Or(type, e1, e2); | |
522 else | |
523 e = this; | |
524 return e; | |
525 } | |
526 | |
527 Expression *XorExp::optimize(int result) | |
528 { Expression *e; | |
529 | |
530 e1 = e1->optimize(result); | |
531 e2 = e2->optimize(result); | |
532 if (e1->isConst() == 1 && e2->isConst() == 1) | |
533 e = Xor(type, e1, e2); | |
534 else | |
535 e = this; | |
536 return e; | |
537 } | |
538 | |
539 Expression *CommaExp::optimize(int result) | |
540 { Expression *e; | |
541 | |
542 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
543 e1 = e1->optimize(result & WANTinterpret); | |
544 e2 = e2->optimize(result); | |
545 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
546 { | |
547 e = e2; | |
548 if (e) | |
549 e->type = type; | |
550 } | |
551 else | |
552 e = this; | |
553 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
554 return e; | |
555 } | |
556 | |
557 Expression *ArrayLengthExp::optimize(int result) | |
558 { Expression *e; | |
559 | |
560 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
561 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
562 e = this; | |
563 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
564 { | |
565 e = ArrayLength(type, e1); | |
566 } | |
567 return e; | |
568 } | |
569 | |
570 Expression *EqualExp::optimize(int result) | |
571 { Expression *e; | |
572 | |
573 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
574 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
575 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
576 e = this; | |
577 | |
578 Expression *e1 = fromConstInitializer(this->e1); | |
579 Expression *e2 = fromConstInitializer(this->e2); | |
580 | |
581 e = Equal(op, type, e1, e2); | |
582 if (e == EXP_CANT_INTERPRET) | |
583 e = this; | |
584 return e; | |
585 } | |
586 | |
587 Expression *IdentityExp::optimize(int result) | |
588 { Expression *e; | |
589 | |
590 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); | |
591 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
592 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
593 e = this; | |
594 | |
595 if (this->e1->isConst() && this->e2->isConst()) | |
596 { | |
597 e = Identity(op, type, this->e1, this->e2); | |
598 } | |
599 return e; | |
600 } | |
601 | |
602 Expression *IndexExp::optimize(int result) | |
603 { Expression *e; | |
604 | |
605 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
606 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
607 if (result & WANTinterpret) | |
608 e1 = fromConstInitializer(e1); | |
609 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
610 e = Index(type, e1, e2); | |
611 if (e == EXP_CANT_INTERPRET) | |
612 e = this; | |
613 return e; | |
614 } | |
615 | |
616 Expression *SliceExp::optimize(int result) | |
617 { Expression *e; | |
618 | |
619 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
620 e = this; | |
621 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
622 if (!lwr) | |
623 { if (e1->op == TOKstring) | |
624 { // Convert slice of string literal into dynamic array | |
625 Type *t = e1->type->toBasetype(); | |
626 if (t->next) | |
627 e = e1->castTo(NULL, t->next->arrayOf()); | |
628 } | |
629 return e; | |
630 } | |
631 if (result & WANTinterpret) | |
632 e1 = fromConstInitializer(e1); | |
633 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
634 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
635 e = Slice(type, e1, lwr, upr); | |
636 if (e == EXP_CANT_INTERPRET) | |
637 e = this; | |
638 return e; | |
639 } | |
640 | |
641 Expression *AndAndExp::optimize(int result) | |
642 { Expression *e; | |
643 | |
644 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
645 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
646 e = this; | |
647 if (e1->isBool(FALSE)) | |
648 { | |
649 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
650 e->type = type; | |
651 e = e->optimize(result); | |
652 } | |
653 else | |
654 { | |
655 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
656 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
657 error("void has no value"); | |
658 if (e1->isConst()) | |
659 { | |
660 if (e2->isConst()) | |
661 { int n1 = e1->isBool(1); | |
662 int n2 = e2->isBool(1); | |
663 | |
664 e = new IntegerExp(loc, n1 && n2, type); | |
665 } | |
666 else if (e1->isBool(TRUE)) | |
667 e = new BoolExp(loc, e2, type); | |
668 } | |
669 } | |
670 return e; | |
671 } | |
672 | |
673 Expression *OrOrExp::optimize(int result) | |
674 { Expression *e; | |
675 | |
676 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
677 e = this; | |
678 if (e1->isBool(TRUE)) | |
679 { // Replace with (e1, 1) | |
680 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
681 e->type = type; | |
682 e = e->optimize(result); | |
683 } | |
684 else | |
685 { | |
686 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
687 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
688 error("void has no value"); | |
689 if (e1->isConst()) | |
690 { | |
691 if (e2->isConst()) | |
692 { int n1 = e1->isBool(1); | |
693 int n2 = e2->isBool(1); | |
694 | |
695 e = new IntegerExp(loc, n1 || n2, type); | |
696 } | |
697 else if (e1->isBool(FALSE)) | |
698 e = new BoolExp(loc, e2, type); | |
699 } | |
700 } | |
701 return e; | |
702 } | |
703 | |
704 Expression *CmpExp::optimize(int result) | |
705 { Expression *e; | |
706 | |
707 //printf("CmpExp::optimize() %s\n", toChars()); | |
708 e1 = e1->optimize(result); | |
709 e2 = e2->optimize(result); | |
710 if (e1->isConst() == 1 && e2->isConst() == 1) | |
711 { | |
712 e = Cmp(op, type, this->e1, this->e2); | |
713 } | |
714 else | |
715 e = this; | |
716 return e; | |
717 } | |
718 | |
719 Expression *CatExp::optimize(int result) | |
720 { Expression *e; | |
721 | |
722 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
723 e1 = e1->optimize(result); | |
724 e2 = e2->optimize(result); | |
725 e = Cat(type, e1, e2); | |
726 if (e == EXP_CANT_INTERPRET) | |
727 e = this; | |
728 return e; | |
729 } | |
730 | |
731 | |
732 Expression *CondExp::optimize(int result) | |
733 { Expression *e; | |
734 | |
735 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
736 if (econd->isBool(TRUE)) | |
737 e = e1->optimize(result); | |
738 else if (econd->isBool(FALSE)) | |
739 e = e2->optimize(result); | |
740 else | |
741 { e1 = e1->optimize(result); | |
742 e2 = e2->optimize(result); | |
743 e = this; | |
744 } | |
745 return e; | |
746 } | |
747 | |
748 |