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