1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/constfold.c
9  */
10 
11 #include "root/dsystem.h"               // mem{cpy|set|cmp}()
12 
13 #ifndef IN_GCC
14 #include <math.h>
15 #endif
16 
17 #include "root/rmem.h"
18 #include "root/root.h"
19 #include "root/port.h"
20 
21 #include "errors.h"
22 #include "mtype.h"
23 #include "expression.h"
24 #include "aggregate.h"
25 #include "declaration.h"
26 #include "utf.h"
27 #include "ctfe.h"
28 #include "target.h"
29 
30 int RealEquals(real_t x1, real_t x2);
31 
expType(Type * type,Expression * e)32 Expression *expType(Type *type, Expression *e)
33 {
34     if (type != e->type)
35     {
36         e = e->copy();
37         e->type = type;
38     }
39     return e;
40 }
41 
42 /* ================================== isConst() ============================== */
43 
isConst(Expression * e)44 int isConst(Expression *e)
45 {
46     //printf("Expression::isConst(): %s\n", e->toChars());
47     switch (e->op)
48     {
49         case TOKint64:
50         case TOKfloat64:
51         case TOKcomplex80:
52             return 1;
53         case TOKnull:
54             return 0;
55         case TOKsymoff:
56             return 2;
57         default:
58             return 0;
59     }
60     assert(0);
61     return 0;
62 }
63 
64 /* =============================== constFold() ============================== */
65 
66 /* The constFold() functions were redundant with the optimize() ones,
67  * and so have been folded in with them.
68  */
69 
70 /* ========================================================================== */
71 
Neg(Type * type,Expression * e1)72 UnionExp Neg(Type *type, Expression *e1)
73 {
74     UnionExp ue;
75     Loc loc = e1->loc;
76 
77     if (e1->type->isreal())
78     {
79         new(&ue) RealExp(loc, -e1->toReal(), type);
80     }
81     else if (e1->type->isimaginary())
82     {
83         new(&ue) RealExp(loc, -e1->toImaginary(), type);
84     }
85     else if (e1->type->iscomplex())
86     {
87         new(&ue) ComplexExp(loc, -e1->toComplex(), type);
88     }
89     else
90     {
91         new(&ue) IntegerExp(loc, -e1->toInteger(), type);
92     }
93     return ue;
94 }
95 
Com(Type * type,Expression * e1)96 UnionExp Com(Type *type, Expression *e1)
97 {
98     UnionExp ue;
99     Loc loc = e1->loc;
100 
101     new(&ue) IntegerExp(loc, ~e1->toInteger(), type);
102     return ue;
103 }
104 
Not(Type * type,Expression * e1)105 UnionExp Not(Type *type, Expression *e1)
106 {
107     UnionExp ue;
108     Loc loc = e1->loc;
109 
110     new(&ue) IntegerExp(loc, e1->isBool(false) ? 1 : 0, type);
111     return ue;
112 }
113 
Bool(Type * type,Expression * e1)114 UnionExp Bool(Type *type, Expression *e1)
115 {
116     UnionExp ue;
117     Loc loc = e1->loc;
118 
119     new(&ue) IntegerExp(loc, e1->isBool(true) ? 1 : 0, type);
120     return ue;
121 }
122 
Add(Loc loc,Type * type,Expression * e1,Expression * e2)123 UnionExp Add(Loc loc, Type *type, Expression *e1, Expression *e2)
124 {
125     UnionExp ue;
126 
127     if (type->isreal())
128     {
129         new(&ue) RealExp(loc, e1->toReal() + e2->toReal(), type);
130     }
131     else if (type->isimaginary())
132     {
133         new(&ue) RealExp(loc, e1->toImaginary() + e2->toImaginary(), type);
134     }
135     else if (type->iscomplex())
136     {
137         // This rigamarole is necessary so that -0.0 doesn't get
138         // converted to +0.0 by doing an extraneous add with +0.0
139         complex_t c1 = complex_t(CTFloat::zero);
140         real_t r1 = CTFloat::zero;
141         real_t i1 = CTFloat::zero;
142 
143         complex_t c2 = complex_t(CTFloat::zero);
144         real_t r2 = CTFloat::zero;
145         real_t i2 = CTFloat::zero;
146 
147         complex_t v = complex_t(CTFloat::zero);
148         int x;
149 
150         if (e1->type->isreal())
151         {
152             r1 = e1->toReal();
153             x = 0;
154         }
155         else if (e1->type->isimaginary())
156         {
157             i1 = e1->toImaginary();
158             x = 3;
159         }
160         else
161         {
162             c1 = e1->toComplex();
163             x = 6;
164         }
165 
166         if (e2->type->isreal())
167         {
168             r2 = e2->toReal();
169         }
170         else if (e2->type->isimaginary())
171         {
172             i2 = e2->toImaginary();
173             x += 1;
174         }
175         else
176         {
177             c2 = e2->toComplex();
178             x += 2;
179         }
180 
181         switch (x)
182         {
183         case 0 + 0:
184             v = complex_t(r1 + r2);
185             break;
186         case 0 + 1:
187             v = complex_t(r1, i2);
188             break;
189         case 0 + 2:
190             v = complex_t(r1 + creall(c2), cimagl(c2));
191             break;
192         case 3 + 0:
193             v = complex_t(r2, i1);
194             break;
195         case 3 + 1:
196             v = complex_t(CTFloat::zero, i1 + i2);
197             break;
198         case 3 + 2:
199             v = complex_t(creall(c2), i1 + cimagl(c2));
200             break;
201         case 6 + 0:
202             v = complex_t(creall(c1) + r2, cimagl(c2));
203             break;
204         case 6 + 1:
205             v = complex_t(creall(c1), cimagl(c1) + i2);
206             break;
207         case 6 + 2:
208             v = c1 + c2;
209             break;
210         default:
211             assert(0);
212         }
213         new(&ue) ComplexExp(loc, v, type);
214     }
215     else if (e1->op == TOKsymoff)
216     {
217         SymOffExp *soe = (SymOffExp *)e1;
218         new(&ue) SymOffExp(loc, soe->var, soe->offset + e2->toInteger());
219         ue.exp()->type = type;
220     }
221     else if (e2->op == TOKsymoff)
222     {
223         SymOffExp *soe = (SymOffExp *)e2;
224         new(&ue) SymOffExp(loc, soe->var, soe->offset + e1->toInteger());
225         ue.exp()->type = type;
226     }
227     else
228         new(&ue) IntegerExp(loc, e1->toInteger() + e2->toInteger(), type);
229     return ue;
230 }
231 
232 
Min(Loc loc,Type * type,Expression * e1,Expression * e2)233 UnionExp Min(Loc loc, Type *type, Expression *e1, Expression *e2)
234 {
235     UnionExp ue;
236 
237     if (type->isreal())
238     {
239         new(&ue) RealExp(loc, e1->toReal() - e2->toReal(), type);
240     }
241     else if (type->isimaginary())
242     {
243         new(&ue) RealExp(loc, e1->toImaginary() - e2->toImaginary(), type);
244     }
245     else if (type->iscomplex())
246     {
247         // This rigamarole is necessary so that -0.0 doesn't get
248         // converted to +0.0 by doing an extraneous add with +0.0
249         complex_t c1 = complex_t(CTFloat::zero);
250         real_t r1 = CTFloat::zero;
251         real_t i1 = CTFloat::zero;
252 
253         complex_t c2 = complex_t(CTFloat::zero);
254         real_t r2 = CTFloat::zero;
255         real_t i2 = CTFloat::zero;
256 
257         complex_t v = complex_t(CTFloat::zero);
258         int x;
259 
260         if (e1->type->isreal())
261         {
262             r1 = e1->toReal();
263             x = 0;
264         }
265         else if (e1->type->isimaginary())
266         {
267             i1 = e1->toImaginary();
268             x = 3;
269         }
270         else
271         {
272             c1 = e1->toComplex();
273             x = 6;
274         }
275 
276         if (e2->type->isreal())
277         {
278             r2 = e2->toReal();
279         }
280         else if (e2->type->isimaginary())
281         {
282             i2 = e2->toImaginary();
283             x += 1;
284         }
285         else
286         {
287             c2 = e2->toComplex();
288             x += 2;
289         }
290 
291         switch (x)
292         {
293         case 0 + 0:
294             v = complex_t(r1 - r2);
295             break;
296         case 0 + 1:
297             v = complex_t(r1, -i2);
298             break;
299         case 0 + 2:
300             v = complex_t(r1 - creall(c2), -cimagl(c2));
301             break;
302         case 3 + 0:
303             v = complex_t(-r2, i1);
304             break;
305         case 3 + 1:
306             v = complex_t(CTFloat::zero, i1 - i2);
307             break;
308         case 3 + 2:
309             v = complex_t(-creall(c2), i1 - cimagl(c2));
310             break;
311         case 6 + 0:
312             v = complex_t(creall(c1) - r2, cimagl(c1));
313             break;
314         case 6 + 1:
315             v = complex_t(creall(c1), cimagl(c1) - i2);
316             break;
317         case 6 + 2:
318             v = c1 - c2;
319             break;
320         default:
321             assert(0);
322         }
323         new(&ue) ComplexExp(loc, v, type);
324     }
325     else if (e1->op == TOKsymoff)
326     {
327         SymOffExp *soe = (SymOffExp *)e1;
328         new(&ue) SymOffExp(loc, soe->var, soe->offset - e2->toInteger());
329         ue.exp()->type = type;
330     }
331     else
332     {
333         new(&ue) IntegerExp(loc, e1->toInteger() - e2->toInteger(), type);
334     }
335     return ue;
336 }
337 
Mul(Loc loc,Type * type,Expression * e1,Expression * e2)338 UnionExp Mul(Loc loc, Type *type, Expression *e1, Expression *e2)
339 {
340     UnionExp ue;
341 
342     if (type->isfloating())
343     {
344         complex_t c = complex_t(CTFloat::zero);
345         real_t r;
346 
347         if (e1->type->isreal())
348         {
349             r = e1->toReal();
350             c = e2->toComplex();
351             c = complex_t(r * creall(c), r * cimagl(c));
352         }
353         else if (e1->type->isimaginary())
354         {
355             r = e1->toImaginary();
356             c = e2->toComplex();
357             c = complex_t(-r * cimagl(c), r * creall(c));
358         }
359         else if (e2->type->isreal())
360         {
361             r = e2->toReal();
362             c = e1->toComplex();
363             c = complex_t(r * creall(c), r * cimagl(c));
364         }
365         else if (e2->type->isimaginary())
366         {
367             r = e2->toImaginary();
368             c = e1->toComplex();
369             c = complex_t(-r * cimagl(c), r * creall(c));
370         }
371         else
372             c = e1->toComplex() * e2->toComplex();
373 
374         if (type->isreal())
375             new(&ue) RealExp(loc, creall(c), type);
376         else if (type->isimaginary())
377             new(&ue) RealExp(loc, cimagl(c), type);
378         else if (type->iscomplex())
379             new(&ue) ComplexExp(loc, c, type);
380         else
381             assert(0);
382     }
383     else
384     {
385         new(&ue) IntegerExp(loc, e1->toInteger() * e2->toInteger(), type);
386     }
387     return ue;
388 }
389 
Div(Loc loc,Type * type,Expression * e1,Expression * e2)390 UnionExp Div(Loc loc, Type *type, Expression *e1, Expression *e2)
391 {
392     UnionExp ue;
393 
394     if (type->isfloating())
395     {
396         complex_t c = complex_t(CTFloat::zero);
397         real_t r;
398 
399         //e1->type->print();
400         //e2->type->print();
401         if (e2->type->isreal())
402         {
403             if (e1->type->isreal())
404             {
405                 new(&ue) RealExp(loc, e1->toReal() / e2->toReal(), type);
406                 return ue;
407             }
408             r = e2->toReal();
409             c = e1->toComplex();
410             c = complex_t(creall(c) / r, cimagl(c) / r);
411         }
412         else if (e2->type->isimaginary())
413         {
414             r = e2->toImaginary();
415             c = e1->toComplex();
416             c = complex_t(cimagl(c) / r, -creall(c) / r);
417         }
418         else
419         {
420             c = e1->toComplex() / e2->toComplex();
421         }
422 
423         if (type->isreal())
424             new(&ue) RealExp(loc, creall(c), type);
425         else if (type->isimaginary())
426             new(&ue) RealExp(loc, cimagl(c), type);
427         else if (type->iscomplex())
428             new(&ue) ComplexExp(loc, c, type);
429         else
430             assert(0);
431     }
432     else
433     {
434         sinteger_t n1;
435         sinteger_t n2;
436         sinteger_t n;
437 
438         n1 = e1->toInteger();
439         n2 = e2->toInteger();
440         if (n2 == 0)
441         {
442             e2->error("divide by 0");
443             new(&ue) ErrorExp();
444             return ue;
445         }
446         if (n2 == -1 && !type->isunsigned())
447         {
448             // Check for int.min / -1
449             if ((dinteger_t)n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
450             {
451                 e2->error("integer overflow: int.min / -1");
452                 new(&ue) ErrorExp();
453                 return ue;
454             }
455             else if ((dinteger_t)n1 == 0x8000000000000000LL) // long.min / -1
456             {
457                 e2->error("integer overflow: long.min / -1");
458                 new(&ue) ErrorExp();
459                 return ue;
460             }
461         }
462         if (e1->type->isunsigned() || e2->type->isunsigned())
463             n = ((dinteger_t) n1) / ((dinteger_t) n2);
464         else
465             n = n1 / n2;
466         new(&ue) IntegerExp(loc, n, type);
467     }
468     return ue;
469 }
470 
Mod(Loc loc,Type * type,Expression * e1,Expression * e2)471 UnionExp Mod(Loc loc, Type *type, Expression *e1, Expression *e2)
472 {
473     UnionExp ue;
474 
475     if (type->isfloating())
476     {
477         complex_t c = complex_t(CTFloat::zero);
478 
479         if (e2->type->isreal())
480         {
481             real_t r2 = e2->toReal();
482 
483 #ifdef IN_GCC
484             c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
485 #else
486             c = complex_t(::fmodl(e1->toReal(), r2), ::fmodl(e1->toImaginary(), r2));
487 #endif
488         }
489         else if (e2->type->isimaginary())
490         {
491             real_t i2 = e2->toImaginary();
492 
493 #ifdef IN_GCC
494             c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
495 #else
496             c = complex_t(::fmodl(e1->toReal(), i2), ::fmodl(e1->toImaginary(), i2));
497 #endif
498         }
499         else
500             assert(0);
501 
502         if (type->isreal())
503             new(&ue) RealExp(loc, creall(c), type);
504         else if (type->isimaginary())
505             new(&ue) RealExp(loc, cimagl(c), type);
506         else if (type->iscomplex())
507             new(&ue) ComplexExp(loc, c, type);
508         else
509             assert(0);
510     }
511     else
512     {
513         sinteger_t n1;
514         sinteger_t n2;
515         sinteger_t n;
516 
517         n1 = e1->toInteger();
518         n2 = e2->toInteger();
519         if (n2 == 0)
520         {
521             e2->error("divide by 0");
522             new(&ue) ErrorExp();
523             return ue;
524         }
525         if (n2 == -1 && !type->isunsigned())
526         {
527             // Check for int.min % -1
528             if ((dinteger_t)n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
529             {
530                 e2->error("integer overflow: int.min %% -1");
531                 new(&ue) ErrorExp();
532                 return ue;
533             }
534             else if ((dinteger_t)n1 == 0x8000000000000000LL) // long.min % -1
535             {
536                 e2->error("integer overflow: long.min %% -1");
537                 new(&ue) ErrorExp();
538                 return ue;
539             }
540         }
541         if (e1->type->isunsigned() || e2->type->isunsigned())
542             n = ((dinteger_t) n1) % ((dinteger_t) n2);
543         else
544             n = n1 % n2;
545         new(&ue) IntegerExp(loc, n, type);
546     }
547     return ue;
548 }
549 
Pow(Loc loc,Type * type,Expression * e1,Expression * e2)550 UnionExp Pow(Loc loc, Type *type, Expression *e1, Expression *e2)
551 {
552     UnionExp ue;
553 
554     // Handle integer power operations.
555     if (e2->type->isintegral())
556     {
557         dinteger_t n = e2->toInteger();
558         bool neg;
559 
560         if (!e2->type->isunsigned() && (sinteger_t)n < 0)
561         {
562             if (e1->type->isintegral())
563             {
564                 new(&ue) CTFEExp(TOKcantexp);
565                 return ue;
566             }
567 
568             // Don't worry about overflow, from now on n is unsigned.
569             neg = true;
570             n = -n;
571         }
572         else
573             neg = false;
574 
575         UnionExp ur, uv;
576         if (e1->type->iscomplex())
577         {
578             new(&ur) ComplexExp(loc, e1->toComplex(), e1->type);
579             new(&uv) ComplexExp(loc, complex_t(CTFloat::one), e1->type);
580         }
581         else if (e1->type->isfloating())
582         {
583             new(&ur) RealExp(loc, e1->toReal(), e1->type);
584             new(&uv) RealExp(loc, CTFloat::one, e1->type);
585         }
586         else
587         {
588             new(&ur) IntegerExp(loc, e1->toInteger(), e1->type);
589             new(&uv) IntegerExp(loc, 1, e1->type);
590         }
591 
592         Expression* r = ur.exp();
593         Expression* v = uv.exp();
594         while (n != 0)
595         {
596             if (n & 1)
597             {
598                 // v = v * r;
599                 uv = Mul(loc, v->type, v, r);
600             }
601             n >>= 1;
602             // r = r * r
603             ur = Mul(loc, r->type, r, r);
604         }
605 
606         if (neg)
607         {
608             // ue = 1.0 / v
609             UnionExp one;
610             new(&one) RealExp(loc, CTFloat::one, v->type);
611             uv = Div(loc, v->type, one.exp(), v);
612         }
613 
614         if (type->iscomplex())
615             new(&ue) ComplexExp(loc, v->toComplex(), type);
616         else if (type->isintegral())
617             new(&ue) IntegerExp(loc, v->toInteger(), type);
618         else
619             new(&ue) RealExp(loc, v->toReal(), type);
620     }
621     else if (e2->type->isfloating())
622     {
623         // x ^^ y for x < 0 and y not an integer is not defined; so set result as NaN
624         if (e1->toReal() < CTFloat::zero)
625         {
626             new(&ue) RealExp(loc, Target::RealProperties::nan, type);
627         }
628         else
629             new(&ue) CTFEExp(TOKcantexp);
630     }
631     else
632         new(&ue) CTFEExp(TOKcantexp);
633 
634     return ue;
635 }
636 
Shl(Loc loc,Type * type,Expression * e1,Expression * e2)637 UnionExp Shl(Loc loc, Type *type, Expression *e1, Expression *e2)
638 {
639     UnionExp ue;
640     new(&ue) IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
641     return ue;
642 }
643 
Shr(Loc loc,Type * type,Expression * e1,Expression * e2)644 UnionExp Shr(Loc loc, Type *type, Expression *e1, Expression *e2)
645 {
646     UnionExp ue;
647     dinteger_t value = e1->toInteger();
648     dinteger_t dcount = e2->toInteger();
649     assert(dcount <= 0xFFFFFFFF);
650     unsigned count = (unsigned)dcount;
651     switch (e1->type->toBasetype()->ty)
652     {
653         case Tint8:
654                 value = (d_int8)(value) >> count;
655                 break;
656 
657         case Tuns8:
658         case Tchar:
659                 value = (d_uns8)(value) >> count;
660                 break;
661 
662         case Tint16:
663                 value = (d_int16)(value) >> count;
664                 break;
665 
666         case Tuns16:
667         case Twchar:
668                 value = (d_uns16)(value) >> count;
669                 break;
670 
671         case Tint32:
672                 value = (d_int32)(value) >> count;
673                 break;
674 
675         case Tuns32:
676         case Tdchar:
677                 value = (d_uns32)(value) >> count;
678                 break;
679 
680         case Tint64:
681                 value = (d_int64)(value) >> count;
682                 break;
683 
684         case Tuns64:
685                 value = (d_uns64)(value) >> count;
686                 break;
687 
688         case Terror:
689                 new(&ue) ErrorExp();
690                 return ue;
691 
692         default:
693                 assert(0);
694     }
695     new(&ue) IntegerExp(loc, value, type);
696     return ue;
697 }
698 
Ushr(Loc loc,Type * type,Expression * e1,Expression * e2)699 UnionExp Ushr(Loc loc, Type *type, Expression *e1, Expression *e2)
700 {
701     UnionExp ue;
702     dinteger_t value = e1->toInteger();
703     dinteger_t dcount = e2->toInteger();
704     assert(dcount <= 0xFFFFFFFF);
705     unsigned count = (unsigned)dcount;
706     switch (e1->type->toBasetype()->ty)
707     {
708         case Tint8:
709         case Tuns8:
710         case Tchar:
711                 // Possible only with >>>=. >>> always gets promoted to int.
712                 value = (value & 0xFF) >> count;
713                 break;
714 
715         case Tint16:
716         case Tuns16:
717         case Twchar:
718                 // Possible only with >>>=. >>> always gets promoted to int.
719                 value = (value & 0xFFFF) >> count;
720                 break;
721 
722         case Tint32:
723         case Tuns32:
724         case Tdchar:
725                 value = (value & 0xFFFFFFFF) >> count;
726                 break;
727 
728         case Tint64:
729         case Tuns64:
730                 value = (d_uns64)(value) >> count;
731                 break;
732 
733         case Terror:
734                 new(&ue) ErrorExp();
735                 return ue;
736 
737         default:
738                 assert(0);
739     }
740     new(&ue) IntegerExp(loc, value, type);
741     return ue;
742 }
743 
And(Loc loc,Type * type,Expression * e1,Expression * e2)744 UnionExp And(Loc loc, Type *type, Expression *e1, Expression *e2)
745 {
746     UnionExp ue;
747     new(&ue) IntegerExp(loc, e1->toInteger() & e2->toInteger(), type);
748     return ue;
749 }
750 
Or(Loc loc,Type * type,Expression * e1,Expression * e2)751 UnionExp Or(Loc loc, Type *type, Expression *e1, Expression *e2)
752 {
753     UnionExp ue;
754     new(&ue) IntegerExp(loc, e1->toInteger() | e2->toInteger(), type);
755     return ue;
756 }
757 
Xor(Loc loc,Type * type,Expression * e1,Expression * e2)758 UnionExp Xor(Loc loc, Type *type, Expression *e1, Expression *e2)
759 {
760     UnionExp ue;
761     new(&ue) IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type);
762     return ue;
763 }
764 
765 /* Also returns TOKcantexp if cannot be computed.
766  */
Equal(TOK op,Loc loc,Type * type,Expression * e1,Expression * e2)767 UnionExp Equal(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2)
768 {
769     UnionExp ue;
770     int cmp = 0;
771     real_t r1;
772     real_t r2;
773 
774     //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
775 
776     assert(op == TOKequal || op == TOKnotequal);
777 
778     if (e1->op == TOKnull)
779     {
780         if (e2->op == TOKnull)
781             cmp = 1;
782         else if (e2->op == TOKstring)
783         {
784             StringExp *es2 = (StringExp *)e2;
785             cmp = (0 == es2->len);
786         }
787         else if (e2->op == TOKarrayliteral)
788         {
789             ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
790             cmp = !es2->elements || (0 == es2->elements->dim);
791         }
792         else
793         {
794             new(&ue) CTFEExp(TOKcantexp);
795             return ue;
796         }
797     }
798     else if (e2->op == TOKnull)
799     {
800         if (e1->op == TOKstring)
801         {
802             StringExp *es1 = (StringExp *)e1;
803             cmp = (0 == es1->len);
804         }
805         else if (e1->op == TOKarrayliteral)
806         {
807             ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
808             cmp = !es1->elements || (0 == es1->elements->dim);
809         }
810         else
811         {
812             new(&ue) CTFEExp(TOKcantexp);
813             return ue;
814         }
815     }
816     else if (e1->op == TOKstring && e2->op == TOKstring)
817     {
818         StringExp *es1 = (StringExp *)e1;
819         StringExp *es2 = (StringExp *)e2;
820 
821         if (es1->sz != es2->sz)
822         {
823             assert(global.errors);
824             new(&ue) CTFEExp(TOKcantexp);
825             return ue;
826         }
827         if (es1->len == es2->len &&
828             memcmp(es1->string, es2->string, es1->sz * es1->len) == 0)
829             cmp = 1;
830         else
831             cmp = 0;
832     }
833     else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral)
834     {
835         ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
836         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
837 
838         if ((!es1->elements || !es1->elements->dim) &&
839             (!es2->elements || !es2->elements->dim))
840             cmp = 1;            // both arrays are empty
841         else if (!es1->elements || !es2->elements)
842             cmp = 0;
843         else if (es1->elements->dim != es2->elements->dim)
844             cmp = 0;
845         else
846         {
847             for (size_t i = 0; i < es1->elements->dim; i++)
848             {
849                 Expression *ee1 = es1->getElement(i);
850                 Expression *ee2 = es2->getElement(i);
851                 ue = Equal(TOKequal, loc, Type::tint32, ee1, ee2);
852                 if (CTFEExp::isCantExp(ue.exp()))
853                     return ue;
854                 cmp = (int)ue.exp()->toInteger();
855                 if (cmp == 0)
856                     break;
857             }
858         }
859     }
860     else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
861     {
862         // Swap operands and use common code
863         Expression *etmp = e1;
864         e1 = e2;
865         e2 = etmp;
866         goto Lsa;
867     }
868     else if (e1->op == TOKstring && e2->op == TOKarrayliteral)
869     {
870      Lsa:
871         StringExp *es1 = (StringExp *)e1;
872         ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
873         size_t dim1 = es1->len;
874         size_t dim2 = es2->elements ? es2->elements->dim : 0;
875         if (dim1 != dim2)
876             cmp = 0;
877         else
878         {
879             cmp = 1;            // if dim1 winds up being 0
880             for (size_t i = 0; i < dim1; i++)
881             {
882                 uinteger_t c = es1->charAt(i);
883                 Expression *ee2 = es2->getElement(i);
884                 if (ee2->isConst() != 1)
885                 {
886                     new(&ue) CTFEExp(TOKcantexp);
887                     return ue;
888                 }
889                 cmp = (c == ee2->toInteger());
890                 if (cmp == 0)
891                     break;
892             }
893         }
894     }
895     else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
896     {
897         StructLiteralExp *es1 = (StructLiteralExp *)e1;
898         StructLiteralExp *es2 = (StructLiteralExp *)e2;
899 
900         if (es1->sd != es2->sd)
901             cmp = 0;
902         else if ((!es1->elements || !es1->elements->dim) &&
903             (!es2->elements || !es2->elements->dim))
904             cmp = 1;            // both arrays are empty
905         else if (!es1->elements || !es2->elements)
906             cmp = 0;
907         else if (es1->elements->dim != es2->elements->dim)
908             cmp = 0;
909         else
910         {
911             cmp = 1;
912             for (size_t i = 0; i < es1->elements->dim; i++)
913             {
914                 Expression *ee1 = (*es1->elements)[i];
915                 Expression *ee2 = (*es2->elements)[i];
916 
917                 if (ee1 == ee2)
918                     continue;
919                 if (!ee1 || !ee2)
920                 {
921                     cmp = 0;
922                     break;
923                 }
924                 ue = Equal(TOKequal, loc, Type::tint32, ee1, ee2);
925                 if (ue.exp()->op == TOKcantexp)
926                     return ue;
927                 cmp = (int)ue.exp()->toInteger();
928                 if (cmp == 0)
929                     break;
930             }
931         }
932     }
933     else if (e1->isConst() != 1 || e2->isConst() != 1)
934     {
935         new(&ue) CTFEExp(TOKcantexp);
936         return ue;
937     }
938     else if (e1->type->isreal())
939     {
940         r1 = e1->toReal();
941         r2 = e2->toReal();
942         goto L1;
943     }
944     else if (e1->type->isimaginary())
945     {
946         r1 = e1->toImaginary();
947         r2 = e2->toImaginary();
948      L1:
949         if (CTFloat::isNaN(r1) || CTFloat::isNaN(r2)) // if unordered
950         {
951             cmp = 0;
952         }
953         else
954         {
955             cmp = (r1 == r2);
956         }
957     }
958     else if (e1->type->iscomplex())
959     {
960         cmp = e1->toComplex() == e2->toComplex();
961     }
962     else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer)
963     {
964         cmp = (e1->toInteger() == e2->toInteger());
965     }
966     else
967     {
968         new(&ue) CTFEExp(TOKcantexp);
969         return ue;
970     }
971 
972     if (op == TOKnotequal)
973         cmp ^= 1;
974     new(&ue) IntegerExp(loc, cmp, type);
975     return ue;
976 }
977 
Identity(TOK op,Loc loc,Type * type,Expression * e1,Expression * e2)978 UnionExp Identity(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2)
979 {
980     UnionExp ue;
981     int cmp;
982 
983     if (e1->op == TOKnull)
984     {
985         cmp = (e2->op == TOKnull);
986     }
987     else if (e2->op == TOKnull)
988     {
989         cmp = 0;
990     }
991     else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
992     {
993         SymOffExp *es1 = (SymOffExp *)e1;
994         SymOffExp *es2 = (SymOffExp *)e2;
995 
996         cmp = (es1->var == es2->var && es1->offset == es2->offset);
997     }
998     else
999     {
1000        if (e1->type->isreal())
1001        {
1002            cmp = RealEquals(e1->toReal(), e2->toReal());
1003        }
1004        else if (e1->type->isimaginary())
1005        {
1006            cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
1007        }
1008        else if (e1->type->iscomplex())
1009        {
1010            complex_t v1 = e1->toComplex();
1011            complex_t v2 = e2->toComplex();
1012            cmp = RealEquals(creall(v1), creall(v2)) &&
1013                  RealEquals(cimagl(v1), cimagl(v1));
1014         }
1015         else
1016         {
1017            ue = Equal((op == TOKidentity) ? TOKequal : TOKnotequal, loc, type, e1, e2);
1018            return ue;
1019         }
1020     }
1021     if (op == TOKnotidentity)
1022         cmp ^= 1;
1023     new(&ue) IntegerExp(loc, cmp, type);
1024     return ue;
1025 }
1026 
1027 
Cmp(TOK op,Loc loc,Type * type,Expression * e1,Expression * e2)1028 UnionExp Cmp(TOK op, Loc loc, Type *type, Expression *e1, Expression *e2)
1029 {
1030     UnionExp ue;
1031     dinteger_t n;
1032     real_t r1;
1033     real_t r2;
1034 
1035     //printf("Cmp(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1036 
1037     if (e1->op == TOKstring && e2->op == TOKstring)
1038     {
1039         StringExp *es1 = (StringExp *)e1;
1040         StringExp *es2 = (StringExp *)e2;
1041         size_t sz = es1->sz;
1042         assert(sz == es2->sz);
1043 
1044         size_t len = es1->len;
1045         if (es2->len < len)
1046             len = es2->len;
1047 
1048         int rawCmp = memcmp(es1->string, es2->string, sz * len);
1049         if (rawCmp == 0)
1050             rawCmp = (int)(es1->len - es2->len);
1051         n = specificCmp(op, rawCmp);
1052     }
1053     else if (e1->isConst() != 1 || e2->isConst() != 1)
1054     {
1055         new(&ue) CTFEExp(TOKcantexp);
1056         return ue;
1057     }
1058     else if (e1->type->isreal())
1059     {
1060         r1 = e1->toReal();
1061         r2 = e2->toReal();
1062         goto L1;
1063     }
1064     else if (e1->type->isimaginary())
1065     {
1066         r1 = e1->toImaginary();
1067         r2 = e2->toImaginary();
1068      L1:
1069         n = realCmp(op, r1, r2);
1070     }
1071     else if (e1->type->iscomplex())
1072     {
1073         assert(0);
1074     }
1075     else
1076     {
1077         sinteger_t n1;
1078         sinteger_t n2;
1079 
1080         n1 = e1->toInteger();
1081         n2 = e2->toInteger();
1082         if (e1->type->isunsigned() || e2->type->isunsigned())
1083             n = intUnsignedCmp(op, n1, n2);
1084         else
1085             n = intSignedCmp(op, n1, n2);
1086     }
1087     new(&ue) IntegerExp(loc, n, type);
1088     return ue;
1089 }
1090 
1091 /* Also returns TOKcantexp if cannot be computed.
1092  *  to: type to cast to
1093  *  type: type to paint the result
1094  */
1095 
Cast(Loc loc,Type * type,Type * to,Expression * e1)1096 UnionExp Cast(Loc loc, Type *type, Type *to, Expression *e1)
1097 {
1098     UnionExp ue;
1099     Type *tb = to->toBasetype();
1100     Type *typeb = type->toBasetype();
1101 
1102     //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars());
1103     //printf("\te1->type = %s\n", e1->type->toChars());
1104     if (e1->type->equals(type) && type->equals(to))
1105     {
1106         new(&ue) UnionExp(e1);
1107         return ue;
1108     }
1109 
1110     if (e1->op == TOKvector && ((TypeVector *)e1->type)->basetype->equals(type) && type->equals(to))
1111     {
1112         Expression *ex = ((VectorExp *)e1)->e1;
1113         new(&ue) UnionExp(ex);
1114         return ue;
1115     }
1116 
1117     if (e1->type->implicitConvTo(to) >= MATCHconst ||
1118         to->implicitConvTo(e1->type) >= MATCHconst)
1119     {
1120         goto L1;
1121     }
1122 
1123     // Allow covariant converions of delegates
1124     // (Perhaps implicit conversion from pure to impure should be a MATCHconst,
1125     // then we wouldn't need this extra check.)
1126     if (e1->type->toBasetype()->ty == Tdelegate &&
1127         e1->type->implicitConvTo(to) == MATCHconvert)
1128     {
1129         goto L1;
1130     }
1131 
1132     /* Allow casting from one string type to another
1133      */
1134     if (e1->op == TOKstring)
1135     {
1136         if (tb->ty == Tarray && typeb->ty == Tarray &&
1137             tb->nextOf()->size() == typeb->nextOf()->size())
1138         {
1139             goto L1;
1140         }
1141     }
1142 
1143     if (e1->op == TOKarrayliteral && typeb == tb)
1144     {
1145 L1:
1146         Expression *ex = expType(to, e1);
1147         new(&ue) UnionExp(ex);
1148         return ue;
1149     }
1150 
1151     if (e1->isConst() != 1)
1152     {
1153         new(&ue) CTFEExp(TOKcantexp);
1154     }
1155     else if (tb->ty == Tbool)
1156     {
1157         new(&ue) IntegerExp(loc, e1->toInteger() != 0, type);
1158     }
1159     else if (type->isintegral())
1160     {
1161         if (e1->type->isfloating())
1162         {
1163             dinteger_t result;
1164             real_t r = e1->toReal();
1165 
1166             switch (typeb->ty)
1167             {
1168                 case Tint8:
1169                     result = (d_int8)(sinteger_t)r;
1170                     break;
1171                 case Tchar:
1172                 case Tuns8:
1173                     result = (d_uns8)(dinteger_t)r;
1174                     break;
1175                 case Tint16:
1176                     result = (d_int16)(sinteger_t)r;
1177                     break;
1178                 case Twchar:
1179                 case Tuns16:
1180                     result = (d_uns16)(dinteger_t)r;
1181                     break;
1182                 case Tint32:
1183                     result = (d_int32)r;
1184                     break;
1185                 case Tdchar:
1186                 case Tuns32:
1187                     result = (d_uns32)r;
1188                     break;
1189                 case Tint64:
1190                     result = (d_int64)r;
1191                     break;
1192                 case Tuns64:
1193                     result = (d_uns64)r;
1194                     break;
1195                 default:
1196                     assert(0);
1197             }
1198 
1199             new(&ue) IntegerExp(loc, result, type);
1200         }
1201         else if (type->isunsigned())
1202             new(&ue) IntegerExp(loc, e1->toUInteger(), type);
1203         else
1204             new(&ue) IntegerExp(loc, e1->toInteger(), type);
1205     }
1206     else if (tb->isreal())
1207     {
1208         real_t value = e1->toReal();
1209 
1210         new(&ue) RealExp(loc, value, type);
1211     }
1212     else if (tb->isimaginary())
1213     {
1214         real_t value = e1->toImaginary();
1215 
1216         new(&ue) RealExp(loc, value, type);
1217     }
1218     else if (tb->iscomplex())
1219     {
1220         complex_t value = e1->toComplex();
1221 
1222         new(&ue) ComplexExp(loc, value, type);
1223     }
1224     else if (tb->isscalar())
1225     {
1226         new(&ue) IntegerExp(loc, e1->toInteger(), type);
1227     }
1228     else if (tb->ty == Tvoid)
1229     {
1230         new(&ue) CTFEExp(TOKcantexp);
1231     }
1232     else if (tb->ty == Tstruct && e1->op == TOKint64)
1233     {
1234         // Struct = 0;
1235         StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration();
1236         assert(sd);
1237         Expressions *elements = new Expressions;
1238         for (size_t i = 0; i < sd->fields.dim; i++)
1239         {
1240             VarDeclaration *v = sd->fields[i];
1241             UnionExp zero;
1242             new(&zero) IntegerExp(0);
1243             ue = Cast(loc, v->type, v->type, zero.exp());
1244             if (ue.exp()->op == TOKcantexp)
1245                 return ue;
1246             elements->push(ue.exp()->copy());
1247         }
1248         new(&ue) StructLiteralExp(loc, sd, elements);
1249         ue.exp()->type = type;
1250     }
1251     else
1252     {
1253         if (type != Type::terror)
1254         {
1255             // have to change to Internal Compiler Error
1256             // all invalid casts should be handled already in Expression::castTo().
1257             error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
1258         }
1259         new(&ue) ErrorExp();
1260     }
1261     return ue;
1262 }
1263 
1264 
ArrayLength(Type * type,Expression * e1)1265 UnionExp ArrayLength(Type *type, Expression *e1)
1266 {
1267     UnionExp ue;
1268     Loc loc = e1->loc;
1269 
1270     if (e1->op == TOKstring)
1271     {
1272         StringExp *es1 = (StringExp *)e1;
1273 
1274         new(&ue) IntegerExp(loc, es1->len, type);
1275     }
1276     else if (e1->op == TOKarrayliteral)
1277     {
1278         ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1279         size_t dim = ale->elements ? ale->elements->dim : 0;
1280 
1281         new(&ue) IntegerExp(loc, dim, type);
1282     }
1283     else if (e1->op == TOKassocarrayliteral)
1284     {
1285         AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1;
1286         size_t dim = ale->keys->dim;
1287 
1288         new(&ue) IntegerExp(loc, dim, type);
1289     }
1290     else if (e1->type->toBasetype()->ty == Tsarray)
1291     {
1292         Expression *e = ((TypeSArray *)e1->type->toBasetype())->dim;
1293         new(&ue) UnionExp(e);
1294     }
1295     else
1296         new(&ue) CTFEExp(TOKcantexp);
1297     return ue;
1298 }
1299 
1300 /* Also return TOKcantexp if this fails
1301  */
Index(Type * type,Expression * e1,Expression * e2)1302 UnionExp Index(Type *type, Expression *e1, Expression *e2)
1303 {
1304     UnionExp ue;
1305     Loc loc = e1->loc;
1306 
1307     //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1308     assert(e1->type);
1309     if (e1->op == TOKstring && e2->op == TOKint64)
1310     {
1311         StringExp *es1 = (StringExp *)e1;
1312         uinteger_t i = e2->toInteger();
1313 
1314         if (i >= es1->len)
1315         {
1316             e1->error("string index %llu is out of bounds [0 .. %llu]", i, (ulonglong)es1->len);
1317             new(&ue) ErrorExp();
1318         }
1319         else
1320         {
1321             new(&ue) IntegerExp(loc, es1->charAt(i), type);
1322         }
1323     }
1324     else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64)
1325     {
1326         TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype();
1327         uinteger_t length = tsa->dim->toInteger();
1328         uinteger_t i = e2->toInteger();
1329 
1330         if (i >= length)
1331         {
1332             e1->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length);
1333             new(&ue) ErrorExp();
1334         }
1335         else if (e1->op == TOKarrayliteral)
1336         {
1337             ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1338             Expression *e = ale->getElement((size_t)i);
1339             e->type = type;
1340             e->loc = loc;
1341             if (hasSideEffect(e))
1342                 new(&ue) CTFEExp(TOKcantexp);
1343             else
1344                 new(&ue) UnionExp(e);
1345         }
1346         else
1347             new(&ue) CTFEExp(TOKcantexp);
1348     }
1349     else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
1350     {
1351         uinteger_t i = e2->toInteger();
1352 
1353         if (e1->op == TOKarrayliteral)
1354         {
1355             ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1356             if (i >= ale->elements->dim)
1357             {
1358                 e1->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
1359                 new(&ue) ErrorExp();
1360             }
1361             else
1362             {
1363                 Expression *e = ale->getElement((size_t)i);
1364                 e->type = type;
1365                 e->loc = loc;
1366                 if (hasSideEffect(e))
1367                     new(&ue) CTFEExp(TOKcantexp);
1368                 else
1369                     new(&ue) UnionExp(e);
1370             }
1371         }
1372         else
1373             new(&ue) CTFEExp(TOKcantexp);
1374     }
1375     else if (e1->op == TOKassocarrayliteral)
1376     {
1377         AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1;
1378         /* Search the keys backwards, in case there are duplicate keys
1379          */
1380         for (size_t i = ae->keys->dim; i;)
1381         {
1382             i--;
1383             Expression *ekey = (*ae->keys)[i];
1384             ue = Equal(TOKequal, loc, Type::tbool, ekey, e2);
1385             if (CTFEExp::isCantExp(ue.exp()))
1386                 return ue;
1387             if (ue.exp()->isBool(true))
1388             {
1389                 Expression *e = (*ae->values)[i];
1390                 e->type = type;
1391                 e->loc = loc;
1392                 if (hasSideEffect(e))
1393                     new(&ue) CTFEExp(TOKcantexp);
1394                 else
1395                     new(&ue) UnionExp(e);
1396                 return ue;
1397             }
1398         }
1399         new(&ue) CTFEExp(TOKcantexp);
1400     }
1401     else
1402         new(&ue) CTFEExp(TOKcantexp);
1403     return ue;
1404 }
1405 
1406 /* Also return TOKcantexp if this fails
1407  */
Slice(Type * type,Expression * e1,Expression * lwr,Expression * upr)1408 UnionExp Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
1409 {
1410     UnionExp ue;
1411     Loc loc = e1->loc;
1412 
1413     if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64)
1414     {
1415         StringExp *es1 = (StringExp *)e1;
1416         uinteger_t ilwr = lwr->toInteger();
1417         uinteger_t iupr = upr->toInteger();
1418 
1419         if (iupr > es1->len || ilwr > iupr)
1420         {
1421             e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr);
1422             new(&ue) ErrorExp();
1423         }
1424         else
1425         {
1426             size_t len = (size_t)(iupr - ilwr);
1427             unsigned char sz = es1->sz;
1428 
1429             void *s = mem.xmalloc((len + 1) * sz);
1430             memcpy((char *)s, (char *)es1->string + ilwr * sz, len * sz);
1431             memset((char *)s + len * sz, 0, sz);
1432 
1433             new(&ue) StringExp(loc, s, len, es1->postfix);
1434             StringExp *es = (StringExp *)ue.exp();
1435             es->sz = sz;
1436             es->committed = es1->committed;
1437             es->type = type;
1438         }
1439     }
1440     else if (e1->op == TOKarrayliteral &&
1441             lwr->op == TOKint64 && upr->op == TOKint64 &&
1442             !hasSideEffect(e1))
1443     {
1444         ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
1445         uinteger_t ilwr = lwr->toInteger();
1446         uinteger_t iupr = upr->toInteger();
1447 
1448         if (iupr > es1->elements->dim || ilwr > iupr)
1449         {
1450             e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr);
1451             new(&ue) ErrorExp();
1452         }
1453         else
1454         {
1455             Expressions *elements = new Expressions();
1456             elements->setDim((size_t)(iupr - ilwr));
1457             memcpy(elements->tdata(),
1458                    es1->elements->tdata() + ilwr,
1459                    (size_t)(iupr - ilwr) * sizeof((*es1->elements)[0]));
1460             new(&ue) ArrayLiteralExp(e1->loc, type, elements);
1461         }
1462     }
1463     else
1464         new(&ue) CTFEExp(TOKcantexp);
1465     assert(ue.exp()->type);
1466     return ue;
1467 }
1468 
1469 /* Set a slice of char/integer array literal 'existingAE' from a string 'newval'.
1470  * existingAE[firstIndex..firstIndex+newval.length] = newval.
1471  */
sliceAssignArrayLiteralFromString(ArrayLiteralExp * existingAE,StringExp * newval,size_t firstIndex)1472 void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex)
1473 {
1474     size_t newlen =  newval->len;
1475     size_t sz = newval->sz;
1476     void *s = newval->string;
1477     Type *elemType = existingAE->type->nextOf();
1478     for (size_t j = 0; j < newlen; j++)
1479     {
1480         dinteger_t val;
1481         switch (sz)
1482         {
1483             case 1:     val = (( utf8_t *)s)[j];    break;
1484             case 2:     val = ((utf16_t *)s)[j];    break;
1485             case 4:     val = ((utf32_t *)s)[j];    break;
1486             default:    assert(0);                  break;
1487         }
1488         (*existingAE->elements)[j + firstIndex]
1489             = new IntegerExp(newval->loc, val, elemType);
1490     }
1491 }
1492 
1493 /* Set a slice of string 'existingSE' from a char array literal 'newae'.
1494  *   existingSE[firstIndex..firstIndex+newae.length] = newae.
1495  */
sliceAssignStringFromArrayLiteral(StringExp * existingSE,ArrayLiteralExp * newae,size_t firstIndex)1496 void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex)
1497 {
1498     void *s = existingSE->string;
1499     for (size_t j = 0; j < newae->elements->dim; j++)
1500     {
1501         unsigned val = (unsigned)newae->getElement(j)->toInteger();
1502         switch (existingSE->sz)
1503         {
1504             case 1:     (( utf8_t *)s)[j + firstIndex] = ( utf8_t)val;  break;
1505             case 2:     ((utf16_t *)s)[j + firstIndex] = (utf16_t)val;  break;
1506             case 4:     ((utf32_t *)s)[j + firstIndex] = (utf32_t)val;  break;
1507             default:    assert(0);                                      break;
1508         }
1509     }
1510 }
1511 
1512 /* Set a slice of string 'existingSE' from a string 'newstr'.
1513  *   existingSE[firstIndex..firstIndex+newstr.length] = newstr.
1514  */
sliceAssignStringFromString(StringExp * existingSE,StringExp * newstr,size_t firstIndex)1515 void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex)
1516 {
1517     void *s = existingSE->string;
1518     size_t sz = existingSE->sz;
1519     assert(sz == newstr->sz);
1520     memcpy((char *)s + firstIndex * sz, newstr->string, sz * newstr->len);
1521 }
1522 
1523 /* Compare a string slice with another string slice.
1524  * Conceptually equivalent to memcmp( se1[lo1..lo1+len],  se2[lo2..lo2+len])
1525  */
sliceCmpStringWithString(StringExp * se1,StringExp * se2,size_t lo1,size_t lo2,size_t len)1526 int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len)
1527 {
1528     void *s1 = se1->string;
1529     void *s2 = se2->string;
1530     size_t sz = se1->sz;
1531     assert(sz == se2->sz);
1532     return memcmp((char *)s1 + sz * lo1, (char *)s2 + sz * lo2, sz * len);
1533 }
1534 
1535 /* Compare a string slice with an array literal slice
1536  * Conceptually equivalent to memcmp( se1[lo1..lo1+len],  ae2[lo2..lo2+len])
1537  */
sliceCmpStringWithArray(StringExp * se1,ArrayLiteralExp * ae2,size_t lo1,size_t lo2,size_t len)1538 int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len)
1539 {
1540     void *s = se1->string;
1541     size_t sz = se1->sz;
1542 
1543     for (size_t j = 0; j < len; j++)
1544     {
1545         unsigned val2 = (unsigned)ae2->getElement(j + lo2)->toInteger();
1546         unsigned val1;
1547         switch (sz)
1548         {
1549             case 1:     val1 = (( utf8_t *)s)[j + lo1]; break;
1550             case 2:     val1 = ((utf16_t *)s)[j + lo1]; break;
1551             case 4:     val1 = ((utf32_t *)s)[j + lo1]; break;
1552             default:    assert(0);                      break;
1553         }
1554         int c = val1 - val2;
1555         if (c)
1556             return c;
1557     }
1558     return 0;
1559 }
1560 
1561 /* Also return TOKcantexp if this fails
1562  */
Cat(Type * type,Expression * e1,Expression * e2)1563 UnionExp Cat(Type *type, Expression *e1, Expression *e2)
1564 {
1565     UnionExp ue;
1566     Expression *e = CTFEExp::cantexp;
1567     Loc loc = e1->loc;
1568     Type *t;
1569     Type *t1 = e1->type->toBasetype();
1570     Type *t2 = e2->type->toBasetype();
1571 
1572     //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1573     //printf("\tt1 = %s, t2 = %s, type = %s\n", t1->toChars(), t2->toChars(), type->toChars());
1574 
1575     if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
1576     {
1577         e = e2;
1578         t = t1;
1579         goto L2;
1580     }
1581     else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
1582     {
1583         e = e1;
1584         t = t2;
1585      L2:
1586         Type *tn = e->type->toBasetype();
1587         if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1588         {
1589             // Create a StringExp
1590             if (t->nextOf())
1591                 t = t->nextOf()->toBasetype();
1592             unsigned char sz = (unsigned char)t->size();
1593 
1594             dinteger_t v = e->toInteger();
1595 
1596             size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, (dchar_t)v);
1597             void *s = mem.xmalloc((len + 1) * sz);
1598             if (t->ty == tn->ty)
1599                 Port::valcpy(s, v, sz);
1600             else
1601                 utf_encode(sz, s, (dchar_t)v);
1602 
1603             // Add terminating 0
1604             memset((char *)s + len * sz, 0, sz);
1605 
1606             new(&ue) StringExp(loc, s, len);
1607             StringExp *es = (StringExp *)ue.exp();
1608             es->type = type;
1609             es->sz = sz;
1610             es->committed = 1;
1611         }
1612         else
1613         {
1614             // Create an ArrayLiteralExp
1615             Expressions *elements = new Expressions();
1616             elements->push(e);
1617             new(&ue) ArrayLiteralExp(e->loc, type, elements);
1618         }
1619         assert(ue.exp()->type);
1620         return ue;
1621     }
1622     else if (e1->op == TOKnull && e2->op == TOKnull)
1623     {
1624         if (type == e1->type)
1625         {
1626             // Handle null ~= null
1627             if (t1->ty == Tarray && t2 == t1->nextOf())
1628             {
1629                 new(&ue) ArrayLiteralExp(e1->loc, type, e2);
1630                 assert(ue.exp()->type);
1631                 return ue;
1632             }
1633             else
1634             {
1635                 new(&ue) UnionExp(e1);
1636                 assert(ue.exp()->type);
1637                 return ue;
1638             }
1639         }
1640         if (type == e2->type)
1641         {
1642             new(&ue) UnionExp(e2);
1643             assert(ue.exp()->type);
1644             return ue;
1645         }
1646         new(&ue) NullExp(e1->loc, type);
1647         assert(ue.exp()->type);
1648         return ue;
1649     }
1650     else if (e1->op == TOKstring && e2->op == TOKstring)
1651     {
1652         // Concatenate the strings
1653         StringExp *es1 = (StringExp *)e1;
1654         StringExp *es2 = (StringExp *)e2;
1655         size_t len = es1->len + es2->len;
1656         unsigned char sz = es1->sz;
1657 
1658         if (sz != es2->sz)
1659         {
1660             /* Can happen with:
1661              *   auto s = "foo"d ~ "bar"c;
1662              */
1663             assert(global.errors);
1664             new(&ue) CTFEExp(TOKcantexp);
1665             assert(ue.exp()->type);
1666             return ue;
1667         }
1668         void *s = mem.xmalloc((len + 1) * sz);
1669         memcpy((char *)s, es1->string, es1->len * sz);
1670         memcpy((char *)s + es1->len * sz, es2->string, es2->len * sz);
1671 
1672         // Add terminating 0
1673         memset((char *)s + len * sz, 0, sz);
1674 
1675         new(&ue) StringExp(loc, s, len);
1676         StringExp *es = (StringExp *)ue.exp();
1677         es->sz = sz;
1678         es->committed = es1->committed | es2->committed;
1679         es->type = type;
1680         assert(ue.exp()->type);
1681         return ue;
1682     }
1683     else if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
1684         t1->nextOf()->isintegral())
1685     {
1686         // [chars] ~ string --> [chars]
1687         StringExp *es = (StringExp *)e2;
1688         ArrayLiteralExp *ea = (ArrayLiteralExp *)e1;
1689         size_t len = es->len + ea->elements->dim;
1690         Expressions * elems = new Expressions;
1691         elems->setDim(len);
1692         for (size_t i= 0; i < ea->elements->dim; ++i)
1693         {
1694             (*elems)[i] = ea->getElement(i);
1695         }
1696         new(&ue) ArrayLiteralExp(e1->loc, type, elems);
1697         ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
1698         sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim);
1699         assert(ue.exp()->type);
1700         return ue;
1701     }
1702     else if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
1703         t2->nextOf()->isintegral())
1704     {
1705         // string ~ [chars] --> [chars]
1706         StringExp *es = (StringExp *)e1;
1707         ArrayLiteralExp *ea = (ArrayLiteralExp *)e2;
1708         size_t len = es->len + ea->elements->dim;
1709         Expressions * elems = new Expressions;
1710         elems->setDim(len);
1711         for (size_t i= 0; i < ea->elements->dim; ++i)
1712         {
1713             (*elems)[es->len + i] = ea->getElement(i);
1714         }
1715         new(&ue) ArrayLiteralExp(e1->loc, type, elems);
1716         ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
1717         sliceAssignArrayLiteralFromString(dest, es, 0);
1718         assert(ue.exp()->type);
1719         return ue;
1720     }
1721     else if (e1->op == TOKstring && e2->op == TOKint64)
1722     {
1723         // string ~ char --> string
1724         StringExp *es1 = (StringExp *)e1;
1725         StringExp *es;
1726         unsigned char sz = es1->sz;
1727         dinteger_t v = e2->toInteger();
1728 
1729         // Is it a concatentation of homogenous types?
1730         // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
1731         bool homoConcat = (sz == t2->size());
1732         size_t len = es1->len;
1733         len += homoConcat ? 1 : utf_codeLength(sz, (dchar_t)v);
1734 
1735         void *s = mem.xmalloc((len + 1) * sz);
1736         memcpy(s, es1->string, es1->len * sz);
1737         if (homoConcat)
1738             Port::valcpy((char *)s + (sz * es1->len), v, sz);
1739         else
1740             utf_encode(sz, (char *)s + (sz * es1->len), (dchar_t)v);
1741 
1742         // Add terminating 0
1743         memset((char *)s + len * sz, 0, sz);
1744 
1745         new(&ue) StringExp(loc, s, len);
1746         es = (StringExp *)ue.exp();
1747         es->sz = sz;
1748         es->committed = es1->committed;
1749         es->type = type;
1750         assert(ue.exp()->type);
1751         return ue;
1752     }
1753     else if (e1->op == TOKint64 && e2->op == TOKstring)
1754     {
1755         // [w|d]?char ~ string --> string
1756         // We assume that we only ever prepend one char of the same type
1757         // (wchar,dchar) as the string's characters.
1758         StringExp *es2 = (StringExp *)e2;
1759         size_t len = 1 + es2->len;
1760         unsigned char sz = es2->sz;
1761         dinteger_t v = e1->toInteger();
1762 
1763         void *s = mem.xmalloc((len + 1) * sz);
1764         Port::valcpy((char *)s, v, sz);
1765         memcpy((char *)s + sz, es2->string, es2->len * sz);
1766 
1767         // Add terminating 0
1768         memset((char *)s + len * sz, 0, sz);
1769 
1770         new(&ue) StringExp(loc, s, len);
1771         StringExp *es = (StringExp *)ue.exp();
1772         es->sz = sz;
1773         es->committed = es2->committed;
1774         es->type = type;
1775         assert(ue.exp()->type);
1776         return ue;
1777     }
1778     else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
1779         t1->nextOf()->equals(t2->nextOf()))
1780     {
1781         // Concatenate the arrays
1782         Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
1783 
1784         new(&ue) ArrayLiteralExp(e1->loc, NULL, elems);
1785 
1786         e = ue.exp();
1787         if (type->toBasetype()->ty == Tsarray)
1788         {
1789             e->type = t1->nextOf()->sarrayOf(elems->dim);
1790         }
1791         else
1792             e->type = type;
1793         assert(ue.exp()->type);
1794         return ue;
1795     }
1796     else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
1797         t1->nextOf()->equals(t2->nextOf()))
1798     {
1799         e = e1;
1800         goto L3;
1801     }
1802     else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
1803         t1->nextOf()->equals(t2->nextOf()))
1804     {
1805         e = e2;
1806      L3:
1807         // Concatenate the array with null
1808         Expressions *elems = ArrayLiteralExp::copyElements(e);
1809 
1810         new(&ue) ArrayLiteralExp(e->loc, NULL, elems);
1811 
1812         e = ue.exp();
1813         if (type->toBasetype()->ty == Tsarray)
1814         {
1815             e->type = t1->nextOf()->sarrayOf(elems->dim);
1816         }
1817         else
1818             e->type = type;
1819         assert(ue.exp()->type);
1820         return ue;
1821     }
1822     else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
1823         e1->type->toBasetype()->nextOf() &&
1824         e1->type->toBasetype()->nextOf()->equals(e2->type))
1825     {
1826         Expressions *elems = (e1->op == TOKarrayliteral)
1827             ? ArrayLiteralExp::copyElements(e1) : new Expressions();
1828         elems->push(e2);
1829 
1830         new(&ue) ArrayLiteralExp(e1->loc, NULL, elems);
1831 
1832         e = ue.exp();
1833         if (type->toBasetype()->ty == Tsarray)
1834         {
1835             e->type = e2->type->sarrayOf(elems->dim);
1836         }
1837         else
1838             e->type = type;
1839         assert(ue.exp()->type);
1840         return ue;
1841     }
1842     else if (e2->op == TOKarrayliteral &&
1843         e2->type->toBasetype()->nextOf()->equals(e1->type))
1844     {
1845         Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
1846 
1847         new(&ue) ArrayLiteralExp(e2->loc, NULL, elems);
1848 
1849         e = ue.exp();
1850         if (type->toBasetype()->ty == Tsarray)
1851         {
1852             e->type = e1->type->sarrayOf(elems->dim);
1853         }
1854         else
1855             e->type = type;
1856         assert(ue.exp()->type);
1857         return ue;
1858     }
1859     else if (e1->op == TOKnull && e2->op == TOKstring)
1860     {
1861         t = e1->type;
1862         e = e2;
1863         goto L1;
1864     }
1865     else if (e1->op == TOKstring && e2->op == TOKnull)
1866     {
1867         e = e1;
1868         t = e2->type;
1869       L1:
1870         Type *tb = t->toBasetype();
1871         if (tb->ty == Tarray && tb->nextOf()->equivalent(e->type))
1872         {
1873             Expressions *expressions = new Expressions();
1874             expressions->push(e);
1875             new(&ue) ArrayLiteralExp(loc, t, expressions);
1876             e = ue.exp();
1877         }
1878         else
1879         {
1880             new(&ue) UnionExp(e);
1881             e = ue.exp();
1882         }
1883         if (!e->type->equals(type))
1884         {
1885             StringExp *se = (StringExp *)e->copy();
1886             e = se->castTo(NULL, type);
1887             new(&ue) UnionExp(e);
1888             e = ue.exp();
1889         }
1890     }
1891     else
1892         new(&ue) CTFEExp(TOKcantexp);
1893     assert(ue.exp()->type);
1894     return ue;
1895 }
1896 
Ptr(Type * type,Expression * e1)1897 UnionExp Ptr(Type *type, Expression *e1)
1898 {
1899     //printf("Ptr(e1 = %s)\n", e1->toChars());
1900     UnionExp ue;
1901     if (e1->op == TOKadd)
1902     {
1903         AddExp *ae = (AddExp *)e1;
1904         if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
1905         {
1906             AddrExp *ade = (AddrExp *)ae->e1;
1907             if (ade->e1->op == TOKstructliteral)
1908             {
1909                 StructLiteralExp *se = (StructLiteralExp *)ade->e1;
1910                 unsigned offset = (unsigned)ae->e2->toInteger();
1911                 Expression *e = se->getField(type, offset);
1912                 if (e)
1913                 {
1914                     new(&ue) UnionExp(e);
1915                     return ue;
1916                 }
1917             }
1918         }
1919     }
1920     new(&ue) CTFEExp(TOKcantexp);
1921     return ue;
1922 }
1923