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