Mercurial > projects > ldc
annotate dmd/optimize.c @ 984:4c0df37d0421
Removing ldc.conf. (IMPORTANT: run 'cmake .' after pull)
Added it to .hgignore.
This gets rid of spurious differences caused by CMake regenerating it differently.
Just run 'cmake .' to get it back in your local checkout.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 19 Feb 2009 13:50:05 +0100 |
parents | e74e2e53ba3b |
children | c519caae3181 |
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 { |
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) | |
424 { | |
425 error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz); | |
426 e2 = new IntegerExp(0); | |
427 } | |
428 } | |
429 } | |
430 return this; | |
431 } | |
432 | |
433 Expression *AddExp::optimize(int result) | |
434 { Expression *e; | |
435 | |
436 //printf("AddExp::optimize(%s)\n", toChars()); | |
437 e1 = e1->optimize(result); | |
438 e2 = e2->optimize(result); | |
439 if (e1->isConst() && e2->isConst()) | |
440 { | |
441 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
442 return this; | |
443 e = Add(type, e1, e2); | |
444 } | |
445 else | |
446 e = this; | |
447 return e; | |
448 } | |
449 | |
450 Expression *MinExp::optimize(int result) | |
451 { Expression *e; | |
452 | |
453 e1 = e1->optimize(result); | |
454 e2 = e2->optimize(result); | |
455 if (e1->isConst() && e2->isConst()) | |
456 { | |
457 if (e2->op == TOKsymoff) | |
458 return this; | |
459 e = Min(type, e1, e2); | |
460 } | |
461 else | |
462 e = this; | |
463 return e; | |
464 } | |
465 | |
466 Expression *MulExp::optimize(int result) | |
467 { Expression *e; | |
468 | |
469 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
470 e1 = e1->optimize(result); | |
471 e2 = e2->optimize(result); | |
472 if (e1->isConst() == 1 && e2->isConst() == 1) | |
473 { | |
474 e = Mul(type, e1, e2); | |
475 } | |
476 else | |
477 e = this; | |
478 return e; | |
479 } | |
480 | |
481 Expression *DivExp::optimize(int result) | |
482 { Expression *e; | |
483 | |
484 //printf("DivExp::optimize(%s)\n", toChars()); | |
485 e1 = e1->optimize(result); | |
486 e2 = e2->optimize(result); | |
487 if (e1->isConst() == 1 && e2->isConst() == 1) | |
488 { | |
489 e = Div(type, e1, e2); | |
490 } | |
491 else | |
492 e = this; | |
493 return e; | |
494 } | |
495 | |
496 Expression *ModExp::optimize(int result) | |
497 { Expression *e; | |
498 | |
499 e1 = e1->optimize(result); | |
500 e2 = e2->optimize(result); | |
501 if (e1->isConst() == 1 && e2->isConst() == 1) | |
502 { | |
503 e = Mod(type, e1, e2); | |
504 } | |
505 else | |
506 e = this; | |
507 return e; | |
508 } | |
509 | |
510 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) | |
511 { Expression *ex = e; | |
512 | |
513 e->e1 = e->e1->optimize(result); | |
514 e->e2 = e->e2->optimize(result); | |
515 if (e->e2->isConst() == 1) | |
516 { | |
517 integer_t i2 = e->e2->toInteger(); | |
518 d_uns64 sz = e->e1->type->size() * 8; | |
519 if (i2 < 0 || i2 > sz) | |
520 { | |
521 error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz); | |
522 e->e2 = new IntegerExp(0); | |
523 } | |
524 if (e->e1->isConst() == 1) | |
525 ex = (*shift)(e->type, e->e1, e->e2); | |
526 } | |
527 return ex; | |
528 } | |
529 | |
530 Expression *ShlExp::optimize(int result) | |
531 { | |
532 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); | |
533 return shift_optimize(result, this, Shl); | |
534 } | |
535 | |
536 Expression *ShrExp::optimize(int result) | |
537 { | |
538 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); | |
539 return shift_optimize(result, this, Shr); | |
540 } | |
541 | |
542 Expression *UshrExp::optimize(int result) | |
543 { | |
544 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); | |
545 return shift_optimize(result, this, Ushr); | |
546 } | |
547 | |
548 Expression *AndExp::optimize(int result) | |
549 { Expression *e; | |
550 | |
551 e1 = e1->optimize(result); | |
552 e2 = e2->optimize(result); | |
553 if (e1->isConst() == 1 && e2->isConst() == 1) | |
554 e = And(type, e1, e2); | |
555 else | |
556 e = this; | |
557 return e; | |
558 } | |
559 | |
560 Expression *OrExp::optimize(int result) | |
561 { Expression *e; | |
562 | |
563 e1 = e1->optimize(result); | |
564 e2 = e2->optimize(result); | |
565 if (e1->isConst() == 1 && e2->isConst() == 1) | |
566 e = Or(type, e1, e2); | |
567 else | |
568 e = this; | |
569 return e; | |
570 } | |
571 | |
572 Expression *XorExp::optimize(int result) | |
573 { Expression *e; | |
574 | |
575 e1 = e1->optimize(result); | |
576 e2 = e2->optimize(result); | |
577 if (e1->isConst() == 1 && e2->isConst() == 1) | |
578 e = Xor(type, e1, e2); | |
579 else | |
580 e = this; | |
581 return e; | |
582 } | |
583 | |
584 Expression *CommaExp::optimize(int result) | |
585 { Expression *e; | |
586 | |
587 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
588 e1 = e1->optimize(result & WANTinterpret); | |
589 e2 = e2->optimize(result); | |
590 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
591 { | |
592 e = e2; | |
593 if (e) | |
594 e->type = type; | |
595 } | |
596 else | |
597 e = this; | |
598 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
599 return e; | |
600 } | |
601 | |
602 Expression *ArrayLengthExp::optimize(int result) | |
603 { Expression *e; | |
604 | |
605 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
606 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
607 e = this; | |
608 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
609 { | |
610 e = ArrayLength(type, e1); | |
611 } | |
612 return e; | |
613 } | |
614 | |
615 Expression *EqualExp::optimize(int result) | |
616 { Expression *e; | |
617 | |
618 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
619 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
620 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
621 e = this; | |
622 | |
623 Expression *e1 = fromConstInitializer(this->e1); | |
624 Expression *e2 = fromConstInitializer(this->e2); | |
625 | |
626 e = Equal(op, type, e1, e2); | |
627 if (e == EXP_CANT_INTERPRET) | |
628 e = this; | |
629 return e; | |
630 } | |
631 | |
632 Expression *IdentityExp::optimize(int result) | |
633 { Expression *e; | |
634 | |
635 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); | |
636 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
637 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
638 e = this; | |
639 | |
640 if (this->e1->isConst() && this->e2->isConst()) | |
641 { | |
642 e = Identity(op, type, this->e1, this->e2); | |
643 } | |
644 return e; | |
645 } | |
646 | |
647 Expression *IndexExp::optimize(int result) | |
648 { Expression *e; | |
649 | |
650 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
651 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
652 if (result & WANTinterpret) | |
653 e1 = fromConstInitializer(e1); | |
654 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
655 e = Index(type, e1, e2); | |
656 if (e == EXP_CANT_INTERPRET) | |
657 e = this; | |
658 return e; | |
659 } | |
660 | |
661 Expression *SliceExp::optimize(int result) | |
662 { Expression *e; | |
663 | |
664 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
665 e = this; | |
666 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
667 if (!lwr) | |
668 { if (e1->op == TOKstring) | |
669 { // Convert slice of string literal into dynamic array | |
670 Type *t = e1->type->toBasetype(); | |
671 if (t->next) | |
672 e = e1->castTo(NULL, t->next->arrayOf()); | |
673 } | |
674 return e; | |
675 } | |
676 if (result & WANTinterpret) | |
677 e1 = fromConstInitializer(e1); | |
678 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
679 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
680 e = Slice(type, e1, lwr, upr); | |
681 if (e == EXP_CANT_INTERPRET) | |
682 e = this; | |
683 return e; | |
684 } | |
685 | |
686 Expression *AndAndExp::optimize(int result) | |
687 { Expression *e; | |
688 | |
689 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
690 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
691 e = this; | |
692 if (e1->isBool(FALSE)) | |
693 { | |
694 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
695 e->type = type; | |
696 e = e->optimize(result); | |
697 } | |
698 else | |
699 { | |
700 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
701 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
702 error("void has no value"); | |
703 if (e1->isConst()) | |
704 { | |
705 if (e2->isConst()) | |
706 { int n1 = e1->isBool(1); | |
707 int n2 = e2->isBool(1); | |
708 | |
709 e = new IntegerExp(loc, n1 && n2, type); | |
710 } | |
711 else if (e1->isBool(TRUE)) | |
712 e = new BoolExp(loc, e2, type); | |
713 } | |
714 } | |
715 return e; | |
716 } | |
717 | |
718 Expression *OrOrExp::optimize(int result) | |
719 { Expression *e; | |
720 | |
721 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
722 e = this; | |
723 if (e1->isBool(TRUE)) | |
724 { // Replace with (e1, 1) | |
725 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
726 e->type = type; | |
727 e = e->optimize(result); | |
728 } | |
729 else | |
730 { | |
731 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
732 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
733 error("void has no value"); | |
734 if (e1->isConst()) | |
735 { | |
736 if (e2->isConst()) | |
737 { int n1 = e1->isBool(1); | |
738 int n2 = e2->isBool(1); | |
739 | |
740 e = new IntegerExp(loc, n1 || n2, type); | |
741 } | |
742 else if (e1->isBool(FALSE)) | |
743 e = new BoolExp(loc, e2, type); | |
744 } | |
745 } | |
746 return e; | |
747 } | |
748 | |
749 Expression *CmpExp::optimize(int result) | |
750 { Expression *e; | |
751 | |
752 //printf("CmpExp::optimize() %s\n", toChars()); | |
753 e1 = e1->optimize(result); | |
754 e2 = e2->optimize(result); | |
755 if (e1->isConst() == 1 && e2->isConst() == 1) | |
756 { | |
757 e = Cmp(op, type, this->e1, this->e2); | |
758 } | |
759 else | |
760 e = this; | |
761 return e; | |
762 } | |
763 | |
764 Expression *CatExp::optimize(int result) | |
765 { Expression *e; | |
766 | |
767 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
768 e1 = e1->optimize(result); | |
769 e2 = e2->optimize(result); | |
770 e = Cat(type, e1, e2); | |
771 if (e == EXP_CANT_INTERPRET) | |
772 e = this; | |
773 return e; | |
774 } | |
775 | |
776 | |
777 Expression *CondExp::optimize(int result) | |
778 { Expression *e; | |
779 | |
780 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
781 if (econd->isBool(TRUE)) | |
782 e = e1->optimize(result); | |
783 else if (econd->isBool(FALSE)) | |
784 e = e2->optimize(result); | |
785 else | |
786 { e1 = e1->optimize(result); | |
787 e2 = e2->optimize(result); | |
788 e = this; | |
789 } | |
790 return e; | |
791 } | |
792 | |
793 |