Mercurial > projects > ldc
annotate dmd/optimize.c @ 1168:ab186e535e72
A different fix to #218 and DMD2682 that does not lead to constant folding regressions.
Fixes run/const_15, run/c/const_16_B.
The price is removing the lvalueness of struct literals. If it turns out too
much code depends on this behavior or we don't want to break with DMD, we
could keep struct literals as lvalues and instead convert struct literals used
as expression initializers into struct initializers.
author | Christian Kamm <kamm incasoftware de> |
---|---|
date | Sun, 29 Mar 2009 11:43:45 +0200 |
parents | b30fe7e1dbb9 |
children | e961851fb8be |
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(); | |
1168
ab186e535e72
A different fix to #218 and DMD2682 that does not lead to constant folding regressions.
Christian Kamm <kamm incasoftware de>
parents:
1103
diff
changeset
|
49 if (v && v->isConst() && v->init) |
336 | 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) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1025
diff
changeset
|
237 error("array index %jd is out of bounds [0..%jd]", index, dim); |
336 | 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 { |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
281 //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
282 e1 = e1->optimize(result); |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
283 |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
284 #if DMDV2 |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
285 if (e1->op == TOKvar) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
286 { VarExp *ve = (VarExp *)e1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
287 VarDeclaration *v = ve->var->isVarDeclaration(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
288 Expression *e = expandVar(result, v); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
289 if (e && e->op == TOKstructliteral) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
290 { StructLiteralExp *sle = (StructLiteralExp *)e; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
291 VarDeclaration *vf = var->isVarDeclaration(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
292 if (vf) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
293 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
294 e = sle->getField(type, vf->offset); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
295 if (e != EXP_CANT_INTERPRET) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
296 return e; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
297 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
298 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
299 } |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
300 else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
301 #endif |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
302 if (e1->op == TOKstructliteral) |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
303 { StructLiteralExp *sle = (StructLiteralExp *)e1; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
304 VarDeclaration *vf = var->isVarDeclaration(); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
305 if (vf) |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
306 { |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
307 Expression *e = sle->getField(type, vf->offset); |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
308 if (e != EXP_CANT_INTERPRET) |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
309 return e; |
588
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
310 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
311 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
312 |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
313 return this; |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
314 } |
870652a9af23
Constant fold structliteral.member again.
Christian Kamm <kamm incasoftware de>
parents:
336
diff
changeset
|
315 |
336 | 316 Expression *CallExp::optimize(int result) |
317 { Expression *e = this; | |
318 | |
319 e1 = e1->optimize(result); | |
320 if (e1->op == TOKvar && result & WANTinterpret) | |
321 { | |
322 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
323 if (fd) | |
324 { | |
325 Expression *eresult = fd->interpret(NULL, arguments); | |
326 if (eresult && eresult != EXP_VOID_INTERPRET) | |
327 e = eresult; | |
328 else if (result & WANTinterpret) | |
329 error("cannot evaluate %s at compile time", toChars()); | |
330 } | |
331 } | |
332 return e; | |
333 } | |
334 | |
335 | |
336 Expression *CastExp::optimize(int result) | |
337 { | |
338 //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); | |
339 //printf("from %s to %s\n", type->toChars(), to->toChars()); | |
340 //printf("from %s\n", type->toChars()); | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
588
diff
changeset
|
341 //printf("e1->type %s\n", e1->type->toChars()); |
336 | 342 //printf("type = %p\n", type); |
343 assert(type); | |
344 enum TOK op1 = e1->op; | |
345 | |
346 e1 = e1->optimize(result); | |
347 if (result & WANTinterpret) | |
348 e1 = fromConstInitializer(e1); | |
349 | |
350 if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && | |
351 (type->ty == Tpointer || type->ty == Tarray) && | |
352 type->next->equals(e1->type->next) | |
353 ) | |
354 { | |
888 | 355 // make a copy before adjusting type to avoid |
356 // messing up the type of an existing initializer | |
357 e1 = e1->syntaxCopy(); | |
336 | 358 e1->type = type; |
359 return e1; | |
360 } | |
361 /* The first test here is to prevent infinite loops | |
362 */ | |
363 if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) | |
364 return e1->castTo(NULL, to); | |
365 if (e1->op == TOKnull && | |
366 (type->ty == Tpointer || type->ty == Tclass)) | |
367 { | |
368 e1->type = type; | |
369 return e1; | |
370 } | |
371 | |
372 if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) | |
373 { | |
374 // See if we can remove an unnecessary cast | |
375 ClassDeclaration *cdfrom; | |
376 ClassDeclaration *cdto; | |
377 int offset; | |
378 | |
379 cdfrom = e1->type->isClassHandle(); | |
380 cdto = type->isClassHandle(); | |
381 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) | |
382 { | |
383 e1->type = type; | |
384 return e1; | |
385 } | |
386 } | |
387 | |
388 Expression *e; | |
389 | |
390 if (e1->isConst()) | |
391 { | |
392 if (e1->op == TOKsymoff) | |
393 { | |
394 if (type->size() == e1->type->size() && | |
395 type->toBasetype()->ty != Tsarray) | |
396 { | |
397 e1->type = type; | |
398 return e1; | |
399 } | |
400 return this; | |
401 } | |
402 if (to->toBasetype()->ty == Tvoid) | |
403 e = this; | |
404 else | |
405 e = Cast(type, to, e1); | |
406 } | |
407 else | |
408 e = this; | |
409 return e; | |
410 } | |
411 | |
412 Expression *BinExp::optimize(int result) | |
413 { | |
414 //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); | |
415 e1 = e1->optimize(result); | |
416 e2 = e2->optimize(result); | |
417 if (op == TOKshlass || op == TOKshrass || op == TOKushrass) | |
418 { | |
419 if (e2->isConst() == 1) | |
420 { | |
421 integer_t i2 = e2->toInteger(); | |
422 d_uns64 sz = e1->type->size() * 8; | |
423 if (i2 < 0 || i2 > sz) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1025
diff
changeset
|
424 { error("shift assign by %jd is outside the range 0..%zu", i2, sz); |
336 | 425 e2 = new IntegerExp(0); |
426 } | |
427 } | |
428 } | |
429 return this; | |
430 } | |
431 | |
432 Expression *AddExp::optimize(int result) | |
433 { Expression *e; | |
434 | |
435 //printf("AddExp::optimize(%s)\n", toChars()); | |
436 e1 = e1->optimize(result); | |
437 e2 = e2->optimize(result); | |
438 if (e1->isConst() && e2->isConst()) | |
439 { | |
440 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
441 return this; | |
442 e = Add(type, e1, e2); | |
443 } | |
444 else | |
445 e = this; | |
446 return e; | |
447 } | |
448 | |
449 Expression *MinExp::optimize(int result) | |
450 { Expression *e; | |
451 | |
452 e1 = e1->optimize(result); | |
453 e2 = e2->optimize(result); | |
454 if (e1->isConst() && e2->isConst()) | |
455 { | |
456 if (e2->op == TOKsymoff) | |
457 return this; | |
458 e = Min(type, e1, e2); | |
459 } | |
460 else | |
461 e = this; | |
462 return e; | |
463 } | |
464 | |
465 Expression *MulExp::optimize(int result) | |
466 { Expression *e; | |
467 | |
468 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
469 e1 = e1->optimize(result); | |
470 e2 = e2->optimize(result); | |
471 if (e1->isConst() == 1 && e2->isConst() == 1) | |
472 { | |
473 e = Mul(type, e1, e2); | |
474 } | |
475 else | |
476 e = this; | |
477 return e; | |
478 } | |
479 | |
480 Expression *DivExp::optimize(int result) | |
481 { Expression *e; | |
482 | |
483 //printf("DivExp::optimize(%s)\n", toChars()); | |
484 e1 = e1->optimize(result); | |
485 e2 = e2->optimize(result); | |
486 if (e1->isConst() == 1 && e2->isConst() == 1) | |
487 { | |
488 e = Div(type, e1, e2); | |
489 } | |
490 else | |
491 e = this; | |
492 return e; | |
493 } | |
494 | |
495 Expression *ModExp::optimize(int result) | |
496 { Expression *e; | |
497 | |
498 e1 = e1->optimize(result); | |
499 e2 = e2->optimize(result); | |
500 if (e1->isConst() == 1 && e2->isConst() == 1) | |
501 { | |
502 e = Mod(type, e1, e2); | |
503 } | |
504 else | |
505 e = this; | |
506 return e; | |
507 } | |
508 | |
509 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) | |
510 { Expression *ex = e; | |
511 | |
512 e->e1 = e->e1->optimize(result); | |
513 e->e2 = e->e2->optimize(result); | |
514 if (e->e2->isConst() == 1) | |
515 { | |
516 integer_t i2 = e->e2->toInteger(); | |
517 d_uns64 sz = e->e1->type->size() * 8; | |
518 if (i2 < 0 || i2 > sz) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1025
diff
changeset
|
519 { e->error("shift by %jd is outside the range 0..%zu", i2, sz); |
336 | 520 e->e2 = new IntegerExp(0); |
521 } | |
522 if (e->e1->isConst() == 1) | |
523 ex = (*shift)(e->type, e->e1, e->e2); | |
524 } | |
525 return ex; | |
526 } | |
527 | |
528 Expression *ShlExp::optimize(int result) | |
529 { | |
530 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); | |
531 return shift_optimize(result, this, Shl); | |
532 } | |
533 | |
534 Expression *ShrExp::optimize(int result) | |
535 { | |
536 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); | |
537 return shift_optimize(result, this, Shr); | |
538 } | |
539 | |
540 Expression *UshrExp::optimize(int result) | |
541 { | |
542 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); | |
543 return shift_optimize(result, this, Ushr); | |
544 } | |
545 | |
546 Expression *AndExp::optimize(int result) | |
547 { Expression *e; | |
548 | |
549 e1 = e1->optimize(result); | |
550 e2 = e2->optimize(result); | |
551 if (e1->isConst() == 1 && e2->isConst() == 1) | |
552 e = And(type, e1, e2); | |
553 else | |
554 e = this; | |
555 return e; | |
556 } | |
557 | |
558 Expression *OrExp::optimize(int result) | |
559 { Expression *e; | |
560 | |
561 e1 = e1->optimize(result); | |
562 e2 = e2->optimize(result); | |
563 if (e1->isConst() == 1 && e2->isConst() == 1) | |
564 e = Or(type, e1, e2); | |
565 else | |
566 e = this; | |
567 return e; | |
568 } | |
569 | |
570 Expression *XorExp::optimize(int result) | |
571 { Expression *e; | |
572 | |
573 e1 = e1->optimize(result); | |
574 e2 = e2->optimize(result); | |
575 if (e1->isConst() == 1 && e2->isConst() == 1) | |
576 e = Xor(type, e1, e2); | |
577 else | |
578 e = this; | |
579 return e; | |
580 } | |
581 | |
582 Expression *CommaExp::optimize(int result) | |
583 { Expression *e; | |
584 | |
585 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
586 e1 = e1->optimize(result & WANTinterpret); | |
587 e2 = e2->optimize(result); | |
588 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
589 { | |
590 e = e2; | |
591 if (e) | |
592 e->type = type; | |
593 } | |
594 else | |
595 e = this; | |
596 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
597 return e; | |
598 } | |
599 | |
600 Expression *ArrayLengthExp::optimize(int result) | |
601 { Expression *e; | |
602 | |
603 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
604 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
605 e = this; | |
606 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
607 { | |
608 e = ArrayLength(type, e1); | |
609 } | |
610 return e; | |
611 } | |
612 | |
613 Expression *EqualExp::optimize(int result) | |
614 { Expression *e; | |
615 | |
616 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
617 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
618 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
619 e = this; | |
620 | |
621 Expression *e1 = fromConstInitializer(this->e1); | |
622 Expression *e2 = fromConstInitializer(this->e2); | |
623 | |
624 e = Equal(op, type, e1, e2); | |
625 if (e == EXP_CANT_INTERPRET) | |
626 e = this; | |
627 return e; | |
628 } | |
629 | |
630 Expression *IdentityExp::optimize(int result) | |
631 { Expression *e; | |
632 | |
633 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); | |
634 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
635 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
636 e = this; | |
637 | |
638 if (this->e1->isConst() && this->e2->isConst()) | |
639 { | |
640 e = Identity(op, type, this->e1, this->e2); | |
641 } | |
642 return e; | |
643 } | |
644 | |
645 Expression *IndexExp::optimize(int result) | |
646 { Expression *e; | |
647 | |
648 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
649 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
650 if (result & WANTinterpret) | |
651 e1 = fromConstInitializer(e1); | |
652 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
653 e = Index(type, e1, e2); | |
654 if (e == EXP_CANT_INTERPRET) | |
655 e = this; | |
656 return e; | |
657 } | |
658 | |
659 Expression *SliceExp::optimize(int result) | |
660 { Expression *e; | |
661 | |
662 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
663 e = this; | |
664 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
665 if (!lwr) | |
666 { if (e1->op == TOKstring) | |
667 { // Convert slice of string literal into dynamic array | |
668 Type *t = e1->type->toBasetype(); | |
669 if (t->next) | |
670 e = e1->castTo(NULL, t->next->arrayOf()); | |
671 } | |
672 return e; | |
673 } | |
674 if (result & WANTinterpret) | |
675 e1 = fromConstInitializer(e1); | |
676 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
677 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
678 e = Slice(type, e1, lwr, upr); | |
679 if (e == EXP_CANT_INTERPRET) | |
680 e = this; | |
681 return e; | |
682 } | |
683 | |
684 Expression *AndAndExp::optimize(int result) | |
685 { Expression *e; | |
686 | |
687 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
688 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
689 e = this; | |
690 if (e1->isBool(FALSE)) | |
691 { | |
692 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
693 e->type = type; | |
694 e = e->optimize(result); | |
695 } | |
696 else | |
697 { | |
698 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
699 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
700 error("void has no value"); | |
701 if (e1->isConst()) | |
702 { | |
703 if (e2->isConst()) | |
704 { int n1 = e1->isBool(1); | |
705 int n2 = e2->isBool(1); | |
706 | |
707 e = new IntegerExp(loc, n1 && n2, type); | |
708 } | |
709 else if (e1->isBool(TRUE)) | |
710 e = new BoolExp(loc, e2, type); | |
711 } | |
712 } | |
713 return e; | |
714 } | |
715 | |
716 Expression *OrOrExp::optimize(int result) | |
717 { Expression *e; | |
718 | |
719 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
720 e = this; | |
721 if (e1->isBool(TRUE)) | |
722 { // Replace with (e1, 1) | |
723 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
724 e->type = type; | |
725 e = e->optimize(result); | |
726 } | |
727 else | |
728 { | |
729 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
730 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
731 error("void has no value"); | |
732 if (e1->isConst()) | |
733 { | |
734 if (e2->isConst()) | |
735 { int n1 = e1->isBool(1); | |
736 int n2 = e2->isBool(1); | |
737 | |
738 e = new IntegerExp(loc, n1 || n2, type); | |
739 } | |
740 else if (e1->isBool(FALSE)) | |
741 e = new BoolExp(loc, e2, type); | |
742 } | |
743 } | |
744 return e; | |
745 } | |
746 | |
747 Expression *CmpExp::optimize(int result) | |
748 { Expression *e; | |
749 | |
750 //printf("CmpExp::optimize() %s\n", toChars()); | |
751 e1 = e1->optimize(result); | |
752 e2 = e2->optimize(result); | |
753 if (e1->isConst() == 1 && e2->isConst() == 1) | |
754 { | |
755 e = Cmp(op, type, this->e1, this->e2); | |
756 } | |
757 else | |
758 e = this; | |
759 return e; | |
760 } | |
761 | |
762 Expression *CatExp::optimize(int result) | |
763 { Expression *e; | |
764 | |
765 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
766 e1 = e1->optimize(result); | |
767 e2 = e2->optimize(result); | |
768 e = Cat(type, e1, e2); | |
769 if (e == EXP_CANT_INTERPRET) | |
770 e = this; | |
771 return e; | |
772 } | |
773 | |
774 | |
775 Expression *CondExp::optimize(int result) | |
776 { Expression *e; | |
777 | |
778 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
779 if (econd->isBool(TRUE)) | |
780 e = e1->optimize(result); | |
781 else if (econd->isBool(FALSE)) | |
782 e = e2->optimize(result); | |
783 else | |
784 { e1 = e1->optimize(result); | |
785 e2 = e2->optimize(result); | |
786 e = this; | |
787 } | |
788 return e; | |
789 } | |
790 | |
791 |