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 variable has a const initializer,
46 * return that initializer.
49 Expression
*expandVar(int result
, VarDeclaration
*v
)
51 //printf("expandVar(result = %d, v = %s)\n", result, v ? v->toChars() : "null");
53 if (v
&& (v
->isConst() || v
->isInvariant() || v
->storage_class
& STCmanifest
))
55 Type
*tb
= v
->type
->toBasetype();
56 if (result
& WANTinterpret
||
57 v
->storage_class
& STCmanifest
||
58 (tb
->ty
!= Tsarray
&& tb
->ty
!= Tstruct
)
65 Expression
*ei
= v
->init
->toExpression();
68 if (ei
->op
== TOKconstruct
|| ei
->op
== TOKblit
)
69 { AssignExp
*ae
= (AssignExp
*)ei
;
71 if (ei
->isConst() != 1 && ei
->op
!= TOKstring
)
73 if (ei
->type
!= v
->type
)
80 e
= e
->semantic(v
->scope
);
81 e
= e
->implicitCastTo(v
->scope
, v
->type
);
90 // Should remove the copy() operation by
91 // making all mods to expressions copy-on-write
99 // BUG: what if const is initialized in constructor?
100 e
= v
->type
->defaultInit();
104 if (e
->type
!= v
->type
)
106 e
= e
->castTo(NULL
, v
->type
);
108 e
= e
->optimize(result
);
112 //if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars());
117 Expression
*fromConstInitializer(int result
, Expression
*e1
)
119 //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
120 //static int xx; if (xx++ == 10) assert(0);
122 if (e1
->op
== TOKvar
)
123 { VarExp
*ve
= (VarExp
*)e1
;
124 VarDeclaration
*v
= ve
->var
->isVarDeclaration();
125 e
= expandVar(result
, v
);
127 { if (e
->type
!= e1
->type
)
128 { // Type 'paint' operation
140 Expression
*Expression::optimize(int result
)
142 //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
146 Expression
*VarExp::optimize(int result
)
148 return fromConstInitializer(result
, this);
151 Expression
*TupleExp::optimize(int result
)
153 for (size_t i
= 0; i
< exps
->dim
; i
++)
154 { Expression
*e
= (Expression
*)exps
->data
[i
];
156 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
157 exps
->data
[i
] = (void *)e
;
162 Expression
*ArrayLiteralExp::optimize(int result
)
166 for (size_t i
= 0; i
< elements
->dim
; i
++)
167 { Expression
*e
= (Expression
*)elements
->data
[i
];
169 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
170 elements
->data
[i
] = (void *)e
;
176 Expression
*AssocArrayLiteralExp::optimize(int result
)
178 assert(keys
->dim
== values
->dim
);
179 for (size_t i
= 0; i
< keys
->dim
; i
++)
180 { Expression
*e
= (Expression
*)keys
->data
[i
];
182 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
183 keys
->data
[i
] = (void *)e
;
185 e
= (Expression
*)values
->data
[i
];
186 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
187 values
->data
[i
] = (void *)e
;
192 Expression
*StructLiteralExp::optimize(int result
)
196 for (size_t i
= 0; i
< elements
->dim
; i
++)
197 { Expression
*e
= (Expression
*)elements
->data
[i
];
200 e
= e
->optimize(WANTvalue
| (result
& WANTinterpret
));
201 elements
->data
[i
] = (void *)e
;
207 Expression
*TypeExp::optimize(int result
)
212 Expression
*UnaExp::optimize(int result
)
214 e1
= e1
->optimize(result
);
218 Expression
*NegExp::optimize(int result
)
221 e1
= e1
->optimize(result
);
222 if (e1
->isConst() == 1)
231 Expression
*ComExp::optimize(int result
)
234 e1
= e1
->optimize(result
);
235 if (e1
->isConst() == 1)
244 Expression
*NotExp::optimize(int result
)
247 e1
= e1
->optimize(result
);
248 if (e1
->isConst() == 1)
257 Expression
*BoolExp::optimize(int result
)
260 e1
= e1
->optimize(result
);
261 if (e1
->isConst() == 1)
270 Expression
*AddrExp::optimize(int result
)
273 //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
275 /* Rewrite &(a,b) as (a,&b)
277 if (e1
->op
== TOKcomma
)
278 { CommaExp
*ce
= (CommaExp
*)e1
;
279 AddrExp
*ae
= new AddrExp(loc
, ce
->e2
);
281 e
= new CommaExp(ce
->loc
, ce
->e1
, ae
);
283 return e
->optimize(result
);
286 if (e1
->op
== TOKvar
)
287 { VarExp
*ve
= (VarExp
*)e1
;
288 if (ve
->var
->storage_class
& STCmanifest
)
289 e1
= e1
->optimize(result
);
292 e1
= e1
->optimize(result
);
294 // Convert &*ex to ex
295 if (e1
->op
== TOKstar
)
298 ex
= ((PtrExp
*)e1
)->e1
;
299 if (type
->equals(ex
->type
))
307 // Stuffing types does not always work in GCC
313 if (e1
->op
== TOKvar
)
314 { VarExp
*ve
= (VarExp
*)e1
;
315 if (!ve
->var
->isOut() && !ve
->var
->isRef() &&
316 !ve
->var
->isImportedSymbol())
318 SymOffExp
*se
= new SymOffExp(loc
, ve
->var
, 0, ve
->hasOverloads
);
323 if (e1
->op
== TOKindex
)
324 { // Convert &array[n] to &array+n
325 IndexExp
*ae
= (IndexExp
*)e1
;
327 if (ae
->e2
->op
== TOKint64
&& ae
->e1
->op
== TOKvar
)
329 integer_t index
= ae
->e2
->toInteger();
330 VarExp
*ve
= (VarExp
*)ae
->e1
;
331 if (ve
->type
->ty
== Tsarray
332 && !ve
->var
->isImportedSymbol())
334 TypeSArray
*ts
= (TypeSArray
*)ve
->type
;
335 integer_t dim
= ts
->dim
->toInteger();
336 if (index
< 0 || index
>= dim
)
337 error("array index %"PRIdMAX
" is out of bounds [0..%"PRIdMAX
"]", index
, dim
);
338 e
= new SymOffExp(loc
, ve
->var
, index
* ts
->nextOf()->size());
347 Expression
*PtrExp::optimize(int result
)
349 //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars());
350 e1
= e1
->optimize(result
);
351 // Convert *&ex to ex
352 if (e1
->op
== TOKaddress
)
356 ex
= ((AddrExp
*)e1
)->e1
;
357 if (type
->equals(ex
->type
))
365 // Stuffing types does not always work in GCC
371 // Constant fold *(&structliteral + offset)
372 if (e1
->op
== TOKadd
)
376 if (e
!= EXP_CANT_INTERPRET
)
380 if (e1
->op
== TOKsymoff
)
381 { SymOffExp
*se
= (SymOffExp
*)e1
;
382 VarDeclaration
*v
= se
->var
->isVarDeclaration();
383 Expression
*e
= expandVar(result
, v
);
384 if (e
&& e
->op
== TOKstructliteral
)
385 { StructLiteralExp
*sle
= (StructLiteralExp
*)e
;
386 e
= sle
->getField(type
, se
->offset
);
387 if (e
!= EXP_CANT_INTERPRET
)
394 Expression
*CallExp::optimize(int result
)
396 //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
397 Expression
*e
= this;
399 e1
= e1
->optimize(result
);
400 if (e1
->op
== TOKvar
)
402 FuncDeclaration
*fd
= ((VarExp
*)e1
)->var
->isFuncDeclaration();
405 enum BUILTIN b
= fd
->isBuiltin();
408 e
= eval_builtin(b
, arguments
);
410 e
= this; // evaluate at runtime
412 else if (result
& WANTinterpret
)
414 Expression
*eresult
= fd
->interpret(NULL
, arguments
);
415 if (eresult
&& eresult
!= EXP_VOID_INTERPRET
)
418 error("cannot evaluate %s at compile time", toChars());
426 Expression
*CastExp::optimize(int result
)
428 //printf("CastExp::optimize(result = %d) %s\n", result, toChars());
429 //printf("from %s to %s\n", type->toChars(), to->toChars());
430 //printf("from %s\n", type->toChars());
431 //printf("e1->type %s\n", e1->type->toChars());
432 //printf("type = %p\n", type);
434 enum TOK op1
= e1
->op
;
437 e1
= e1
->optimize(result
);
438 e1
= fromConstInitializer(result
, e1
);
440 if ((e1
->op
== TOKstring
|| e1
->op
== TOKarrayliteral
) &&
441 (type
->ty
== Tpointer
|| type
->ty
== Tarray
) &&
442 e1
->type
->nextOf()->size() == type
->nextOf()->size()
445 e1
= e1
->castTo(NULL
, type
);
446 if (X
) printf(" returning1 %s\n", e1
->toChars());
450 if (e1
->op
== TOKstructliteral
&&
451 e1
->type
->implicitConvTo(type
) >= MATCHconst
)
454 if (X
) printf(" returning2 %s\n", e1
->toChars());
458 /* The first test here is to prevent infinite loops
460 if (op1
!= TOKarrayliteral
&& e1
->op
== TOKarrayliteral
)
461 return e1
->castTo(NULL
, to
);
462 if (e1
->op
== TOKnull
&&
463 (type
->ty
== Tpointer
|| type
->ty
== Tclass
|| type
->ty
== Tarray
))
466 if (X
) printf(" returning3 %s\n", e1
->toChars());
470 if (result
& WANTflags
&& type
->ty
== Tclass
&& e1
->type
->ty
== Tclass
)
472 // See if we can remove an unnecessary cast
473 ClassDeclaration
*cdfrom
;
474 ClassDeclaration
*cdto
;
475 target_ptrdiff_t offset
;
477 cdfrom
= e1
->type
->isClassHandle();
478 cdto
= type
->isClassHandle();
479 if (cdto
->isBaseOf(cdfrom
, &offset
) && offset
== 0)
482 if (X
) printf(" returning4 %s\n", e1
->toChars());
487 // We can convert 'head const' to mutable
488 if (to
->constOf()->equals(e1
->type
->constOf()))
489 // if (to->constConv(e1->type) >= MATCHconst)
492 if (X
) printf(" returning5 %s\n", e1
->toChars());
500 if (e1
->op
== TOKsymoff
)
502 if (type
->size() == e1
->type
->size() &&
503 type
->toBasetype()->ty
!= Tsarray
)
510 if (to
->toBasetype()->ty
== Tvoid
)
513 e
= Cast(type
, to
, e1
);
517 if (X
) printf(" returning6 %s\n", e
->toChars());
522 Expression
*BinExp::optimize(int result
)
524 //printf("BinExp::optimize(result = %d) %s\n", result, toChars());
525 if (op
!= TOKconstruct
&& op
!= TOKblit
) // don't replace const variable with its initializer
526 e1
= e1
->optimize(result
);
527 e2
= e2
->optimize(result
);
528 if (op
== TOKshlass
|| op
== TOKshrass
|| op
== TOKushrass
)
530 if (e2
->isConst() == 1)
532 integer_t i2
= e2
->toInteger();
533 d_uns64 sz
= e1
->type
->size() * 8;
534 if (i2
< 0 || i2
> sz
)
535 { error("shift assign by %jd is outside the range 0..%zu", i2
, sz
);
536 e2
= new IntegerExp(0);
543 Expression
*AddExp::optimize(int result
)
546 //printf("AddExp::optimize(%s)\n", toChars());
547 e1
= e1
->optimize(result
);
548 e2
= e2
->optimize(result
);
549 if (e1
->isConst() && e2
->isConst())
551 if (e1
->op
== TOKsymoff
&& e2
->op
== TOKsymoff
)
553 e
= Add(type
, e1
, e2
);
560 Expression
*MinExp::optimize(int result
)
563 e1
= e1
->optimize(result
);
564 e2
= e2
->optimize(result
);
565 if (e1
->isConst() && e2
->isConst())
567 if (e2
->op
== TOKsymoff
)
569 e
= Min(type
, e1
, e2
);
576 Expression
*MulExp::optimize(int result
)
579 //printf("MulExp::optimize(result = %d) %s\n", result, toChars());
580 e1
= e1
->optimize(result
);
581 e2
= e2
->optimize(result
);
582 if (e1
->isConst() == 1 && e2
->isConst() == 1)
584 e
= Mul(type
, e1
, e2
);
591 Expression
*DivExp::optimize(int result
)
594 //printf("DivExp::optimize(%s)\n", toChars());
595 e1
= e1
->optimize(result
);
596 e2
= e2
->optimize(result
);
597 if (e1
->isConst() == 1 && e2
->isConst() == 1)
599 e
= Div(type
, e1
, e2
);
606 Expression
*ModExp::optimize(int result
)
609 e1
= e1
->optimize(result
);
610 e2
= e2
->optimize(result
);
611 if (e1
->isConst() == 1 && e2
->isConst() == 1)
613 e
= Mod(type
, e1
, e2
);
620 Expression
*shift_optimize(int result
, BinExp
*e
, Expression
*(*shift
)(Type
*, Expression
*, Expression
*))
621 { Expression
*ex
= e
;
623 e
->e1
= e
->e1
->optimize(result
);
624 e
->e2
= e
->e2
->optimize(result
);
625 if (e
->e2
->isConst() == 1)
627 integer_t i2
= e
->e2
->toInteger();
628 target_size_t sz
= e
->e1
->type
->size() * 8;
629 if (i2
< 0 || i2
> sz
)
630 { error("shift left by %"PRIdMAX
" exceeds %"PRIuTSIZE
, i2
, sz
);
631 e
->e2
= new IntegerExp(0);
633 if (e
->e1
->isConst() == 1)
634 ex
= (*shift
)(e
->type
, e
->e1
, e
->e2
);
639 Expression
*ShlExp::optimize(int result
)
641 //printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
642 return shift_optimize(result
, this, Shl
);
645 Expression
*ShrExp::optimize(int result
)
647 //printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
648 return shift_optimize(result
, this, Shr
);
651 Expression
*UshrExp::optimize(int result
)
653 //printf("UshrExp::optimize(result = %d) %s\n", result, toChars());
654 return shift_optimize(result
, this, Ushr
);
657 Expression
*AndExp::optimize(int result
)
660 e1
= e1
->optimize(result
);
661 e2
= e2
->optimize(result
);
662 if (e1
->isConst() == 1 && e2
->isConst() == 1)
663 e
= And(type
, e1
, e2
);
669 Expression
*OrExp::optimize(int result
)
672 e1
= e1
->optimize(result
);
673 e2
= e2
->optimize(result
);
674 if (e1
->isConst() == 1 && e2
->isConst() == 1)
675 e
= Or(type
, e1
, e2
);
681 Expression
*XorExp::optimize(int result
)
684 e1
= e1
->optimize(result
);
685 e2
= e2
->optimize(result
);
686 if (e1
->isConst() == 1 && e2
->isConst() == 1)
687 e
= Xor(type
, e1
, e2
);
693 Expression
*CommaExp::optimize(int result
)
696 //printf("CommaExp::optimize(result = %d) %s\n", result, toChars());
697 e1
= e1
->optimize(result
& WANTinterpret
);
698 e2
= e2
->optimize(result
);
699 if (!e1
|| e1
->op
== TOKint64
|| e1
->op
== TOKfloat64
|| !e1
->checkSideEffect(2))
707 //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars());
711 Expression
*ArrayLengthExp::optimize(int result
)
714 //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
715 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
717 if (e1
->op
== TOKstring
|| e1
->op
== TOKarrayliteral
|| e1
->op
== TOKassocarrayliteral
)
719 e
= ArrayLength(type
, e1
);
724 Expression
*EqualExp::optimize(int result
)
727 //printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
728 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
729 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
732 Expression
*e1
= fromConstInitializer(result
, this->e1
);
733 Expression
*e2
= fromConstInitializer(result
, this->e2
);
735 e
= Equal(op
, type
, e1
, e2
);
736 if (e
== EXP_CANT_INTERPRET
)
741 Expression
*IdentityExp::optimize(int result
)
744 //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars());
745 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
746 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
748 if (this->e1
->isConst() && this->e2
->isConst())
750 e
= Identity(op
, type
, this->e1
, this->e2
);
755 Expression
*IndexExp::optimize(int result
)
758 //printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
759 Expression
*e1
= this->e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
760 e1
= fromConstInitializer(result
, e1
);
761 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
762 e
= Index(type
, e1
, e2
);
763 if (e
== EXP_CANT_INTERPRET
)
768 Expression
*SliceExp::optimize(int result
)
771 //printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
773 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
775 { if (e1
->op
== TOKstring
)
776 { // Convert slice of string literal into dynamic array
777 Type
*t
= e1
->type
->toBasetype();
779 e
= e1
->castTo(NULL
, t
->nextOf()->arrayOf());
783 e1
= fromConstInitializer(result
, e1
);
784 lwr
= lwr
->optimize(WANTvalue
| (result
& WANTinterpret
));
785 upr
= upr
->optimize(WANTvalue
| (result
& WANTinterpret
));
786 e
= Slice(type
, e1
, lwr
, upr
);
787 if (e
== EXP_CANT_INTERPRET
)
789 //printf("-SliceExp::optimize() %s\n", e->toChars());
793 Expression
*AndAndExp::optimize(int result
)
796 //printf("AndAndExp::optimize(%d) %s\n", result, toChars());
797 e1
= e1
->optimize(WANTflags
| (result
& WANTinterpret
));
799 if (e1
->isBool(FALSE
))
801 e
= new CommaExp(loc
, e1
, new IntegerExp(loc
, 0, type
));
803 e
= e
->optimize(result
);
807 e2
= e2
->optimize(WANTflags
| (result
& WANTinterpret
));
808 if (result
&& e2
->type
->toBasetype()->ty
== Tvoid
&& !global
.errors
)
809 error("void has no value");
813 { int n1
= e1
->isBool(1);
814 int n2
= e2
->isBool(1);
816 e
= new IntegerExp(loc
, n1
&& n2
, type
);
818 else if (e1
->isBool(TRUE
))
819 e
= new BoolExp(loc
, e2
, type
);
825 Expression
*OrOrExp::optimize(int result
)
828 e1
= e1
->optimize(WANTflags
| (result
& WANTinterpret
));
830 if (e1
->isBool(TRUE
))
831 { // Replace with (e1, 1)
832 e
= new CommaExp(loc
, e1
, new IntegerExp(loc
, 1, type
));
834 e
= e
->optimize(result
);
838 e2
= e2
->optimize(WANTflags
| (result
& WANTinterpret
));
839 if (result
&& e2
->type
->toBasetype()->ty
== Tvoid
&& !global
.errors
)
840 error("void has no value");
844 { int n1
= e1
->isBool(1);
845 int n2
= e2
->isBool(1);
847 e
= new IntegerExp(loc
, n1
|| n2
, type
);
849 else if (e1
->isBool(FALSE
))
850 e
= new BoolExp(loc
, e2
, type
);
856 Expression
*CmpExp::optimize(int result
)
859 //printf("CmpExp::optimize() %s\n", toChars());
860 e1
= e1
->optimize(WANTvalue
| (result
& WANTinterpret
));
861 e2
= e2
->optimize(WANTvalue
| (result
& WANTinterpret
));
863 Expression
*e1
= fromConstInitializer(result
, this->e1
);
864 Expression
*e2
= fromConstInitializer(result
, this->e2
);
866 e
= Cmp(op
, type
, e1
, e2
);
867 if (e
== EXP_CANT_INTERPRET
)
872 Expression
*CatExp::optimize(int result
)
875 //printf("CatExp::optimize(%d) %s\n", result, toChars());
876 e1
= e1
->optimize(result
);
877 e2
= e2
->optimize(result
);
878 e
= Cat(type
, e1
, e2
);
879 if (e
== EXP_CANT_INTERPRET
)
885 Expression
*CondExp::optimize(int result
)
888 econd
= econd
->optimize(WANTflags
| (result
& WANTinterpret
));
889 if (econd
->isBool(TRUE
))
890 e
= e1
->optimize(result
);
891 else if (econd
->isBool(FALSE
))
892 e
= e2
->optimize(result
);
894 { e1
= e1
->optimize(result
);
895 e2
= e2
->optimize(result
);