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