Mercurial > projects > ldc
annotate dmd/optimize.c @ 323:0d52412d5b1a trunk
[svn r344] Fixed some very minor issues with the usage listing when calling llvmdc with no arguments.
Changed the way moduleinfo is registered to use the same approach as DMD, this eliminates the need for correct linking order and should make the way for using a natively compiled runtime library. This should speed up linking tremendously and should now be possible.
Fixed the llvm.used array to only be emitted if really necessary.
author | lindquist |
---|---|
date | Wed, 09 Jul 2008 23:43:51 +0200 |
parents | 2b72433d5c8c |
children | aaade6ded589 |
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 } | |
94
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
92
diff
changeset
|
212 #if !IN_LLVM |
1 | 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) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
94
diff
changeset
|
237 error("array index %lld is out of bounds [0..%lld]", index, dim); |
1 | 238 e = new SymOffExp(loc, ve->var, index * ts->next->size()); |
239 e->type = type; | |
240 return e; | |
241 } | |
242 } | |
243 } | |
94
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
92
diff
changeset
|
244 #endif |
1 | 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 | |
279 Expression *CallExp::optimize(int result) | |
280 { Expression *e = this; | |
281 | |
282 e1 = e1->optimize(result); | |
283 if (e1->op == TOKvar && result & WANTinterpret) | |
284 { | |
285 FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); | |
286 if (fd) | |
287 { | |
288 Expression *eresult = fd->interpret(NULL, arguments); | |
92 | 289 if (eresult && eresult != EXP_VOID_INTERPRET) |
1 | 290 e = eresult; |
291 else if (result & WANTinterpret) | |
292 error("cannot evaluate %s at compile time", toChars()); | |
293 } | |
294 } | |
295 return e; | |
296 } | |
297 | |
298 | |
299 Expression *CastExp::optimize(int result) | |
300 { | |
301 //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); | |
302 //printf("from %s to %s\n", type->toChars(), to->toChars()); | |
303 //printf("from %s\n", type->toChars()); | |
304 //printf("type = %p\n", type); | |
305 assert(type); | |
306 enum TOK op1 = e1->op; | |
307 | |
308 e1 = e1->optimize(result); | |
309 if (result & WANTinterpret) | |
310 e1 = fromConstInitializer(e1); | |
311 | |
312 if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && | |
313 (type->ty == Tpointer || type->ty == Tarray) && | |
314 type->next->equals(e1->type->next) | |
315 ) | |
316 { | |
317 e1->type = type; | |
318 return e1; | |
319 } | |
320 /* The first test here is to prevent infinite loops | |
321 */ | |
322 if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) | |
323 return e1->castTo(NULL, to); | |
324 if (e1->op == TOKnull && | |
325 (type->ty == Tpointer || type->ty == Tclass)) | |
326 { | |
327 e1->type = type; | |
328 return e1; | |
329 } | |
330 | |
331 if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) | |
332 { | |
333 // See if we can remove an unnecessary cast | |
334 ClassDeclaration *cdfrom; | |
335 ClassDeclaration *cdto; | |
336 int offset; | |
337 | |
338 cdfrom = e1->type->isClassHandle(); | |
339 cdto = type->isClassHandle(); | |
340 if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) | |
341 { | |
342 e1->type = type; | |
343 return e1; | |
344 } | |
345 } | |
346 | |
347 Expression *e; | |
348 | |
349 if (e1->isConst()) | |
350 { | |
351 if (e1->op == TOKsymoff) | |
352 { | |
353 if (type->size() == e1->type->size() && | |
354 type->toBasetype()->ty != Tsarray) | |
355 { | |
356 e1->type = type; | |
357 return e1; | |
358 } | |
359 return this; | |
360 } | |
361 if (to->toBasetype()->ty == Tvoid) | |
362 e = this; | |
363 else | |
364 e = Cast(type, to, e1); | |
365 } | |
366 else | |
367 e = this; | |
368 return e; | |
369 } | |
370 | |
371 Expression *BinExp::optimize(int result) | |
372 { | |
373 //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); | |
374 e1 = e1->optimize(result); | |
375 e2 = e2->optimize(result); | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
376 if (op == TOKshlass || op == TOKshrass || op == TOKushrass) |
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 if (e2->isConst() == 1) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
379 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
380 integer_t i2 = e2->toInteger(); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
381 d_uns64 sz = e1->type->size() * 8; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
382 if (i2 < 0 || i2 > sz) |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
94
diff
changeset
|
383 { |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
94
diff
changeset
|
384 error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz); |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
385 e2 = new IntegerExp(0); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
386 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
387 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
388 } |
1 | 389 return this; |
390 } | |
391 | |
392 Expression *AddExp::optimize(int result) | |
393 { Expression *e; | |
394 | |
395 //printf("AddExp::optimize(%s)\n", toChars()); | |
396 e1 = e1->optimize(result); | |
397 e2 = e2->optimize(result); | |
398 if (e1->isConst() && e2->isConst()) | |
399 { | |
400 if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
401 return this; | |
402 e = Add(type, e1, e2); | |
403 } | |
404 else | |
405 e = this; | |
406 return e; | |
407 } | |
408 | |
409 Expression *MinExp::optimize(int result) | |
410 { Expression *e; | |
411 | |
412 e1 = e1->optimize(result); | |
413 e2 = e2->optimize(result); | |
414 if (e1->isConst() && e2->isConst()) | |
415 { | |
416 if (e2->op == TOKsymoff) | |
417 return this; | |
418 e = Min(type, e1, e2); | |
419 } | |
420 else | |
421 e = this; | |
422 return e; | |
423 } | |
424 | |
425 Expression *MulExp::optimize(int result) | |
426 { Expression *e; | |
427 | |
428 //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); | |
429 e1 = e1->optimize(result); | |
430 e2 = e2->optimize(result); | |
431 if (e1->isConst() == 1 && e2->isConst() == 1) | |
432 { | |
433 e = Mul(type, e1, e2); | |
434 } | |
435 else | |
436 e = this; | |
437 return e; | |
438 } | |
439 | |
440 Expression *DivExp::optimize(int result) | |
441 { Expression *e; | |
442 | |
443 //printf("DivExp::optimize(%s)\n", toChars()); | |
444 e1 = e1->optimize(result); | |
445 e2 = e2->optimize(result); | |
446 if (e1->isConst() == 1 && e2->isConst() == 1) | |
447 { | |
448 e = Div(type, e1, e2); | |
449 } | |
450 else | |
451 e = this; | |
452 return e; | |
453 } | |
454 | |
455 Expression *ModExp::optimize(int result) | |
456 { Expression *e; | |
457 | |
458 e1 = e1->optimize(result); | |
459 e2 = e2->optimize(result); | |
460 if (e1->isConst() == 1 && e2->isConst() == 1) | |
461 { | |
462 e = Mod(type, e1, e2); | |
463 } | |
464 else | |
465 e = this; | |
466 return e; | |
467 } | |
468 | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
469 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
|
470 { Expression *ex = e; |
1 | 471 |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
472 e->e1 = e->e1->optimize(result); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
473 e->e2 = e->e2->optimize(result); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
474 if (e->e2->isConst() == 1) |
1 | 475 { |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
476 integer_t i2 = e->e2->toInteger(); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
477 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
|
478 if (i2 < 0 || i2 > sz) |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
94
diff
changeset
|
479 { |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
94
diff
changeset
|
480 error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz); |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
481 e->e2 = new IntegerExp(0); |
1 | 482 } |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
483 if (e->e1->isConst() == 1) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
484 ex = (*shift)(e->type, e->e1, e->e2); |
1 | 485 } |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
486 return ex; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
487 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
488 |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
489 Expression *ShlExp::optimize(int result) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
490 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
491 //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
|
492 return shift_optimize(result, this, Shl); |
1 | 493 } |
494 | |
495 Expression *ShrExp::optimize(int result) | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
496 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
497 //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
|
498 return shift_optimize(result, this, Shr); |
1 | 499 } |
500 | |
501 Expression *UshrExp::optimize(int result) | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
502 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
1
diff
changeset
|
503 //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
|
504 return shift_optimize(result, this, Ushr); |
1 | 505 } |
506 | |
507 Expression *AndExp::optimize(int result) | |
508 { Expression *e; | |
509 | |
510 e1 = e1->optimize(result); | |
511 e2 = e2->optimize(result); | |
512 if (e1->isConst() == 1 && e2->isConst() == 1) | |
513 e = And(type, e1, e2); | |
514 else | |
515 e = this; | |
516 return e; | |
517 } | |
518 | |
519 Expression *OrExp::optimize(int result) | |
520 { Expression *e; | |
521 | |
522 e1 = e1->optimize(result); | |
523 e2 = e2->optimize(result); | |
524 if (e1->isConst() == 1 && e2->isConst() == 1) | |
525 e = Or(type, e1, e2); | |
526 else | |
527 e = this; | |
528 return e; | |
529 } | |
530 | |
531 Expression *XorExp::optimize(int result) | |
532 { Expression *e; | |
533 | |
534 e1 = e1->optimize(result); | |
535 e2 = e2->optimize(result); | |
536 if (e1->isConst() == 1 && e2->isConst() == 1) | |
537 e = Xor(type, e1, e2); | |
538 else | |
539 e = this; | |
540 return e; | |
541 } | |
542 | |
543 Expression *CommaExp::optimize(int result) | |
544 { Expression *e; | |
545 | |
546 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); | |
547 e1 = e1->optimize(result & WANTinterpret); | |
548 e2 = e2->optimize(result); | |
549 if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) | |
550 { | |
551 e = e2; | |
552 if (e) | |
553 e->type = type; | |
554 } | |
555 else | |
556 e = this; | |
557 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); | |
558 return e; | |
559 } | |
560 | |
561 Expression *ArrayLengthExp::optimize(int result) | |
562 { Expression *e; | |
563 | |
564 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); | |
565 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
566 e = this; | |
567 if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) | |
568 { | |
569 e = ArrayLength(type, e1); | |
570 } | |
571 return e; | |
572 } | |
573 | |
574 Expression *EqualExp::optimize(int result) | |
575 { Expression *e; | |
576 | |
577 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); | |
578 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
579 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
580 e = this; | |
581 | |
582 Expression *e1 = fromConstInitializer(this->e1); | |
583 Expression *e2 = fromConstInitializer(this->e2); | |
584 | |
585 e = Equal(op, type, e1, e2); | |
586 if (e == EXP_CANT_INTERPRET) | |
587 e = this; | |
588 return e; | |
589 } | |
590 | |
591 Expression *IdentityExp::optimize(int result) | |
592 { Expression *e; | |
593 | |
594 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); | |
595 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
596 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
597 e = this; | |
598 | |
599 if (this->e1->isConst() && this->e2->isConst()) | |
600 { | |
601 e = Identity(op, type, this->e1, this->e2); | |
602 } | |
603 return e; | |
604 } | |
605 | |
606 Expression *IndexExp::optimize(int result) | |
607 { Expression *e; | |
608 | |
609 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); | |
610 Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); | |
611 if (result & WANTinterpret) | |
612 e1 = fromConstInitializer(e1); | |
613 e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); | |
614 e = Index(type, e1, e2); | |
615 if (e == EXP_CANT_INTERPRET) | |
616 e = this; | |
617 return e; | |
618 } | |
619 | |
620 Expression *SliceExp::optimize(int result) | |
621 { Expression *e; | |
622 | |
623 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); | |
624 e = this; | |
625 e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); | |
626 if (!lwr) | |
627 { if (e1->op == TOKstring) | |
628 { // Convert slice of string literal into dynamic array | |
629 Type *t = e1->type->toBasetype(); | |
630 if (t->next) | |
631 e = e1->castTo(NULL, t->next->arrayOf()); | |
632 } | |
633 return e; | |
634 } | |
635 if (result & WANTinterpret) | |
636 e1 = fromConstInitializer(e1); | |
637 lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); | |
638 upr = upr->optimize(WANTvalue | (result & WANTinterpret)); | |
639 e = Slice(type, e1, lwr, upr); | |
640 if (e == EXP_CANT_INTERPRET) | |
641 e = this; | |
642 return e; | |
643 } | |
644 | |
645 Expression *AndAndExp::optimize(int result) | |
646 { Expression *e; | |
647 | |
648 //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); | |
649 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
650 e = this; | |
651 if (e1->isBool(FALSE)) | |
652 { | |
653 e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); | |
654 e->type = type; | |
655 e = e->optimize(result); | |
656 } | |
657 else | |
658 { | |
659 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
660 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
661 error("void has no value"); | |
662 if (e1->isConst()) | |
663 { | |
664 if (e2->isConst()) | |
665 { int n1 = e1->isBool(1); | |
666 int n2 = e2->isBool(1); | |
667 | |
668 e = new IntegerExp(loc, n1 && n2, type); | |
669 } | |
670 else if (e1->isBool(TRUE)) | |
671 e = new BoolExp(loc, e2, type); | |
672 } | |
673 } | |
674 return e; | |
675 } | |
676 | |
677 Expression *OrOrExp::optimize(int result) | |
678 { Expression *e; | |
679 | |
680 e1 = e1->optimize(WANTflags | (result & WANTinterpret)); | |
681 e = this; | |
682 if (e1->isBool(TRUE)) | |
683 { // Replace with (e1, 1) | |
684 e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); | |
685 e->type = type; | |
686 e = e->optimize(result); | |
687 } | |
688 else | |
689 { | |
690 e2 = e2->optimize(WANTflags | (result & WANTinterpret)); | |
691 if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) | |
692 error("void has no value"); | |
693 if (e1->isConst()) | |
694 { | |
695 if (e2->isConst()) | |
696 { int n1 = e1->isBool(1); | |
697 int n2 = e2->isBool(1); | |
698 | |
699 e = new IntegerExp(loc, n1 || n2, type); | |
700 } | |
701 else if (e1->isBool(FALSE)) | |
702 e = new BoolExp(loc, e2, type); | |
703 } | |
704 } | |
705 return e; | |
706 } | |
707 | |
708 Expression *CmpExp::optimize(int result) | |
709 { Expression *e; | |
710 | |
711 //printf("CmpExp::optimize() %s\n", toChars()); | |
712 e1 = e1->optimize(result); | |
713 e2 = e2->optimize(result); | |
714 if (e1->isConst() == 1 && e2->isConst() == 1) | |
715 { | |
716 e = Cmp(op, type, this->e1, this->e2); | |
717 } | |
718 else | |
719 e = this; | |
720 return e; | |
721 } | |
722 | |
723 Expression *CatExp::optimize(int result) | |
724 { Expression *e; | |
725 | |
726 //printf("CatExp::optimize(%d) %s\n", result, toChars()); | |
727 e1 = e1->optimize(result); | |
728 e2 = e2->optimize(result); | |
729 e = Cat(type, e1, e2); | |
730 if (e == EXP_CANT_INTERPRET) | |
731 e = this; | |
732 return e; | |
733 } | |
734 | |
735 | |
736 Expression *CondExp::optimize(int result) | |
737 { Expression *e; | |
738 | |
739 econd = econd->optimize(WANTflags | (result & WANTinterpret)); | |
740 if (econd->isBool(TRUE)) | |
741 e = e1->optimize(result); | |
742 else if (econd->isBool(FALSE)) | |
743 e = e2->optimize(result); | |
744 else | |
745 { e1 = e1->optimize(result); | |
746 e2 = e2->optimize(result); | |
747 e = this; | |
748 } | |
749 return e; | |
750 } | |
751 | |
752 |