]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/constfold.c
Merge dmd upstream 6d5b853d3
[thirdparty/gcc.git] / gcc / d / dmd / constfold.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
f3ed896c 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
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
f9ab59ff
IB
11#include "root/dsystem.h" // mem{cpy|set|cmp}()
12
13#ifndef IN_GCC
b4c522fa 14#include <math.h>
f9ab59ff 15#endif
b4c522fa
IB
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
30int RealEquals(real_t x1, real_t x2);
31
32Expression *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
44int 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
72UnionExp 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
96UnionExp 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
105UnionExp 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
114UnionExp 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
123UnionExp 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
233UnionExp 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
338UnionExp 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
390UnionExp 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
9d7d33ac 449 if ((dinteger_t)n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
b4c522fa
IB
450 {
451 e2->error("integer overflow: int.min / -1");
452 new(&ue) ErrorExp();
453 return ue;
454 }
9d7d33ac 455 else if ((dinteger_t)n1 == 0x8000000000000000LL) // long.min / -1
b4c522fa
IB
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
471UnionExp 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
f9ab59ff 483#ifdef IN_GCC
b4c522fa 484 c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
f9ab59ff
IB
485#else
486 c = complex_t(::fmodl(e1->toReal(), r2), ::fmodl(e1->toImaginary(), r2));
487#endif
b4c522fa
IB
488 }
489 else if (e2->type->isimaginary())
490 {
491 real_t i2 = e2->toImaginary();
492
f9ab59ff 493#ifdef IN_GCC
b4c522fa 494 c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
f9ab59ff
IB
495#else
496 c = complex_t(::fmodl(e1->toReal(), i2), ::fmodl(e1->toImaginary(), i2));
497#endif
b4c522fa
IB
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
550UnionExp 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
637UnionExp 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
644UnionExp 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
699UnionExp 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
744UnionExp 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
751UnionExp 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
758UnionExp 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 */
767UnionExp 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
978UnionExp 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
1028UnionExp 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
1096UnionExp 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 {
1145L1:
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
1265UnionExp 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 */
1302UnionExp 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 */
1408UnionExp 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, elements);
1461 ue.exp()->type = type;
1462 }
1463 }
1464 else
1465 new(&ue) CTFEExp(TOKcantexp);
1466 assert(ue.exp()->type);
1467 return ue;
1468}
1469
1470/* Set a slice of char/integer array literal 'existingAE' from a string 'newval'.
1471 * existingAE[firstIndex..firstIndex+newval.length] = newval.
1472 */
1473void sliceAssignArrayLiteralFromString(ArrayLiteralExp *existingAE, StringExp *newval, size_t firstIndex)
1474{
1475 size_t newlen = newval->len;
1476 size_t sz = newval->sz;
1477 void *s = newval->string;
1478 Type *elemType = existingAE->type->nextOf();
1479 for (size_t j = 0; j < newlen; j++)
1480 {
1481 dinteger_t val;
1482 switch (sz)
1483 {
1484 case 1: val = (( utf8_t *)s)[j]; break;
1485 case 2: val = ((utf16_t *)s)[j]; break;
1486 case 4: val = ((utf32_t *)s)[j]; break;
1487 default: assert(0); break;
1488 }
1489 (*existingAE->elements)[j + firstIndex]
1490 = new IntegerExp(newval->loc, val, elemType);
1491 }
1492}
1493
1494/* Set a slice of string 'existingSE' from a char array literal 'newae'.
1495 * existingSE[firstIndex..firstIndex+newae.length] = newae.
1496 */
1497void sliceAssignStringFromArrayLiteral(StringExp *existingSE, ArrayLiteralExp *newae, size_t firstIndex)
1498{
1499 void *s = existingSE->string;
1500 for (size_t j = 0; j < newae->elements->dim; j++)
1501 {
1502 unsigned val = (unsigned)newae->getElement(j)->toInteger();
1503 switch (existingSE->sz)
1504 {
1505 case 1: (( utf8_t *)s)[j + firstIndex] = ( utf8_t)val; break;
1506 case 2: ((utf16_t *)s)[j + firstIndex] = (utf16_t)val; break;
1507 case 4: ((utf32_t *)s)[j + firstIndex] = (utf32_t)val; break;
1508 default: assert(0); break;
1509 }
1510 }
1511}
1512
1513/* Set a slice of string 'existingSE' from a string 'newstr'.
1514 * existingSE[firstIndex..firstIndex+newstr.length] = newstr.
1515 */
1516void sliceAssignStringFromString(StringExp *existingSE, StringExp *newstr, size_t firstIndex)
1517{
1518 void *s = existingSE->string;
1519 size_t sz = existingSE->sz;
1520 assert(sz == newstr->sz);
1521 memcpy((char *)s + firstIndex * sz, newstr->string, sz * newstr->len);
1522}
1523
1524/* Compare a string slice with another string slice.
1525 * Conceptually equivalent to memcmp( se1[lo1..lo1+len], se2[lo2..lo2+len])
1526 */
1527int sliceCmpStringWithString(StringExp *se1, StringExp *se2, size_t lo1, size_t lo2, size_t len)
1528{
1529 void *s1 = se1->string;
1530 void *s2 = se2->string;
1531 size_t sz = se1->sz;
1532 assert(sz == se2->sz);
1533 return memcmp((char *)s1 + sz * lo1, (char *)s2 + sz * lo2, sz * len);
1534}
1535
1536/* Compare a string slice with an array literal slice
1537 * Conceptually equivalent to memcmp( se1[lo1..lo1+len], ae2[lo2..lo2+len])
1538 */
1539int sliceCmpStringWithArray(StringExp *se1, ArrayLiteralExp *ae2, size_t lo1, size_t lo2, size_t len)
1540{
1541 void *s = se1->string;
1542 size_t sz = se1->sz;
1543
1544 for (size_t j = 0; j < len; j++)
1545 {
1546 unsigned val2 = (unsigned)ae2->getElement(j + lo2)->toInteger();
1547 unsigned val1;
1548 switch (sz)
1549 {
1550 case 1: val1 = (( utf8_t *)s)[j + lo1]; break;
1551 case 2: val1 = ((utf16_t *)s)[j + lo1]; break;
1552 case 4: val1 = ((utf32_t *)s)[j + lo1]; break;
1553 default: assert(0); break;
1554 }
1555 int c = val1 - val2;
1556 if (c)
1557 return c;
1558 }
1559 return 0;
1560}
1561
1562/* Also return TOKcantexp if this fails
1563 */
1564UnionExp Cat(Type *type, Expression *e1, Expression *e2)
1565{
1566 UnionExp ue;
1567 Expression *e = CTFEExp::cantexp;
1568 Loc loc = e1->loc;
1569 Type *t;
1570 Type *t1 = e1->type->toBasetype();
1571 Type *t2 = e2->type->toBasetype();
1572
1573 //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1574 //printf("\tt1 = %s, t2 = %s, type = %s\n", t1->toChars(), t2->toChars(), type->toChars());
1575
1576 if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
1577 {
1578 e = e2;
1579 t = t1;
1580 goto L2;
1581 }
1582 else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
1583 {
1584 e = e1;
1585 t = t2;
1586 L2:
1587 Type *tn = e->type->toBasetype();
1588 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1589 {
1590 // Create a StringExp
1591 if (t->nextOf())
1592 t = t->nextOf()->toBasetype();
1593 unsigned char sz = (unsigned char)t->size();
1594
1595 dinteger_t v = e->toInteger();
1596
1597 size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, (dchar_t)v);
1598 void *s = mem.xmalloc((len + 1) * sz);
1599 if (t->ty == tn->ty)
1600 Port::valcpy(s, v, sz);
1601 else
1602 utf_encode(sz, s, (dchar_t)v);
1603
1604 // Add terminating 0
1605 memset((char *)s + len * sz, 0, sz);
1606
1607 new(&ue) StringExp(loc, s, len);
1608 StringExp *es = (StringExp *)ue.exp();
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, elements);
1618 }
1619 ue.exp()->type = type;
1620 assert(ue.exp()->type);
1621 return ue;
1622 }
1623 else if (e1->op == TOKnull && e2->op == TOKnull)
1624 {
1625 if (type == e1->type)
1626 {
1627 // Handle null ~= null
1628 if (t1->ty == Tarray && t2 == t1->nextOf())
1629 {
1630 new(&ue) ArrayLiteralExp(e1->loc, e2);
1631 ue.exp()->type = type;
1632 assert(ue.exp()->type);
1633 return ue;
1634 }
1635 else
1636 {
1637 new(&ue) UnionExp(e1);
1638 assert(ue.exp()->type);
1639 return ue;
1640 }
1641 }
1642 if (type == e2->type)
1643 {
1644 new(&ue) UnionExp(e2);
1645 assert(ue.exp()->type);
1646 return ue;
1647 }
1648 new(&ue) NullExp(e1->loc, type);
1649 assert(ue.exp()->type);
1650 return ue;
1651 }
1652 else if (e1->op == TOKstring && e2->op == TOKstring)
1653 {
1654 // Concatenate the strings
1655 StringExp *es1 = (StringExp *)e1;
1656 StringExp *es2 = (StringExp *)e2;
1657 size_t len = es1->len + es2->len;
1658 unsigned char sz = es1->sz;
1659
1660 if (sz != es2->sz)
1661 {
1662 /* Can happen with:
1663 * auto s = "foo"d ~ "bar"c;
1664 */
1665 assert(global.errors);
1666 new(&ue) CTFEExp(TOKcantexp);
1667 assert(ue.exp()->type);
1668 return ue;
1669 }
1670 void *s = mem.xmalloc((len + 1) * sz);
1671 memcpy((char *)s, es1->string, es1->len * sz);
1672 memcpy((char *)s + es1->len * sz, es2->string, es2->len * sz);
1673
1674 // Add terminating 0
1675 memset((char *)s + len * sz, 0, sz);
1676
1677 new(&ue) StringExp(loc, s, len);
1678 StringExp *es = (StringExp *)ue.exp();
1679 es->sz = sz;
1680 es->committed = es1->committed | es2->committed;
1681 es->type = type;
1682 assert(ue.exp()->type);
1683 return ue;
1684 }
1685 else if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
1686 t1->nextOf()->isintegral())
1687 {
1688 // [chars] ~ string --> [chars]
1689 StringExp *es = (StringExp *)e2;
1690 ArrayLiteralExp *ea = (ArrayLiteralExp *)e1;
1691 size_t len = es->len + ea->elements->dim;
1692 Expressions * elems = new Expressions;
1693 elems->setDim(len);
1694 for (size_t i= 0; i < ea->elements->dim; ++i)
1695 {
1696 (*elems)[i] = ea->getElement(i);
1697 }
1698 new(&ue) ArrayLiteralExp(e1->loc, elems);
1699 ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
1700 dest->type = type;
1701 sliceAssignArrayLiteralFromString(dest, es, ea->elements->dim);
1702 assert(ue.exp()->type);
1703 return ue;
1704 }
1705 else if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
1706 t2->nextOf()->isintegral())
1707 {
1708 // string ~ [chars] --> [chars]
1709 StringExp *es = (StringExp *)e1;
1710 ArrayLiteralExp *ea = (ArrayLiteralExp *)e2;
1711 size_t len = es->len + ea->elements->dim;
1712 Expressions * elems = new Expressions;
1713 elems->setDim(len);
1714 for (size_t i= 0; i < ea->elements->dim; ++i)
1715 {
1716 (*elems)[es->len + i] = ea->getElement(i);
1717 }
1718 new(&ue) ArrayLiteralExp(e1->loc, elems);
1719 ArrayLiteralExp *dest = (ArrayLiteralExp *)ue.exp();
1720 dest->type = type;
1721 sliceAssignArrayLiteralFromString(dest, es, 0);
1722 assert(ue.exp()->type);
1723 return ue;
1724 }
1725 else if (e1->op == TOKstring && e2->op == TOKint64)
1726 {
1727 // string ~ char --> string
1728 StringExp *es1 = (StringExp *)e1;
1729 StringExp *es;
1730 unsigned char sz = es1->sz;
1731 dinteger_t v = e2->toInteger();
1732
1733 // Is it a concatentation of homogenous types?
1734 // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
1735 bool homoConcat = (sz == t2->size());
1736 size_t len = es1->len;
1737 len += homoConcat ? 1 : utf_codeLength(sz, (dchar_t)v);
1738
1739 void *s = mem.xmalloc((len + 1) * sz);
1740 memcpy(s, es1->string, es1->len * sz);
1741 if (homoConcat)
1742 Port::valcpy((char *)s + (sz * es1->len), v, sz);
1743 else
1744 utf_encode(sz, (char *)s + (sz * es1->len), (dchar_t)v);
1745
1746 // Add terminating 0
1747 memset((char *)s + len * sz, 0, sz);
1748
1749 new(&ue) StringExp(loc, s, len);
1750 es = (StringExp *)ue.exp();
1751 es->sz = sz;
1752 es->committed = es1->committed;
1753 es->type = type;
1754 assert(ue.exp()->type);
1755 return ue;
1756 }
1757 else if (e1->op == TOKint64 && e2->op == TOKstring)
1758 {
1759 // Concatenate the strings
1760 StringExp *es2 = (StringExp *)e2;
1761 size_t len = 1 + es2->len;
1762 unsigned char sz = es2->sz;
1763 dinteger_t v = e1->toInteger();
1764
1765 void *s = mem.xmalloc((len + 1) * sz);
1766 memcpy((char *)s, &v, sz);
1767 memcpy((char *)s + sz, es2->string, es2->len * sz);
1768
1769 // Add terminating 0
1770 memset((char *)s + len * sz, 0, sz);
1771
1772 new(&ue) StringExp(loc, s, len);
1773 StringExp *es = (StringExp *)ue.exp();
1774 es->sz = sz;
1775 es->committed = es2->committed;
1776 es->type = type;
1777 assert(ue.exp()->type);
1778 return ue;
1779 }
1780 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
1781 t1->nextOf()->equals(t2->nextOf()))
1782 {
1783 // Concatenate the arrays
1784 Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
1785
1786 new(&ue) ArrayLiteralExp(e1->loc, elems);
1787
1788 e = ue.exp();
1789 if (type->toBasetype()->ty == Tsarray)
1790 {
1791 e->type = t1->nextOf()->sarrayOf(elems->dim);
1792 }
1793 else
1794 e->type = type;
1795 assert(ue.exp()->type);
1796 return ue;
1797 }
1798 else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
1799 t1->nextOf()->equals(t2->nextOf()))
1800 {
1801 e = e1;
1802 goto L3;
1803 }
1804 else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
1805 t1->nextOf()->equals(t2->nextOf()))
1806 {
1807 e = e2;
1808 L3:
1809 // Concatenate the array with null
1810 Expressions *elems = ArrayLiteralExp::copyElements(e);
1811
1812 new(&ue) ArrayLiteralExp(e->loc, elems);
1813
1814 e = ue.exp();
1815 if (type->toBasetype()->ty == Tsarray)
1816 {
1817 e->type = t1->nextOf()->sarrayOf(elems->dim);
1818 }
1819 else
1820 e->type = type;
1821 assert(ue.exp()->type);
1822 return ue;
1823 }
1824 else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
1825 e1->type->toBasetype()->nextOf() &&
1826 e1->type->toBasetype()->nextOf()->equals(e2->type))
1827 {
1828 Expressions *elems = (e1->op == TOKarrayliteral)
1829 ? ArrayLiteralExp::copyElements(e1) : new Expressions();
1830 elems->push(e2);
1831
1832 new(&ue) ArrayLiteralExp(e1->loc, elems);
1833
1834 e = ue.exp();
1835 if (type->toBasetype()->ty == Tsarray)
1836 {
1837 e->type = e2->type->sarrayOf(elems->dim);
1838 }
1839 else
1840 e->type = type;
1841 assert(ue.exp()->type);
1842 return ue;
1843 }
1844 else if (e2->op == TOKarrayliteral &&
1845 e2->type->toBasetype()->nextOf()->equals(e1->type))
1846 {
1847 Expressions *elems = ArrayLiteralExp::copyElements(e1, e2);
1848
1849 new(&ue) ArrayLiteralExp(e2->loc, elems);
1850
1851 e = ue.exp();
1852 if (type->toBasetype()->ty == Tsarray)
1853 {
1854 e->type = e1->type->sarrayOf(elems->dim);
1855 }
1856 else
1857 e->type = type;
1858 assert(ue.exp()->type);
1859 return ue;
1860 }
1861 else if (e1->op == TOKnull && e2->op == TOKstring)
1862 {
1863 t = e1->type;
1864 e = e2;
1865 goto L1;
1866 }
1867 else if (e1->op == TOKstring && e2->op == TOKnull)
1868 {
1869 e = e1;
1870 t = e2->type;
1871 L1:
1872 Type *tb = t->toBasetype();
1873 if (tb->ty == Tarray && tb->nextOf()->equivalent(e->type))
1874 {
1875 Expressions *expressions = new Expressions();
1876 expressions->push(e);
1877 new(&ue) ArrayLiteralExp(loc, expressions);
1878 e = ue.exp();
1879 e->type = t;
1880 }
1881 else
1882 {
1883 new(&ue) UnionExp(e);
1884 e = ue.exp();
1885 }
1886 if (!e->type->equals(type))
1887 {
1888 StringExp *se = (StringExp *)e->copy();
1889 e = se->castTo(NULL, type);
1890 new(&ue) UnionExp(e);
1891 e = ue.exp();
1892 }
1893 }
1894 else
1895 new(&ue) CTFEExp(TOKcantexp);
1896 assert(ue.exp()->type);
1897 return ue;
1898}
1899
1900UnionExp Ptr(Type *type, Expression *e1)
1901{
1902 //printf("Ptr(e1 = %s)\n", e1->toChars());
1903 UnionExp ue;
1904 if (e1->op == TOKadd)
1905 {
1906 AddExp *ae = (AddExp *)e1;
1907 if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
1908 {
1909 AddrExp *ade = (AddrExp *)ae->e1;
1910 if (ade->e1->op == TOKstructliteral)
1911 {
1912 StructLiteralExp *se = (StructLiteralExp *)ade->e1;
1913 unsigned offset = (unsigned)ae->e2->toInteger();
1914 Expression *e = se->getField(type, offset);
1915 if (e)
1916 {
1917 new(&ue) UnionExp(e);
1918 return ue;
1919 }
1920 }
1921 }
1922 }
1923 new(&ue) CTFEExp(TOKcantexp);
1924 return ue;
1925}