2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 by Digital Mars
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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
28 #include "expression.h"
29 #include "declaration.h"
30 #include "aggregate.h"
35 #include "d-gcc-real.h"
38 extern "C" bool real_isnan (const real_t
*);
41 static real_t zero
; // work around DMC bug for now
44 /*************************************
45 * If expression is a variable with a const initializer,
46 * return that initializer.
49 Expression
*fromConstInitializer(Expression
*e1
)
51 //printf("fromConstInitializer(%s)\n", e1->toChars());
53 { VarExp
*ve
= (VarExp
*)e1
;
54 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
55 if (v
&& v
->isConst() && v
->init
)
56 { Expression
*ei
= v
->init
->toExpression();
65 Expression
*Expression::optimize(int result
)
67 //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
71 Expression
*VarExp::optimize(int result
)
73 if (result
& WANTinterpret
)
75 return fromConstInitializer(this);
80 Expression
*TupleExp::optimize(int result
)
82 for (size_t i
= 0; i
< exps
->dim
; i
++)
83 { Expression
*e
= (Expression
*)exps
->data
[i
];
85 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
86 exps
->data
[i
] = (void *)e
;
91 Expression
*ArrayLiteralExp::optimize(int result
)
95 for (size_t i
= 0; i
< elements
->dim
; i
++)
96 { Expression
*e
= (Expression
*)elements
->data
[i
];
98 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
99 elements
->data
[i
] = (void *)e
;
105 Expression
*AssocArrayLiteralExp::optimize(int result
)
107 assert(keys
->dim
== values
->dim
);
108 for (size_t i
= 0; i
< keys
->dim
; i
++)
109 { Expression
*e
= (Expression
*)keys
->data
[i
];
111 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
112 keys
->data
[i
] = (void *)e
;
114 e
= (Expression
*)values
->data
[i
];
115 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
116 values
->data
[i
] = (void *)e
;
121 Expression
*StructLiteralExp::optimize(int result
)
125 for (size_t i
= 0; i
< elements
->dim
; i
++)
126 { Expression
*e
= (Expression
*)elements
->data
[i
];
129 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
130 elements
->data
[i
] = (void *)e
;
136 Expression
*TypeExp::optimize(int result
)
141 Expression
*UnaExp::optimize(int result
)
143 e1
= e1
->optimize(result
);
147 Expression
*NegExp::optimize(int result
)
150 e1
= e1
->optimize(result
);
151 if (e1
->isConst() == 1)
160 Expression
*ComExp::optimize(int result
)
163 e1
= e1
->optimize(result
);
164 if (e1
->isConst() == 1)
173 Expression
*NotExp::optimize(int result
)
176 e1
= e1
->optimize(result
);
177 if (e1
->isConst() == 1)
186 Expression
*BoolExp::optimize(int result
)
189 e1
= e1
->optimize(result
);
190 if (e1
->isConst() == 1)
199 Expression
*AddrExp::optimize(int result
)
202 //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
203 e1
= e1
->optimize(result
);
204 // Convert &*ex to ex
205 if (e1
->op
== TOKstar
)
208 ex
= ((PtrExp
*)e1
)->e1
;
209 if (type
->equals(ex
->type
))
218 if (e1
->op
== TOKvar
)
219 { VarExp
*ve
= (VarExp
*)e1
;
220 if (!ve
->var
->isOut() && !ve
->var
->isRef() &&
221 !ve
->var
->isImportedSymbol())
223 e
= new SymOffExp(loc
, ve
->var
, 0);
228 if (e1
->op
== TOKindex
)
229 { // Convert &array[n] to &array+n
230 IndexExp
*ae
= (IndexExp
*)e1
;
232 if (ae
->e2
->op
== TOKint64
&& ae
->e1
->op
== TOKvar
)
234 integer_t index
= ae
->e2
->toInteger();
235 VarExp
*ve
= (VarExp
*)ae
->e1
;
236 if (ve
->type
->ty
== Tsarray
&& ve
->type
->next
->ty
!= Tbit
237 && !ve
->var
->isImportedSymbol())
239 TypeSArray
*ts
= (TypeSArray
*)ve
->type
;
240 integer_t dim
= ts
->dim
->toInteger();
241 if (index
< 0 || index
>= dim
)
242 error("array index %"PRIdMAX
" is out of bounds [0..%"PRIdMAX
"]", index
, dim
);
243 e
= new SymOffExp(loc
, ve
->var
, index
* ts
->next
->size());
252 Expression
*PtrExp::optimize(int result
)
254 //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
255 e1
= e1
->optimize(result
);
256 // Convert *&ex to ex
257 if (e1
->op
== TOKaddress
)
261 ex
= ((AddrExp
*)e1
)->e1
;
262 if (type
->equals(ex
->type
))
270 // Stuffing types does not always work in GCC
276 // Constant fold *(&structliteral + offset)
277 if (e1
->op
== TOKadd
)
281 if (e
!= EXP_CANT_INTERPRET
)
288 Expression
*CallExp::optimize(int result
)
289 { Expression
*e
= this;
291 e1
= e1
->optimize(result
);
292 if (e1
->op
== TOKvar
&& result
& WANTinterpret
)
294 FuncDeclaration
*fd
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
297 Expression
*eresult
= fd
->interpret(NULL
, arguments
);
298 if (eresult
&& eresult
!= EXP_VOID_INTERPRET
)
300 else if (result
& WANTinterpret
)
301 error("cannot evaluate %s at compile time", toChars());
308 Expression
*CastExp::optimize(int result
)
310 //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
311 //printf("from %s to %s\n", type->toChars(), to->toChars());
312 //printf("from %s\n", type->toChars());
313 //printf("type = %p\n", type);
315 enum TOK op1
= e1
->op
;
317 e1
= e1
->optimize(result
);
318 if (result
& WANTinterpret
)
319 e1
= fromConstInitializer(e1
);
321 if ((e1
->op
== TOKstring
|| e1
->op
== TOKarrayliteral
) &&
322 (type
->ty
== Tpointer
|| type
->ty
== Tarray
) &&
323 type
->next
->equals(e1
->type
->next
)
329 /* The first test here is to prevent infinite loops
331 if (op1
!= TOKarrayliteral
&& e1
->op
== TOKarrayliteral
)
332 return e1
->castTo(NULL
, to
);
333 if (e1
->op
== TOKnull
&&
334 (type
->ty
== Tpointer
|| type
->ty
== Tclass
))
340 if (result
& WANTflags
&& type
->ty
== Tclass
&& e1
->type
->ty
== Tclass
)
342 // See if we can remove an unnecessary cast
343 ClassDeclaration
*cdfrom
;
344 ClassDeclaration
*cdto
;
345 target_ptrdiff_t offset
;
347 cdfrom
= e1
->type
->isClassHandle();
348 cdto
= type
->isClassHandle();
349 if (cdto
->isBaseOf(cdfrom
, &offset
) && offset
== 0)
360 if (e1
->op
== TOKsymoff
)
362 if (type
->size() == e1
->type
->size() &&
363 type
->toBasetype()->ty
!= Tsarray
)
370 if (to
->toBasetype()->ty
== Tvoid
)
373 e
= Cast(type
, to
, e1
);
380 Expression
*BinExp::optimize(int result
)
382 //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
383 e1
= e1
->optimize(result
);
384 e2
= e2
->optimize(result
);
385 if (op
== TOKshlass
|| op
== TOKshrass
|| op
== TOKushrass
)
387 if (e2
->isConst() == 1)
389 integer_t i2
= e2
->toInteger();
390 d_uns64 sz
= e1
->type
->size() * 8;
391 if (i2
< 0 || i2
> sz
)
392 { error("shift assign by %jd is outside the range 0..%zu", i2
, sz
);
393 e2
= new IntegerExp(0);
400 Expression
*AddExp::optimize(int result
)
403 //printf("AddExp::optimize(%s)\n", toChars());
404 e1
= e1
->optimize(result
);
405 e2
= e2
->optimize(result
);
406 if (e1
->isConst() && e2
->isConst())
408 if (e1
->op
== TOKsymoff
&& e2
->op
== TOKsymoff
)
410 e
= Add(type
, e1
, e2
);
417 Expression
*MinExp::optimize(int result
)
420 e1
= e1
->optimize(result
);
421 e2
= e2
->optimize(result
);
422 if (e1
->isConst() && e2
->isConst())
424 if (e2
->op
== TOKsymoff
)
426 e
= Min(type
, e1
, e2
);
433 Expression
*MulExp::optimize(int result
)
436 //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
437 e1
= e1
->optimize(result
);
438 e2
= e2
->optimize(result
);
439 if (e1
->isConst() == 1 && e2
->isConst() == 1)
441 e
= Mul(type
, e1
, e2
);
448 Expression
*DivExp::optimize(int result
)
451 //printf("DivExp::optimize(%s)\n", toChars());
452 e1
= e1
->optimize(result
);
453 e2
= e2
->optimize(result
);
454 if (e1
->isConst() == 1 && e2
->isConst() == 1)
456 e
= Div(type
, e1
, e2
);
463 Expression
*ModExp::optimize(int result
)
466 e1
= e1
->optimize(result
);
467 e2
= e2
->optimize(result
);
468 if (e1
->isConst() == 1 && e2
->isConst() == 1)
470 e
= Mod(type
, e1
, e2
);
477 Expression
*shift_optimize(int result
, BinExp
*e
, Expression
*(*shift
)(Type
*, Expression
*, Expression
*))
478 { Expression
*ex
= e
;
480 e
->e1
= e
->e1
->optimize(result
);
481 e
->e2
= e
->e2
->optimize(result
);
482 if (e
->e2
->isConst() == 1)
484 integer_t i2
= e
->e2
->toInteger();
485 target_size_t sz
= e
->e1
->type
->size() * 8;
486 if (i2
< 0 || i2
> sz
)
487 { error("shift left by %"PRIdMAX
" exceeds %"PRIuTSIZE
, i2
, sz
);
488 e
->e2
= new IntegerExp(0);
490 if (e
->e1
->isConst() == 1)
491 ex
= (*shift
)(e
->type
, e
->e1
, e
->e2
);
496 Expression
*ShlExp::optimize(int result
)
498 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
499 return shift_optimize(result
, this, Shl
);
502 Expression
*ShrExp::optimize(int result
)
504 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
505 return shift_optimize(result
, this, Shr
);
508 Expression
*UshrExp::optimize(int result
)
510 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
511 return shift_optimize(result
, this, Ushr
);
514 Expression
*AndExp::optimize(int result
)
517 e1
= e1
->optimize(result
);
518 e2
= e2
->optimize(result
);
519 if (e1
->isConst() == 1 && e2
->isConst() == 1)
520 e
= And(type
, e1
, e2
);
526 Expression
*OrExp::optimize(int result
)
529 e1
= e1
->optimize(result
);
530 e2
= e2
->optimize(result
);
531 if (e1
->isConst() == 1 && e2
->isConst() == 1)
532 e
= Or(type
, e1
, e2
);
538 Expression
*XorExp::optimize(int result
)
541 e1
= e1
->optimize(result
);
542 e2
= e2
->optimize(result
);
543 if (e1
->isConst() == 1 && e2
->isConst() == 1)
544 e
= Xor(type
, e1
, e2
);
550 Expression
*CommaExp::optimize(int result
)
553 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
554 e1
= e1
->optimize(result
& WANTinterpret
);
555 e2
= e2
->optimize(result
);
556 if (!e1
|| e1
->op
== TOKint64
|| e1
->op
== TOKfloat64
|| !e1
->checkSideEffect(2))
564 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
568 Expression
*ArrayLengthExp::optimize(int result
)
571 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
572 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
574 if (e1
->op
== TOKstring
|| e1
->op
== TOKarrayliteral
|| e1
->op
== TOKassocarrayliteral
)
576 e
= ArrayLength(type
, e1
);
581 Expression
*EqualExp::optimize(int result
)
584 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
585 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
586 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
589 Expression
*e1
= fromConstInitializer(this->e1
);
590 Expression
*e2
= fromConstInitializer(this->e2
);
592 e
= Equal(op
, type
, e1
, e2
);
593 if (e
== EXP_CANT_INTERPRET
)
598 Expression
*IdentityExp::optimize(int result
)
601 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
602 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
603 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
605 if (this->e1
->isConst() && this->e2
->isConst())
607 e
= Identity(op
, type
, this->e1
, this->e2
);
612 Expression
*IndexExp::optimize(int result
)
615 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
616 Expression
*e1
= this->e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
617 if (result
& WANTinterpret
)
618 e1
= fromConstInitializer(e1
);
619 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
620 e
= Index(type
, e1
, e2
);
621 if (e
== EXP_CANT_INTERPRET
)
626 Expression
*SliceExp::optimize(int result
)
629 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
631 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
633 { if (e1
->op
== TOKstring
)
634 { // Convert slice of string literal into dynamic array
635 Type
*t
= e1
->type
->toBasetype();
637 e
= e1
->castTo(NULL
, t
->next
->arrayOf());
641 if (result
& WANTinterpret
)
642 e1
= fromConstInitializer(e1
);
643 lwr
= lwr
->optimize(WANTvalue
| (result
& WANTinterpret
));
644 upr
= upr
->optimize(WANTvalue
| (result
& WANTinterpret
));
645 e
= Slice(type
, e1
, lwr
, upr
);
646 if (e
== EXP_CANT_INTERPRET
)
651 Expression
*AndAndExp::optimize(int result
)
654 //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
655 e1
= e1
->optimize(WANTflags
| (result
& WANTinterpret
));
657 if (e1
->isBool(FALSE
))
659 e
= new CommaExp(loc
, e1
, new IntegerExp(loc
, 0, type
));
661 e
= e
->optimize(result
);
665 e2
= e2
->optimize(WANTflags
| (result
& WANTinterpret
));
666 if (result
&& e2
->type
->toBasetype()->ty
== Tvoid
&& !global
.errors
)
667 error("void has no value");
671 { int n1
= e1
->isBool(1);
672 int n2
= e2
->isBool(1);
674 e
= new IntegerExp(loc
, n1
&& n2
, type
);
676 else if (e1
->isBool(TRUE
))
677 e
= new BoolExp(loc
, e2
, type
);
683 Expression
*OrOrExp::optimize(int result
)
686 e1
= e1
->optimize(WANTflags
| (result
& WANTinterpret
));
688 if (e1
->isBool(TRUE
))
689 { // Replace with (e1, 1)
690 e
= new CommaExp(loc
, e1
, new IntegerExp(loc
, 1, type
));
692 e
= e
->optimize(result
);
696 e2
= e2
->optimize(WANTflags
| (result
& WANTinterpret
));
697 if (result
&& e2
->type
->toBasetype()->ty
== Tvoid
&& !global
.errors
)
698 error("void has no value");
702 { int n1
= e1
->isBool(1);
703 int n2
= e2
->isBool(1);
705 e
= new IntegerExp(loc
, n1
|| n2
, type
);
707 else if (e1
->isBool(FALSE
))
708 e
= new BoolExp(loc
, e2
, type
);
714 Expression
*CmpExp::optimize(int result
)
717 //printf("CmpExp::optimize() %s\n", toChars());
718 e1
= e1
->optimize(result
);
719 e2
= e2
->optimize(result
);
720 if (e1
->isConst() == 1 && e2
->isConst() == 1)
722 e
= Cmp(op
, type
, this->e1
, this->e2
);
729 Expression
*CatExp::optimize(int result
)
732 //printf("CatExp::optimize(%d) %s\n", result, toChars());
733 e1
= e1
->optimize(result
);
734 e2
= e2
->optimize(result
);
735 e
= Cat(type
, e1
, e2
);
736 if (e
== EXP_CANT_INTERPRET
)
742 Expression
*CondExp::optimize(int result
)
745 econd
= econd
->optimize(WANTflags
| (result
& WANTinterpret
));
746 if (econd
->isBool(TRUE
))
747 e
= e1
->optimize(result
);
748 else if (econd
->isBool(FALSE
))
749 e
= e2
->optimize(result
);
751 { e1
= e1
->optimize(result
);
752 e2
= e2
->optimize(result
);