Mercurial > projects > ldc
annotate dmd/constfold.c @ 305:2b72433d5c8c trunk
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its
Identifier, which should be useful elsewhere too.
Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author | lindquist |
---|---|
date | Fri, 27 Jun 2008 22:04:35 +0200 |
parents | 3cfcb944304e |
children | aaade6ded589 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <stdlib.h> | |
13 #include <assert.h> | |
14 #include <math.h> | |
15 | |
16 #if __DMC__ | |
17 #include <complex.h> | |
18 #endif | |
19 | |
20 #include "mem.h" | |
21 #include "root.h" | |
22 | |
23 #include "mtype.h" | |
24 #include "expression.h" | |
25 #include "aggregate.h" | |
26 #include "declaration.h" | |
27 | |
28 #ifdef IN_GCC | |
29 #include "d-gcc-real.h" | |
30 | |
31 /* %% fix? */ | |
32 extern "C" bool real_isnan (const real_t *); | |
33 #endif | |
34 | |
35 static real_t zero; // work around DMC bug for now | |
36 | |
37 #define LOG 0 | |
38 | |
39 Expression *expType(Type *type, Expression *e) | |
40 { | |
41 if (type != e->type) | |
42 { | |
43 e = e->copy(); | |
44 e->type = type; | |
45 } | |
46 return e; | |
47 } | |
48 | |
49 /* ================================== isConst() ============================== */ | |
50 | |
51 int Expression::isConst() | |
52 { | |
53 //printf("Expression::isConst(): %s\n", toChars()); | |
54 return 0; | |
55 } | |
56 | |
57 int IntegerExp::isConst() | |
58 { | |
59 return 1; | |
60 } | |
61 | |
62 int RealExp::isConst() | |
63 { | |
64 return 1; | |
65 } | |
66 | |
67 int ComplexExp::isConst() | |
68 { | |
69 return 1; | |
70 } | |
71 | |
72 int SymOffExp::isConst() | |
73 { | |
74 return 2; | |
75 } | |
76 | |
77 /* =============================== constFold() ============================== */ | |
78 | |
79 /* The constFold() functions were redundant with the optimize() ones, | |
80 * and so have been folded in with them. | |
81 */ | |
82 | |
83 /* ========================================================================== */ | |
84 | |
85 Expression *Neg(Type *type, Expression *e1) | |
86 { Expression *e; | |
87 Loc loc = e1->loc; | |
88 | |
89 if (e1->type->isreal()) | |
90 { | |
91 e = new RealExp(loc, -e1->toReal(), type); | |
92 } | |
93 else if (e1->type->isimaginary()) | |
94 { | |
95 e = new RealExp(loc, -e1->toImaginary(), type); | |
96 } | |
97 else if (e1->type->iscomplex()) | |
98 { | |
99 e = new ComplexExp(loc, -e1->toComplex(), type); | |
100 } | |
101 else | |
102 e = new IntegerExp(loc, -e1->toInteger(), type); | |
103 return e; | |
104 } | |
105 | |
106 Expression *Com(Type *type, Expression *e1) | |
107 { Expression *e; | |
108 Loc loc = e1->loc; | |
109 | |
110 e = new IntegerExp(loc, ~e1->toInteger(), type); | |
111 return e; | |
112 } | |
113 | |
114 Expression *Not(Type *type, Expression *e1) | |
115 { Expression *e; | |
116 Loc loc = e1->loc; | |
117 | |
118 e = new IntegerExp(loc, e1->isBool(0), type); | |
119 return e; | |
120 } | |
121 | |
122 Expression *Bool(Type *type, Expression *e1) | |
123 { Expression *e; | |
124 Loc loc = e1->loc; | |
125 | |
126 e = new IntegerExp(loc, e1->isBool(1), type); | |
127 return e; | |
128 } | |
129 | |
130 Expression *Add(Type *type, Expression *e1, Expression *e2) | |
131 { Expression *e; | |
132 Loc loc = e1->loc; | |
133 | |
134 #if LOG | |
135 printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
136 #endif | |
137 if (type->isreal()) | |
138 { | |
139 e = new RealExp(loc, e1->toReal() + e2->toReal(), type); | |
140 } | |
141 else if (type->isimaginary()) | |
142 { | |
143 e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type); | |
144 } | |
145 else if (type->iscomplex()) | |
146 { | |
147 // This rigamarole is necessary so that -0.0 doesn't get | |
148 // converted to +0.0 by doing an extraneous add with +0.0 | |
149 complex_t c1; | |
150 real_t r1; | |
151 real_t i1; | |
152 | |
153 complex_t c2; | |
154 real_t r2; | |
155 real_t i2; | |
156 | |
157 complex_t v; | |
158 int x; | |
159 | |
160 if (e1->type->isreal()) | |
161 { r1 = e1->toReal(); | |
162 x = 0; | |
163 } | |
164 else if (e1->type->isimaginary()) | |
165 { i1 = e1->toImaginary(); | |
166 x = 3; | |
167 } | |
168 else | |
169 { c1 = e1->toComplex(); | |
170 x = 6; | |
171 } | |
172 | |
173 if (e2->type->isreal()) | |
174 { r2 = e2->toReal(); | |
175 } | |
176 else if (e2->type->isimaginary()) | |
177 { i2 = e2->toImaginary(); | |
178 x += 1; | |
179 } | |
180 else | |
181 { c2 = e2->toComplex(); | |
182 x += 2; | |
183 } | |
184 | |
185 switch (x) | |
186 { | |
187 #if __DMC__ | |
188 case 0+0: v = (complex_t) (r1 + r2); break; | |
189 case 0+1: v = r1 + i2 * I; break; | |
190 case 0+2: v = r1 + c2; break; | |
191 case 3+0: v = i1 * I + r2; break; | |
192 case 3+1: v = (complex_t) ((i1 + i2) * I); break; | |
193 case 3+2: v = i1 * I + c2; break; | |
194 case 6+0: v = c1 + r2; break; | |
195 case 6+1: v = c1 + i2 * I; break; | |
196 case 6+2: v = c1 + c2; break; | |
197 #else | |
198 case 0+0: v = complex_t(r1 + r2, 0); break; | |
199 case 0+1: v = complex_t(r1, i2); break; | |
200 case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); break; | |
201 case 3+0: v = complex_t(r2, i1); break; | |
202 case 3+1: v = complex_t(0, i1 + i2); break; | |
203 case 3+2: v = complex_t(creall(c2), i1 + cimagl(c2)); break; | |
204 case 6+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break; | |
205 case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break; | |
206 case 6+2: v = c1 + c2; break; | |
207 #endif | |
208 default: assert(0); | |
209 } | |
210 e = new ComplexExp(loc, v, type); | |
211 } | |
212 else if (e1->op == TOKsymoff) | |
213 { | |
214 SymOffExp *soe = (SymOffExp *)e1; | |
215 e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger()); | |
216 e->type = type; | |
217 } | |
218 else if (e2->op == TOKsymoff) | |
219 { | |
220 SymOffExp *soe = (SymOffExp *)e2; | |
221 e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger()); | |
222 e->type = type; | |
223 } | |
224 else | |
225 e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type); | |
226 return e; | |
227 } | |
228 | |
229 | |
230 Expression *Min(Type *type, Expression *e1, Expression *e2) | |
231 { Expression *e; | |
232 Loc loc = e1->loc; | |
233 | |
234 if (type->isreal()) | |
235 { | |
236 e = new RealExp(loc, e1->toReal() - e2->toReal(), type); | |
237 } | |
238 else if (type->isimaginary()) | |
239 { | |
240 e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type); | |
241 } | |
242 else if (type->iscomplex()) | |
243 { | |
244 // This rigamarole is necessary so that -0.0 doesn't get | |
245 // converted to +0.0 by doing an extraneous add with +0.0 | |
246 complex_t c1; | |
247 real_t r1; | |
248 real_t i1; | |
249 | |
250 complex_t c2; | |
251 real_t r2; | |
252 real_t i2; | |
253 | |
254 complex_t v; | |
255 int x; | |
256 | |
257 if (e1->type->isreal()) | |
258 { r1 = e1->toReal(); | |
259 x = 0; | |
260 } | |
261 else if (e1->type->isimaginary()) | |
262 { i1 = e1->toImaginary(); | |
263 x = 3; | |
264 } | |
265 else | |
266 { c1 = e1->toComplex(); | |
267 x = 6; | |
268 } | |
269 | |
270 if (e2->type->isreal()) | |
271 { r2 = e2->toReal(); | |
272 } | |
273 else if (e2->type->isimaginary()) | |
274 { i2 = e2->toImaginary(); | |
275 x += 1; | |
276 } | |
277 else | |
278 { c2 = e2->toComplex(); | |
279 x += 2; | |
280 } | |
281 | |
282 switch (x) | |
283 { | |
284 #if __DMC__ | |
285 case 0+0: v = (complex_t) (r1 - r2); break; | |
286 case 0+1: v = r1 - i2 * I; break; | |
287 case 0+2: v = r1 - c2; break; | |
288 case 3+0: v = i1 * I - r2; break; | |
289 case 3+1: v = (complex_t) ((i1 - i2) * I); break; | |
290 case 3+2: v = i1 * I - c2; break; | |
291 case 6+0: v = c1 - r2; break; | |
292 case 6+1: v = c1 - i2 * I; break; | |
293 case 6+2: v = c1 - c2; break; | |
294 #else | |
295 case 0+0: v = complex_t(r1 - r2, 0); break; | |
296 case 0+1: v = complex_t(r1, -i2); break; | |
297 case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); break; | |
298 case 3+0: v = complex_t(-r2, i1); break; | |
299 case 3+1: v = complex_t(0, i1 - i2); break; | |
300 case 3+2: v = complex_t(-creall(c2), i1 - cimagl(c2)); break; | |
301 case 6+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break; | |
302 case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break; | |
303 case 6+2: v = c1 - c2; break; | |
304 #endif | |
305 default: assert(0); | |
306 } | |
307 e = new ComplexExp(loc, v, type); | |
308 } | |
309 else if (e1->op == TOKsymoff) | |
310 { | |
311 SymOffExp *soe = (SymOffExp *)e1; | |
312 e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger()); | |
313 e->type = type; | |
314 } | |
315 else | |
316 { | |
317 e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type); | |
318 } | |
319 return e; | |
320 } | |
321 | |
322 Expression *Mul(Type *type, Expression *e1, Expression *e2) | |
323 { Expression *e; | |
324 Loc loc = e1->loc; | |
325 | |
326 if (type->isfloating()) | |
327 { complex_t c; | |
328 #ifdef IN_GCC | |
329 real_t r; | |
330 #else | |
331 d_float80 r; | |
332 #endif | |
333 | |
334 if (e1->type->isreal()) | |
335 { | |
336 #if __DMC__ | |
337 c = e1->toReal() * e2->toComplex(); | |
338 #else | |
339 r = e1->toReal(); | |
340 c = e2->toComplex(); | |
341 c = complex_t(r * creall(c), r * cimagl(c)); | |
342 #endif | |
343 } | |
344 else if (e1->type->isimaginary()) | |
345 { | |
346 #if __DMC__ | |
347 c = e1->toImaginary() * I * e2->toComplex(); | |
348 #else | |
349 r = e1->toImaginary(); | |
350 c = e2->toComplex(); | |
351 c = complex_t(-r * cimagl(c), r * creall(c)); | |
352 #endif | |
353 } | |
354 else if (e2->type->isreal()) | |
355 { | |
356 #if __DMC__ | |
357 c = e2->toReal() * e1->toComplex(); | |
358 #else | |
359 r = e2->toReal(); | |
360 c = e1->toComplex(); | |
361 c = complex_t(r * creall(c), r * cimagl(c)); | |
362 #endif | |
363 } | |
364 else if (e2->type->isimaginary()) | |
365 { | |
366 #if __DMC__ | |
367 c = e1->toComplex() * e2->toImaginary() * I; | |
368 #else | |
369 r = e2->toImaginary(); | |
370 c = e1->toComplex(); | |
371 c = complex_t(-r * cimagl(c), r * creall(c)); | |
372 #endif | |
373 } | |
374 else | |
375 c = e1->toComplex() * e2->toComplex(); | |
376 | |
377 if (type->isreal()) | |
378 e = new RealExp(loc, creall(c), type); | |
379 else if (type->isimaginary()) | |
380 e = new RealExp(loc, cimagl(c), type); | |
381 else if (type->iscomplex()) | |
382 e = new ComplexExp(loc, c, type); | |
383 else | |
384 assert(0); | |
385 } | |
386 else | |
387 { | |
388 e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type); | |
389 } | |
390 return e; | |
391 } | |
392 | |
393 Expression *Div(Type *type, Expression *e1, Expression *e2) | |
394 { Expression *e; | |
395 Loc loc = e1->loc; | |
396 | |
397 if (type->isfloating()) | |
398 { complex_t c; | |
399 #ifdef IN_GCC | |
400 real_t r; | |
401 #else | |
402 d_float80 r; | |
403 #endif | |
404 | |
405 //e1->type->print(); | |
406 //e2->type->print(); | |
407 if (e2->type->isreal()) | |
408 { | |
409 if (e1->type->isreal()) | |
410 { | |
411 e = new RealExp(loc, e1->toReal() / e2->toReal(), type); | |
412 return e; | |
413 } | |
414 #if __DMC__ | |
415 //r = e2->toReal(); | |
416 //c = e1->toComplex(); | |
417 //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r); | |
418 | |
419 c = e1->toComplex() / e2->toReal(); | |
420 #else | |
421 r = e2->toReal(); | |
422 c = e1->toComplex(); | |
423 c = complex_t(creall(c) / r, cimagl(c) / r); | |
424 #endif | |
425 } | |
426 else if (e2->type->isimaginary()) | |
427 { | |
428 #if __DMC__ | |
429 //r = e2->toImaginary(); | |
430 //c = e1->toComplex(); | |
431 //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r); | |
432 | |
433 c = e1->toComplex() / (e2->toImaginary() * I); | |
434 #else | |
435 r = e2->toImaginary(); | |
436 c = e1->toComplex(); | |
437 c = complex_t(cimagl(c) / r, -creall(c) / r); | |
438 #endif | |
439 } | |
440 else | |
441 { | |
442 c = e1->toComplex() / e2->toComplex(); | |
443 } | |
444 | |
445 if (type->isreal()) | |
446 e = new RealExp(loc, creall(c), type); | |
447 else if (type->isimaginary()) | |
448 e = new RealExp(loc, cimagl(c), type); | |
449 else if (type->iscomplex()) | |
450 e = new ComplexExp(loc, c, type); | |
451 else | |
452 assert(0); | |
453 } | |
454 else | |
455 { sinteger_t n1; | |
456 sinteger_t n2; | |
457 sinteger_t n; | |
458 | |
459 n1 = e1->toInteger(); | |
460 n2 = e2->toInteger(); | |
461 if (n2 == 0) | |
462 { e2->error("divide by 0"); | |
463 e2 = new IntegerExp(0, 1, e2->type); | |
464 n2 = 1; | |
465 } | |
466 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
467 n = ((d_uns64) n1) / ((d_uns64) n2); | |
468 else | |
469 n = n1 / n2; | |
470 e = new IntegerExp(loc, n, type); | |
471 } | |
472 return e; | |
473 } | |
474 | |
475 Expression *Mod(Type *type, Expression *e1, Expression *e2) | |
476 { Expression *e; | |
477 Loc loc = e1->loc; | |
478 | |
479 if (type->isfloating()) | |
480 { | |
481 complex_t c; | |
482 | |
483 if (e2->type->isreal()) | |
484 { real_t r2 = e2->toReal(); | |
485 | |
486 #ifdef __DMC__ | |
487 c = fmodl(e1->toReal(), r2) + fmodl(e1->toImaginary(), r2) * I; | |
488 #elif defined(IN_GCC) | |
489 c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2); | |
490 #else | |
491 c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2)); | |
492 #endif | |
493 } | |
494 else if (e2->type->isimaginary()) | |
495 { real_t i2 = e2->toImaginary(); | |
496 | |
497 #ifdef __DMC__ | |
498 c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I; | |
499 #elif defined(IN_GCC) | |
500 c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2); | |
501 #else | |
502 c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2)); | |
503 #endif | |
504 } | |
505 else | |
506 assert(0); | |
507 | |
508 if (type->isreal()) | |
509 e = new RealExp(loc, creall(c), type); | |
510 else if (type->isimaginary()) | |
511 e = new RealExp(loc, cimagl(c), type); | |
512 else if (type->iscomplex()) | |
513 e = new ComplexExp(loc, c, type); | |
514 else | |
515 assert(0); | |
516 } | |
517 else | |
518 { sinteger_t n1; | |
519 sinteger_t n2; | |
520 sinteger_t n; | |
521 | |
522 n1 = e1->toInteger(); | |
523 n2 = e2->toInteger(); | |
524 if (n2 == 0) | |
525 { e2->error("divide by 0"); | |
526 e2 = new IntegerExp(0, 1, e2->type); | |
527 n2 = 1; | |
528 } | |
529 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
530 n = ((d_uns64) n1) % ((d_uns64) n2); | |
531 else | |
532 n = n1 % n2; | |
533 e = new IntegerExp(loc, n, type); | |
534 } | |
535 return e; | |
536 } | |
537 | |
538 Expression *Shl(Type *type, Expression *e1, Expression *e2) | |
539 { Expression *e; | |
540 Loc loc = e1->loc; | |
541 | |
542 e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); | |
543 return e; | |
544 } | |
545 | |
546 Expression *Shr(Type *type, Expression *e1, Expression *e2) | |
547 { Expression *e; | |
548 Loc loc = e1->loc; | |
549 unsigned count; | |
550 integer_t value; | |
551 | |
552 value = e1->toInteger(); | |
553 count = e2->toInteger(); | |
554 switch (e1->type->toBasetype()->ty) | |
555 { | |
556 case Tint8: | |
557 value = (d_int8)(value) >> count; | |
558 break; | |
559 | |
560 case Tuns8: | |
561 value = (d_uns8)(value) >> count; | |
562 break; | |
563 | |
564 case Tint16: | |
565 value = (d_int16)(value) >> count; | |
566 break; | |
567 | |
568 case Tuns16: | |
569 value = (d_uns16)(value) >> count; | |
570 break; | |
571 | |
572 case Tint32: | |
573 value = (d_int32)(value) >> count; | |
574 break; | |
575 | |
576 case Tuns32: | |
577 value = (d_uns32)(value) >> count; | |
578 break; | |
579 | |
580 case Tint64: | |
581 value = (d_int64)(value) >> count; | |
582 break; | |
583 | |
584 case Tuns64: | |
585 value = (d_uns64)(value) >> count; | |
586 break; | |
587 | |
588 default: | |
589 assert(0); | |
590 } | |
591 e = new IntegerExp(loc, value, type); | |
592 return e; | |
593 } | |
594 | |
595 Expression *Ushr(Type *type, Expression *e1, Expression *e2) | |
596 { Expression *e; | |
597 Loc loc = e1->loc; | |
598 unsigned count; | |
599 integer_t value; | |
600 | |
601 value = e1->toInteger(); | |
602 count = e2->toInteger(); | |
603 switch (e1->type->toBasetype()->ty) | |
604 { | |
605 case Tint8: | |
606 case Tuns8: | |
607 assert(0); // no way to trigger this | |
608 value = (value & 0xFF) >> count; | |
609 break; | |
610 | |
611 case Tint16: | |
612 case Tuns16: | |
613 assert(0); // no way to trigger this | |
614 value = (value & 0xFFFF) >> count; | |
615 break; | |
616 | |
617 case Tint32: | |
618 case Tuns32: | |
619 value = (value & 0xFFFFFFFF) >> count; | |
620 break; | |
621 | |
622 case Tint64: | |
623 case Tuns64: | |
624 value = (d_uns64)(value) >> count; | |
625 break; | |
626 | |
627 default: | |
628 assert(0); | |
629 } | |
630 e = new IntegerExp(loc, value, type); | |
631 return e; | |
632 } | |
633 | |
634 Expression *And(Type *type, Expression *e1, Expression *e2) | |
635 { Expression *e; | |
636 Loc loc = e1->loc; | |
637 | |
638 e = new IntegerExp(loc, e1->toInteger() & e2->toInteger(), type); | |
639 return e; | |
640 } | |
641 | |
642 Expression *Or(Type *type, Expression *e1, Expression *e2) | |
643 { Expression *e; | |
644 Loc loc = e1->loc; | |
645 | |
646 e = new IntegerExp(loc, e1->toInteger() | e2->toInteger(), type); | |
647 return e; | |
648 } | |
649 | |
650 Expression *Xor(Type *type, Expression *e1, Expression *e2) | |
651 { Expression *e; | |
652 Loc loc = e1->loc; | |
653 | |
654 e = new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); | |
655 return e; | |
656 } | |
657 | |
658 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
659 */ | |
660 Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
661 { Expression *e; | |
662 Loc loc = e1->loc; | |
663 int cmp; | |
664 real_t r1; | |
665 real_t r2; | |
666 | |
667 //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
668 | |
669 assert(op == TOKequal || op == TOKnotequal); | |
670 | |
19 | 671 if (e1->op == TOKnull) |
672 { | |
673 if (e2->op == TOKnull) | |
674 cmp = 1; | |
675 else if (e2->op == TOKstring) | |
676 { StringExp *es2 = (StringExp *)e2; | |
677 cmp = (0 == es2->len); | |
678 } | |
679 else if (e2->op == TOKarrayliteral) | |
680 { ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
681 cmp = !es2->elements || (0 == es2->elements->dim); | |
682 } | |
683 else | |
684 return EXP_CANT_INTERPRET; | |
685 } | |
686 else if (e2->op == TOKnull) | |
687 { | |
688 if (e1->op == TOKstring) | |
689 { StringExp *es1 = (StringExp *)e1; | |
690 cmp = (0 == es1->len); | |
691 } | |
692 else if (e1->op == TOKarrayliteral) | |
693 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
694 cmp = !es1->elements || (0 == es1->elements->dim); | |
695 } | |
696 else | |
697 return EXP_CANT_INTERPRET; | |
698 } | |
699 else if (e1->op == TOKstring && e2->op == TOKstring) | |
1 | 700 { StringExp *es1 = (StringExp *)e1; |
701 StringExp *es2 = (StringExp *)e2; | |
702 | |
703 assert(es1->sz == es2->sz); | |
704 if (es1->len == es2->len && | |
705 memcmp(es1->string, es2->string, es1->sz * es1->len) == 0) | |
706 cmp = 1; | |
707 else | |
708 cmp = 0; | |
709 } | |
710 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) | |
711 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
712 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
713 | |
714 if ((!es1->elements || !es1->elements->dim) && | |
715 (!es2->elements || !es2->elements->dim)) | |
716 cmp = 1; // both arrays are empty | |
717 else if (!es1->elements || !es2->elements) | |
718 cmp = 0; | |
719 else if (es1->elements->dim != es2->elements->dim) | |
720 cmp = 0; | |
721 else | |
722 { | |
723 for (size_t i = 0; i < es1->elements->dim; i++) | |
724 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
725 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
726 | |
727 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
728 if (v == EXP_CANT_INTERPRET) | |
729 return EXP_CANT_INTERPRET; | |
730 cmp = v->toInteger(); | |
731 if (cmp == 0) | |
732 break; | |
733 } | |
734 } | |
735 } | |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
736 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
737 { // Swap operands and use common code |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
738 Expression *e = e1; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
739 e1 = e2; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
740 e2 = e; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
741 goto Lsa; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
742 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
743 else if (e1->op == TOKstring && e2->op == TOKarrayliteral) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
744 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
745 Lsa: |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
746 StringExp *es1 = (StringExp *)e1; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
747 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
748 size_t dim1 = es1->len; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
749 size_t dim2 = es2->elements ? es2->elements->dim : 0; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
750 if (dim1 != dim2) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
751 cmp = 0; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
752 else |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
753 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
754 for (size_t i = 0; i < dim1; i++) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
755 { |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
756 uinteger_t c = es1->charAt(i); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
757 Expression *ee2 = (Expression *)es2->elements->data[i]; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
758 if (ee2->isConst() != 1) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
759 return EXP_CANT_INTERPRET; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
760 cmp = (c == ee2->toInteger()); |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
761 if (cmp == 0) |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
762 break; |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
763 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
764 } |
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
765 } |
1 | 766 else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral) |
767 { StructLiteralExp *es1 = (StructLiteralExp *)e1; | |
768 StructLiteralExp *es2 = (StructLiteralExp *)e2; | |
769 | |
770 if (es1->sd != es2->sd) | |
771 cmp = 0; | |
772 else if ((!es1->elements || !es1->elements->dim) && | |
773 (!es2->elements || !es2->elements->dim)) | |
774 cmp = 1; // both arrays are empty | |
775 else if (!es1->elements || !es2->elements) | |
776 cmp = 0; | |
777 else if (es1->elements->dim != es2->elements->dim) | |
778 cmp = 0; | |
779 else | |
780 { | |
781 cmp = 1; | |
782 for (size_t i = 0; i < es1->elements->dim; i++) | |
783 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
784 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
785 | |
786 if (ee1 == ee2) | |
787 continue; | |
788 if (!ee1 || !ee2) | |
789 { cmp = 0; | |
790 break; | |
791 } | |
792 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
793 if (v == EXP_CANT_INTERPRET) | |
794 return EXP_CANT_INTERPRET; | |
795 cmp = v->toInteger(); | |
796 if (cmp == 0) | |
797 break; | |
798 } | |
799 } | |
800 } | |
801 #if 0 // Should handle this | |
802 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) | |
803 { | |
804 } | |
805 #endif | |
806 else if (e1->isConst() != 1 || e2->isConst() != 1) | |
807 return EXP_CANT_INTERPRET; | |
808 else if (e1->type->isreal()) | |
809 { | |
810 r1 = e1->toReal(); | |
811 r2 = e2->toReal(); | |
812 goto L1; | |
813 } | |
814 else if (e1->type->isimaginary()) | |
815 { | |
816 r1 = e1->toImaginary(); | |
817 r2 = e2->toImaginary(); | |
818 L1: | |
819 #if __DMC__ | |
820 cmp = (r1 == r2); | |
821 #else | |
822 if (isnan(r1) || isnan(r2)) // if unordered | |
823 { | |
824 cmp = 0; | |
825 } | |
826 else | |
827 { | |
828 cmp = (r1 == r2); | |
829 } | |
830 #endif | |
831 } | |
832 else if (e1->type->iscomplex()) | |
833 { | |
834 cmp = e1->toComplex() == e2->toComplex(); | |
835 } | |
836 else if (e1->type->isintegral()) | |
837 { | |
838 cmp = (e1->toInteger() == e2->toInteger()); | |
839 } | |
840 else | |
841 return EXP_CANT_INTERPRET; | |
842 if (op == TOKnotequal) | |
843 cmp ^= 1; | |
844 e = new IntegerExp(loc, cmp, type); | |
845 return e; | |
846 } | |
847 | |
848 Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
849 { Expression *e; | |
850 Loc loc = e1->loc; | |
851 int cmp; | |
852 | |
19 | 853 if (e1->op == TOKnull && e2->op == TOKnull) |
854 { | |
855 cmp = 1; | |
856 } | |
857 else if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
1 | 858 { |
859 SymOffExp *es1 = (SymOffExp *)e1; | |
860 SymOffExp *es2 = (SymOffExp *)e2; | |
861 | |
862 cmp = (es1->var == es2->var && es1->offset == es2->offset); | |
863 } | |
864 else if (e1->isConst() == 1 && e2->isConst() == 1) | |
865 return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, | |
866 type, e1, e2); | |
867 else | |
868 assert(0); | |
869 if (op == TOKnotidentity) | |
870 cmp ^= 1; | |
871 return new IntegerExp(loc, cmp, type); | |
872 } | |
873 | |
874 | |
875 Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
876 { Expression *e; | |
877 Loc loc = e1->loc; | |
878 integer_t n; | |
879 real_t r1; | |
880 real_t r2; | |
881 | |
882 if (e1->type->isreal()) | |
883 { | |
884 r1 = e1->toReal(); | |
885 r2 = e2->toReal(); | |
886 goto L1; | |
887 } | |
888 else if (e1->type->isimaginary()) | |
889 { | |
890 r1 = e1->toImaginary(); | |
891 r2 = e2->toImaginary(); | |
892 L1: | |
893 #if __DMC__ | |
894 // DMC is the only compiler I know of that handles NAN arguments | |
895 // correctly in comparisons. | |
896 switch (op) | |
897 { | |
898 case TOKlt: n = r1 < r2; break; | |
899 case TOKle: n = r1 <= r2; break; | |
900 case TOKgt: n = r1 > r2; break; | |
901 case TOKge: n = r1 >= r2; break; | |
902 | |
903 case TOKleg: n = r1 <>= r2; break; | |
904 case TOKlg: n = r1 <> r2; break; | |
905 case TOKunord: n = r1 !<>= r2; break; | |
906 case TOKue: n = r1 !<> r2; break; | |
907 case TOKug: n = r1 !<= r2; break; | |
908 case TOKuge: n = r1 !< r2; break; | |
909 case TOKul: n = r1 !>= r2; break; | |
910 case TOKule: n = r1 !> r2; break; | |
911 | |
912 default: | |
913 assert(0); | |
914 } | |
915 #else | |
916 // Don't rely on compiler, handle NAN arguments separately | |
917 #if IN_GCC | |
918 if (real_isnan(&r1) || real_isnan(&r2)) // if unordered | |
919 #else | |
920 if (isnan(r1) || isnan(r2)) // if unordered | |
921 #endif | |
922 { | |
923 switch (op) | |
924 { | |
925 case TOKlt: n = 0; break; | |
926 case TOKle: n = 0; break; | |
927 case TOKgt: n = 0; break; | |
928 case TOKge: n = 0; break; | |
929 | |
930 case TOKleg: n = 0; break; | |
931 case TOKlg: n = 0; break; | |
932 case TOKunord: n = 1; break; | |
933 case TOKue: n = 1; break; | |
934 case TOKug: n = 1; break; | |
935 case TOKuge: n = 1; break; | |
936 case TOKul: n = 1; break; | |
937 case TOKule: n = 1; break; | |
938 | |
939 default: | |
940 assert(0); | |
941 } | |
942 } | |
943 else | |
944 { | |
945 switch (op) | |
946 { | |
947 case TOKlt: n = r1 < r2; break; | |
948 case TOKle: n = r1 <= r2; break; | |
949 case TOKgt: n = r1 > r2; break; | |
950 case TOKge: n = r1 >= r2; break; | |
951 | |
952 case TOKleg: n = 1; break; | |
953 case TOKlg: n = r1 != r2; break; | |
954 case TOKunord: n = 0; break; | |
955 case TOKue: n = r1 == r2; break; | |
956 case TOKug: n = r1 > r2; break; | |
957 case TOKuge: n = r1 >= r2; break; | |
958 case TOKul: n = r1 < r2; break; | |
959 case TOKule: n = r1 <= r2; break; | |
960 | |
961 default: | |
962 assert(0); | |
963 } | |
964 } | |
965 #endif | |
966 } | |
967 else if (e1->type->iscomplex()) | |
968 { | |
969 assert(0); | |
970 } | |
971 else | |
972 { sinteger_t n1; | |
973 sinteger_t n2; | |
974 | |
975 n1 = e1->toInteger(); | |
976 n2 = e2->toInteger(); | |
977 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
978 { | |
979 switch (op) | |
980 { | |
981 case TOKlt: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
982 case TOKle: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
983 case TOKgt: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
984 case TOKge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
985 | |
986 case TOKleg: n = 1; break; | |
987 case TOKlg: n = ((d_uns64) n1) != ((d_uns64) n2); break; | |
988 case TOKunord: n = 0; break; | |
989 case TOKue: n = ((d_uns64) n1) == ((d_uns64) n2); break; | |
990 case TOKug: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
991 case TOKuge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
992 case TOKul: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
993 case TOKule: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
994 | |
995 default: | |
996 assert(0); | |
997 } | |
998 } | |
999 else | |
1000 { | |
1001 switch (op) | |
1002 { | |
1003 case TOKlt: n = n1 < n2; break; | |
1004 case TOKle: n = n1 <= n2; break; | |
1005 case TOKgt: n = n1 > n2; break; | |
1006 case TOKge: n = n1 >= n2; break; | |
1007 | |
1008 case TOKleg: n = 1; break; | |
1009 case TOKlg: n = n1 != n2; break; | |
1010 case TOKunord: n = 0; break; | |
1011 case TOKue: n = n1 == n2; break; | |
1012 case TOKug: n = n1 > n2; break; | |
1013 case TOKuge: n = n1 >= n2; break; | |
1014 case TOKul: n = n1 < n2; break; | |
1015 case TOKule: n = n1 <= n2; break; | |
1016 | |
1017 default: | |
1018 assert(0); | |
1019 } | |
1020 } | |
1021 } | |
1022 e = new IntegerExp(loc, n, type); | |
1023 return e; | |
1024 } | |
1025 | |
1026 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
1027 * to: type to cast to | |
1028 * type: type to paint the result | |
1029 */ | |
1030 | |
1031 Expression *Cast(Type *type, Type *to, Expression *e1) | |
1032 { Expression *e = EXP_CANT_INTERPRET; | |
1033 Loc loc = e1->loc; | |
1034 | |
1035 //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); | |
1036 //printf("e1->type = %s\n", e1->type->toChars()); | |
1037 if (type->equals(e1->type) && to->equals(type)) | |
1038 return e1; | |
1039 | |
1040 if (e1->isConst() != 1) | |
1041 return EXP_CANT_INTERPRET; | |
1042 | |
1043 Type *tb = to->toBasetype(); | |
1044 if (tb->ty == Tbool) | |
1045 e = new IntegerExp(loc, e1->toInteger() != 0, type); | |
1046 else if (type->isintegral()) | |
1047 { | |
1048 if (e1->type->isfloating()) | |
1049 { integer_t result; | |
1050 real_t r = e1->toReal(); | |
1051 | |
1052 switch (type->toBasetype()->ty) | |
1053 { | |
1054 case Tint8: result = (d_int8)r; break; | |
1055 case Tchar: | |
1056 case Tuns8: result = (d_uns8)r; break; | |
1057 case Tint16: result = (d_int16)r; break; | |
1058 case Twchar: | |
1059 case Tuns16: result = (d_uns16)r; break; | |
1060 case Tint32: result = (d_int32)r; break; | |
1061 case Tdchar: | |
1062 case Tuns32: result = (d_uns32)r; break; | |
1063 case Tint64: result = (d_int64)r; break; | |
1064 case Tuns64: result = (d_uns64)r; break; | |
1065 default: | |
1066 assert(0); | |
1067 } | |
1068 | |
1069 e = new IntegerExp(loc, result, type); | |
1070 } | |
1071 else if (type->isunsigned()) | |
1072 e = new IntegerExp(loc, e1->toUInteger(), type); | |
1073 else | |
1074 e = new IntegerExp(loc, e1->toInteger(), type); | |
1075 } | |
1076 else if (tb->isreal()) | |
1077 { real_t value = e1->toReal(); | |
1078 | |
1079 e = new RealExp(loc, value, type); | |
1080 } | |
1081 else if (tb->isimaginary()) | |
1082 { real_t value = e1->toImaginary(); | |
1083 | |
1084 e = new RealExp(loc, value, type); | |
1085 } | |
1086 else if (tb->iscomplex()) | |
1087 { complex_t value = e1->toComplex(); | |
1088 | |
1089 e = new ComplexExp(loc, value, type); | |
1090 } | |
1091 else if (tb->isscalar()) | |
1092 e = new IntegerExp(loc, e1->toInteger(), type); | |
1093 else if (tb->ty == Tvoid) | |
1094 e = EXP_CANT_INTERPRET; | |
1095 else if (tb->ty == Tstruct && e1->op == TOKint64) | |
1096 { // Struct = 0; | |
1097 StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration(); | |
1098 assert(sd); | |
1099 Expressions *elements = new Expressions; | |
1100 for (size_t i = 0; i < sd->fields.dim; i++) | |
1101 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
1102 VarDeclaration *v = s->isVarDeclaration(); | |
1103 assert(v); | |
1104 | |
1105 Expression *exp = new IntegerExp(0); | |
1106 exp = Cast(v->type, v->type, exp); | |
1107 if (exp == EXP_CANT_INTERPRET) | |
1108 return exp; | |
1109 elements->push(exp); | |
1110 } | |
1111 e = new StructLiteralExp(loc, sd, elements); | |
1112 e->type = type; | |
1113 } | |
1114 else | |
1115 { | |
19 | 1116 error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars()); |
1 | 1117 e = new IntegerExp(loc, 0, type); |
1118 } | |
1119 return e; | |
1120 } | |
1121 | |
1122 | |
1123 Expression *ArrayLength(Type *type, Expression *e1) | |
1124 { Expression *e; | |
1125 Loc loc = e1->loc; | |
1126 | |
1127 if (e1->op == TOKstring) | |
1128 { StringExp *es1 = (StringExp *)e1; | |
1129 | |
1130 e = new IntegerExp(loc, es1->len, type); | |
1131 } | |
1132 else if (e1->op == TOKarrayliteral) | |
1133 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1134 size_t dim; | |
1135 | |
1136 dim = ale->elements ? ale->elements->dim : 0; | |
1137 e = new IntegerExp(loc, dim, type); | |
1138 } | |
1139 else if (e1->op == TOKassocarrayliteral) | |
1140 { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1; | |
1141 size_t dim = ale->keys->dim; | |
1142 | |
1143 e = new IntegerExp(loc, dim, type); | |
1144 } | |
1145 else | |
1146 e = EXP_CANT_INTERPRET; | |
1147 return e; | |
1148 } | |
1149 | |
1150 /* Also return EXP_CANT_INTERPRET if this fails | |
1151 */ | |
1152 Expression *Index(Type *type, Expression *e1, Expression *e2) | |
1153 { Expression *e = EXP_CANT_INTERPRET; | |
1154 Loc loc = e1->loc; | |
1155 | |
1156 //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1157 assert(e1->type); | |
1158 if (e1->op == TOKstring && e2->op == TOKint64) | |
1159 { StringExp *es1 = (StringExp *)e1; | |
1160 uinteger_t i = e2->toInteger(); | |
1161 | |
1162 if (i >= es1->len) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1163 e1->error("string index %llu is out of bounds [0 .. %"PRIuSIZE"]", i, es1->len); |
1 | 1164 else |
35
3cfcb944304e
[svn r39] * Updated to DMD 1.022 with the exception of:
lindquist
parents:
19
diff
changeset
|
1165 { unsigned value = es1->charAt(i); |
1 | 1166 e = new IntegerExp(loc, value, type); |
1167 } | |
1168 } | |
1169 else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) | |
1170 { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype(); | |
1171 uinteger_t length = tsa->dim->toInteger(); | |
1172 uinteger_t i = e2->toInteger(); | |
1173 | |
1174 if (i >= length) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1175 { |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1176 e2->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length); |
1 | 1177 } |
1178 else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1179 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1180 e = (Expression *)ale->elements->data[i]; | |
1181 e->type = type; | |
1182 } | |
1183 } | |
1184 else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64) | |
1185 { | |
1186 uinteger_t i = e2->toInteger(); | |
1187 | |
1188 if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1189 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1190 if (i >= ale->elements->dim) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1191 { |
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1192 e2->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); |
1 | 1193 } |
1194 else | |
1195 { e = (Expression *)ale->elements->data[i]; | |
1196 e->type = type; | |
1197 } | |
1198 } | |
1199 } | |
1200 else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2)) | |
1201 { | |
1202 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1; | |
1203 /* Search the keys backwards, in case there are duplicate keys | |
1204 */ | |
1205 for (size_t i = ae->keys->dim; i;) | |
1206 { | |
1207 i--; | |
1208 Expression *ekey = (Expression *)ae->keys->data[i]; | |
1209 Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); | |
1210 if (ex == EXP_CANT_INTERPRET) | |
1211 return ex; | |
1212 if (ex->isBool(TRUE)) | |
1213 { e = (Expression *)ae->values->data[i]; | |
1214 e->type = type; | |
1215 break; | |
1216 } | |
1217 } | |
1218 } | |
1219 return e; | |
1220 } | |
1221 | |
1222 /* Also return EXP_CANT_INTERPRET if this fails | |
1223 */ | |
1224 Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) | |
1225 { Expression *e = EXP_CANT_INTERPRET; | |
1226 Loc loc = e1->loc; | |
1227 | |
1228 #if LOG | |
1229 printf("Slice()\n"); | |
1230 if (lwr) | |
1231 { printf("\te1 = %s\n", e1->toChars()); | |
1232 printf("\tlwr = %s\n", lwr->toChars()); | |
1233 printf("\tupr = %s\n", upr->toChars()); | |
1234 } | |
1235 #endif | |
1236 if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64) | |
1237 { StringExp *es1 = (StringExp *)e1; | |
1238 uinteger_t ilwr = lwr->toInteger(); | |
1239 uinteger_t iupr = upr->toInteger(); | |
1240 | |
1241 if (iupr > es1->len || ilwr > iupr) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1242 e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr); |
1 | 1243 else |
1244 { integer_t value; | |
1245 void *s; | |
1246 size_t len = iupr - ilwr; | |
1247 int sz = es1->sz; | |
1248 StringExp *es; | |
1249 | |
1250 s = mem.malloc((len + 1) * sz); | |
1251 memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz); | |
1252 memset((unsigned char *)s + len * sz, 0, sz); | |
1253 | |
1254 es = new StringExp(loc, s, len, es1->postfix); | |
1255 es->sz = sz; | |
1256 es->committed = 1; | |
1257 es->type = type; | |
1258 e = es; | |
1259 } | |
1260 } | |
1261 else if (e1->op == TOKarrayliteral && | |
1262 lwr->op == TOKint64 && upr->op == TOKint64 && | |
1263 !e1->checkSideEffect(2)) | |
1264 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1265 uinteger_t ilwr = lwr->toInteger(); | |
1266 uinteger_t iupr = upr->toInteger(); | |
1267 | |
1268 if (iupr > es1->elements->dim || ilwr > iupr) | |
305
2b72433d5c8c
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
lindquist
parents:
35
diff
changeset
|
1269 e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr); |
1 | 1270 else |
1271 { | |
1272 Expressions *elements = new Expressions(); | |
1273 elements->setDim(iupr - ilwr); | |
1274 memcpy(elements->data, | |
1275 es1->elements->data + ilwr, | |
1276 (iupr - ilwr) * sizeof(es1->elements->data[0])); | |
1277 e = new ArrayLiteralExp(e1->loc, elements); | |
1278 e->type = type; | |
1279 } | |
1280 } | |
1281 return e; | |
1282 } | |
1283 | |
1284 /* Also return EXP_CANT_INTERPRET if this fails | |
1285 */ | |
1286 Expression *Cat(Type *type, Expression *e1, Expression *e2) | |
1287 { Expression *e = EXP_CANT_INTERPRET; | |
1288 Loc loc = e1->loc; | |
1289 Type *t; | |
1290 | |
1291 //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1292 | |
19 | 1293 if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral)) |
1 | 1294 { e = e2; |
1295 goto L2; | |
1296 } | |
19 | 1297 else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull) |
1 | 1298 { e = e1; |
1299 L2: | |
1300 Type *tn = e->type->toBasetype(); | |
1301 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) | |
1302 { | |
1303 // Create a StringExp | |
1304 void *s; | |
1305 StringExp *es; | |
1306 size_t len = 1; | |
1307 int sz = tn->size(); | |
1308 integer_t v = e->toInteger(); | |
1309 | |
1310 s = mem.malloc((len + 1) * sz); | |
1311 memcpy((unsigned char *)s, &v, sz); | |
1312 | |
1313 // Add terminating 0 | |
1314 memset((unsigned char *)s + len * sz, 0, sz); | |
1315 | |
1316 es = new StringExp(loc, s, len); | |
1317 es->sz = sz; | |
1318 es->committed = 1; | |
1319 e = es; | |
1320 } | |
1321 else | |
1322 { // Create an ArrayLiteralExp | |
1323 Expressions *elements = new Expressions(); | |
1324 elements->push(e); | |
1325 e = new ArrayLiteralExp(e->loc, elements); | |
1326 } | |
1327 e->type = type; | |
1328 return e; | |
1329 } | |
1330 else if (e1->op == TOKstring && e2->op == TOKstring) | |
1331 { | |
1332 // Concatenate the strings | |
1333 void *s; | |
1334 StringExp *es1 = (StringExp *)e1; | |
1335 StringExp *es2 = (StringExp *)e2; | |
1336 StringExp *es; | |
1337 Type *t; | |
1338 size_t len = es1->len + es2->len; | |
1339 int sz = es1->sz; | |
1340 | |
1341 assert(sz == es2->sz); | |
1342 s = mem.malloc((len + 1) * sz); | |
1343 memcpy(s, es1->string, es1->len * sz); | |
1344 memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz); | |
1345 | |
1346 // Add terminating 0 | |
1347 memset((unsigned char *)s + len * sz, 0, sz); | |
1348 | |
1349 es = new StringExp(loc, s, len); | |
1350 es->sz = sz; | |
1351 es->committed = es1->committed | es2->committed; | |
1352 if (es1->committed) | |
1353 t = es1->type; | |
1354 else | |
1355 t = es2->type; | |
1356 es->type = type; | |
1357 e = es; | |
1358 } | |
1359 else if (e1->op == TOKstring && e2->op == TOKint64) | |
1360 { | |
1361 // Concatenate the strings | |
1362 void *s; | |
1363 StringExp *es1 = (StringExp *)e1; | |
1364 StringExp *es; | |
1365 Type *t; | |
1366 size_t len = es1->len + 1; | |
1367 int sz = es1->sz; | |
1368 integer_t v = e2->toInteger(); | |
1369 | |
1370 s = mem.malloc((len + 1) * sz); | |
1371 memcpy(s, es1->string, es1->len * sz); | |
1372 memcpy((unsigned char *)s + es1->len * sz, &v, sz); | |
1373 | |
1374 // Add terminating 0 | |
1375 memset((unsigned char *)s + len * sz, 0, sz); | |
1376 | |
1377 es = new StringExp(loc, s, len); | |
1378 es->sz = sz; | |
1379 es->committed = es1->committed; | |
1380 t = es1->type; | |
1381 es->type = type; | |
1382 e = es; | |
1383 } | |
1384 else if (e1->op == TOKint64 && e2->op == TOKstring) | |
1385 { | |
1386 // Concatenate the strings | |
1387 void *s; | |
1388 StringExp *es2 = (StringExp *)e2; | |
1389 StringExp *es; | |
1390 Type *t; | |
1391 size_t len = 1 + es2->len; | |
1392 int sz = es2->sz; | |
1393 integer_t v = e1->toInteger(); | |
1394 | |
1395 s = mem.malloc((len + 1) * sz); | |
1396 memcpy((unsigned char *)s, &v, sz); | |
1397 memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); | |
1398 | |
1399 // Add terminating 0 | |
1400 memset((unsigned char *)s + len * sz, 0, sz); | |
1401 | |
1402 es = new StringExp(loc, s, len); | |
1403 es->sz = sz; | |
1404 es->committed = es2->committed; | |
1405 t = es2->type; | |
1406 es->type = type; | |
1407 e = es; | |
1408 } | |
1409 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && | |
1410 e1->type->equals(e2->type)) | |
1411 { | |
1412 // Concatenate the arrays | |
1413 ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1414 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1415 | |
1416 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1417 es1->elements->insert(es1->elements->dim, es2->elements); | |
1418 e = es1; | |
1419 | |
1420 if (type->toBasetype()->ty == Tsarray) | |
1421 { | |
1422 e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1423 e->type = e->type->semantic(loc, NULL); | |
1424 } | |
1425 else | |
1426 e->type = type; | |
1427 } | |
1428 else if (e1->op == TOKarrayliteral && | |
19 | 1429 e1->type->toBasetype()->nextOf()->equals(e2->type)) |
1 | 1430 { |
1431 ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1432 | |
1433 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1434 es1->elements->push(e2); | |
1435 e = es1; | |
1436 | |
1437 if (type->toBasetype()->ty == Tsarray) | |
1438 { | |
1439 e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1440 e->type = e->type->semantic(loc, NULL); | |
1441 } | |
1442 else | |
1443 e->type = type; | |
1444 } | |
1445 else if (e2->op == TOKarrayliteral && | |
19 | 1446 e2->type->toBasetype()->nextOf()->equals(e1->type)) |
1 | 1447 { |
1448 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1449 | |
1450 es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy()); | |
1451 es2->elements->shift(e1); | |
1452 e = es2; | |
1453 | |
1454 if (type->toBasetype()->ty == Tsarray) | |
1455 { | |
1456 e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex)); | |
1457 e->type = e->type->semantic(loc, NULL); | |
1458 } | |
1459 else | |
1460 e->type = type; | |
1461 } | |
1462 else if (e1->op == TOKnull && e2->op == TOKstring) | |
1463 { | |
1464 t = e1->type; | |
1465 e = e2; | |
1466 goto L1; | |
1467 } | |
1468 else if (e1->op == TOKstring && e2->op == TOKnull) | |
1469 { e = e1; | |
1470 t = e2->type; | |
1471 L1: | |
1472 Type *tb = t->toBasetype(); | |
19 | 1473 if (tb->ty == Tarray && tb->nextOf()->equals(e->type)) |
1 | 1474 { Expressions *expressions = new Expressions(); |
1475 expressions->push(e); | |
1476 e = new ArrayLiteralExp(loc, expressions); | |
1477 e->type = t; | |
1478 } | |
1479 if (!e->type->equals(type)) | |
1480 { StringExp *se = (StringExp *)e->copy(); | |
1481 e = se->castTo(NULL, type); | |
1482 } | |
1483 } | |
1484 return e; | |
1485 } | |
1486 | |
1487 Expression *Ptr(Type *type, Expression *e1) | |
1488 { | |
1489 //printf("Ptr(e1 = %s)\n", e1->toChars()); | |
1490 if (e1->op == TOKadd) | |
1491 { AddExp *ae = (AddExp *)e1; | |
1492 if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) | |
1493 { AddrExp *ade = (AddrExp *)ae->e1; | |
1494 if (ade->e1->op == TOKstructliteral) | |
1495 { StructLiteralExp *se = (StructLiteralExp *)ade->e1; | |
1496 unsigned offset = ae->e2->toInteger(); | |
1497 Expression *e = se->getField(type, offset); | |
1498 if (!e) | |
1499 e = EXP_CANT_INTERPRET; | |
1500 return e; | |
1501 } | |
1502 } | |
1503 } | |
1504 return EXP_CANT_INTERPRET; | |
1505 } | |
1506 |