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
|
|
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);
|
|
289 if (eresult && eresult != EXP_VOID_INTERPRET)
|
|
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);
|
|
376 if (op == TOKshlass || op == TOKshrass || op == TOKushrass)
|
|
377 {
|
|
378 if (e2->isConst() == 1)
|
|
379 {
|
|
380 integer_t i2 = e2->toInteger();
|
|
381 d_uns64 sz = e1->type->size() * 8;
|
|
382 if (i2 < 0 || i2 > sz)
|
|
383 {
|
|
384 error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
|
385 e2 = new IntegerExp(0);
|
|
386 }
|
|
387 }
|
|
388 }
|
|
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
|
|
469 Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *))
|
|
470 { Expression *ex = e;
|
|
471
|
|
472 e->e1 = e->e1->optimize(result);
|
|
473 e->e2 = e->e2->optimize(result);
|
|
474 if (e->e2->isConst() == 1)
|
|
475 {
|
|
476 integer_t i2 = e->e2->toInteger();
|
|
477 d_uns64 sz = e->e1->type->size() * 8;
|
|
478 if (i2 < 0 || i2 > sz)
|
|
479 {
|
|
480 error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
|
481 e->e2 = new IntegerExp(0);
|
|
482 }
|
|
483 if (e->e1->isConst() == 1)
|
|
484 ex = (*shift)(e->type, e->e1, e->e2);
|
|
485 }
|
|
486 return ex;
|
|
487 }
|
|
488
|
|
489 Expression *ShlExp::optimize(int result)
|
|
490 {
|
|
491 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
|
|
492 return shift_optimize(result, this, Shl);
|
|
493 }
|
|
494
|
|
495 Expression *ShrExp::optimize(int result)
|
|
496 {
|
|
497 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
|
|
498 return shift_optimize(result, this, Shr);
|
|
499 }
|
|
500
|
|
501 Expression *UshrExp::optimize(int result)
|
|
502 {
|
|
503 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
|
|
504 return shift_optimize(result, this, Ushr);
|
|
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
|