Mercurial > projects > ldc
annotate dmd/constfold.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | b30fe7e1dbb9 |
children | e961851fb8be |
rev | line source |
---|---|
336 | 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 | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
20 #include "rmem.h" |
336 | 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); | |
735
eee9efe5b51f
Attempt at getting LLVM to provide a proper target data layout. Should assert now if things are borked.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
734
diff
changeset
|
490 #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) |
734
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
491 // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?! |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
492 // arm also doesn't like fmodl |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
493 c = complex_t(fmod(e1->toReal(), r2), fmod(e1->toImaginary(), r2)); |
336 | 494 #else |
495 c = complex_t(fmodl(e1->toReal(), r2), fmodl(e1->toImaginary(), r2)); | |
496 #endif | |
497 } | |
498 else if (e2->type->isimaginary()) | |
499 { real_t i2 = e2->toImaginary(); | |
500 | |
501 #ifdef __DMC__ | |
502 c = fmodl(e1->toReal(), i2) + fmodl(e1->toImaginary(), i2) * I; | |
503 #elif defined(IN_GCC) | |
504 c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2); | |
735
eee9efe5b51f
Attempt at getting LLVM to provide a proper target data layout. Should assert now if things are borked.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
734
diff
changeset
|
505 #elif (defined(__FreeBSD__) && __FreeBSD_version < 800000) || defined(__arm__) || defined(__thumb__) |
637
29dc68c949b0
Applied the FreeBSD patch from Ralith, closes ticket #95 , slightly changed but basically the same. Thanx Ralith :)
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
506 // freebsd is kinda messed up. the STABLE branch doesn't support C99's fmodl !?! |
734
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
507 // arm also doesn't like fmodl |
6dcab994ddc3
Fold in mandel's patch for ARM from #106
Christian Kamm <kamm incasoftware de>
parents:
717
diff
changeset
|
508 c = complex_t(fmod(e1->toReal(), i2), fmod(e1->toImaginary(), i2)); |
336 | 509 #else |
510 c = complex_t(fmodl(e1->toReal(), i2), fmodl(e1->toImaginary(), i2)); | |
511 #endif | |
512 } | |
513 else | |
514 assert(0); | |
515 | |
516 if (type->isreal()) | |
517 e = new RealExp(loc, creall(c), type); | |
518 else if (type->isimaginary()) | |
519 e = new RealExp(loc, cimagl(c), type); | |
520 else if (type->iscomplex()) | |
521 e = new ComplexExp(loc, c, type); | |
522 else | |
523 assert(0); | |
524 } | |
525 else | |
526 { sinteger_t n1; | |
527 sinteger_t n2; | |
528 sinteger_t n; | |
529 | |
530 n1 = e1->toInteger(); | |
531 n2 = e2->toInteger(); | |
532 if (n2 == 0) | |
533 { e2->error("divide by 0"); | |
534 e2 = new IntegerExp(0, 1, e2->type); | |
535 n2 = 1; | |
536 } | |
537 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
538 n = ((d_uns64) n1) % ((d_uns64) n2); | |
539 else | |
540 n = n1 % n2; | |
541 e = new IntegerExp(loc, n, type); | |
542 } | |
543 return e; | |
544 } | |
545 | |
546 Expression *Shl(Type *type, Expression *e1, Expression *e2) | |
547 { Expression *e; | |
548 Loc loc = e1->loc; | |
549 | |
550 e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type); | |
551 return e; | |
552 } | |
553 | |
554 Expression *Shr(Type *type, Expression *e1, Expression *e2) | |
555 { Expression *e; | |
556 Loc loc = e1->loc; | |
557 unsigned count; | |
558 integer_t value; | |
559 | |
560 value = e1->toInteger(); | |
561 count = e2->toInteger(); | |
562 switch (e1->type->toBasetype()->ty) | |
563 { | |
564 case Tint8: | |
565 value = (d_int8)(value) >> count; | |
566 break; | |
567 | |
568 case Tuns8: | |
569 value = (d_uns8)(value) >> count; | |
570 break; | |
571 | |
572 case Tint16: | |
573 value = (d_int16)(value) >> count; | |
574 break; | |
575 | |
576 case Tuns16: | |
577 value = (d_uns16)(value) >> count; | |
578 break; | |
579 | |
580 case Tint32: | |
581 value = (d_int32)(value) >> count; | |
582 break; | |
583 | |
584 case Tuns32: | |
585 value = (d_uns32)(value) >> count; | |
586 break; | |
587 | |
588 case Tint64: | |
589 value = (d_int64)(value) >> count; | |
590 break; | |
591 | |
592 case Tuns64: | |
593 value = (d_uns64)(value) >> count; | |
594 break; | |
595 | |
596 default: | |
597 assert(0); | |
598 } | |
599 e = new IntegerExp(loc, value, type); | |
600 return e; | |
601 } | |
602 | |
603 Expression *Ushr(Type *type, Expression *e1, Expression *e2) | |
604 { Expression *e; | |
605 Loc loc = e1->loc; | |
606 unsigned count; | |
607 integer_t value; | |
608 | |
609 value = e1->toInteger(); | |
610 count = e2->toInteger(); | |
611 switch (e1->type->toBasetype()->ty) | |
612 { | |
613 case Tint8: | |
614 case Tuns8: | |
615 assert(0); // no way to trigger this | |
616 value = (value & 0xFF) >> count; | |
617 break; | |
618 | |
619 case Tint16: | |
620 case Tuns16: | |
621 assert(0); // no way to trigger this | |
622 value = (value & 0xFFFF) >> count; | |
623 break; | |
624 | |
625 case Tint32: | |
626 case Tuns32: | |
627 value = (value & 0xFFFFFFFF) >> count; | |
628 break; | |
629 | |
630 case Tint64: | |
631 case Tuns64: | |
632 value = (d_uns64)(value) >> count; | |
633 break; | |
634 | |
635 default: | |
636 assert(0); | |
637 } | |
638 e = new IntegerExp(loc, value, type); | |
639 return e; | |
640 } | |
641 | |
642 Expression *And(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 *Or(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 Expression *Xor(Type *type, Expression *e1, Expression *e2) | |
659 { Expression *e; | |
660 Loc loc = e1->loc; | |
661 | |
662 e = new IntegerExp(loc, e1->toInteger() ^ e2->toInteger(), type); | |
663 return e; | |
664 } | |
665 | |
666 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
667 */ | |
668 Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
669 { Expression *e; | |
670 Loc loc = e1->loc; | |
671 int cmp; | |
672 real_t r1; | |
673 real_t r2; | |
674 | |
675 //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
676 | |
677 assert(op == TOKequal || op == TOKnotequal); | |
678 | |
679 if (e1->op == TOKnull) | |
680 { | |
681 if (e2->op == TOKnull) | |
682 cmp = 1; | |
683 else if (e2->op == TOKstring) | |
684 { StringExp *es2 = (StringExp *)e2; | |
685 cmp = (0 == es2->len); | |
686 } | |
687 else if (e2->op == TOKarrayliteral) | |
688 { ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
689 cmp = !es2->elements || (0 == es2->elements->dim); | |
690 } | |
691 else | |
692 return EXP_CANT_INTERPRET; | |
693 } | |
694 else if (e2->op == TOKnull) | |
695 { | |
696 if (e1->op == TOKstring) | |
697 { StringExp *es1 = (StringExp *)e1; | |
698 cmp = (0 == es1->len); | |
699 } | |
700 else if (e1->op == TOKarrayliteral) | |
701 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
702 cmp = !es1->elements || (0 == es1->elements->dim); | |
703 } | |
704 else | |
705 return EXP_CANT_INTERPRET; | |
706 } | |
707 else if (e1->op == TOKstring && e2->op == TOKstring) | |
708 { StringExp *es1 = (StringExp *)e1; | |
709 StringExp *es2 = (StringExp *)e2; | |
710 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
711 if (es1->sz != es2->sz) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
712 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
713 assert(global.errors); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
714 return EXP_CANT_INTERPRET; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
715 } |
336 | 716 if (es1->len == es2->len && |
717 memcmp(es1->string, es2->string, es1->sz * es1->len) == 0) | |
718 cmp = 1; | |
719 else | |
720 cmp = 0; | |
721 } | |
722 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral) | |
723 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
724 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
725 | |
726 if ((!es1->elements || !es1->elements->dim) && | |
727 (!es2->elements || !es2->elements->dim)) | |
728 cmp = 1; // both arrays are empty | |
729 else if (!es1->elements || !es2->elements) | |
730 cmp = 0; | |
731 else if (es1->elements->dim != es2->elements->dim) | |
732 cmp = 0; | |
733 else | |
734 { | |
735 for (size_t i = 0; i < es1->elements->dim; i++) | |
736 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
737 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
738 | |
739 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
740 if (v == EXP_CANT_INTERPRET) | |
741 return EXP_CANT_INTERPRET; | |
742 cmp = v->toInteger(); | |
743 if (cmp == 0) | |
744 break; | |
745 } | |
746 } | |
747 } | |
748 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) | |
749 { // Swap operands and use common code | |
750 Expression *e = e1; | |
751 e1 = e2; | |
752 e2 = e; | |
753 goto Lsa; | |
754 } | |
755 else if (e1->op == TOKstring && e2->op == TOKarrayliteral) | |
756 { | |
757 Lsa: | |
758 StringExp *es1 = (StringExp *)e1; | |
759 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
760 size_t dim1 = es1->len; | |
761 size_t dim2 = es2->elements ? es2->elements->dim : 0; | |
762 if (dim1 != dim2) | |
763 cmp = 0; | |
764 else | |
765 { | |
766 for (size_t i = 0; i < dim1; i++) | |
767 { | |
768 uinteger_t c = es1->charAt(i); | |
769 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
770 if (ee2->isConst() != 1) | |
771 return EXP_CANT_INTERPRET; | |
772 cmp = (c == ee2->toInteger()); | |
773 if (cmp == 0) | |
774 break; | |
775 } | |
776 } | |
777 } | |
778 else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral) | |
779 { StructLiteralExp *es1 = (StructLiteralExp *)e1; | |
780 StructLiteralExp *es2 = (StructLiteralExp *)e2; | |
781 | |
782 if (es1->sd != es2->sd) | |
783 cmp = 0; | |
784 else if ((!es1->elements || !es1->elements->dim) && | |
785 (!es2->elements || !es2->elements->dim)) | |
786 cmp = 1; // both arrays are empty | |
787 else if (!es1->elements || !es2->elements) | |
788 cmp = 0; | |
789 else if (es1->elements->dim != es2->elements->dim) | |
790 cmp = 0; | |
791 else | |
792 { | |
793 cmp = 1; | |
794 for (size_t i = 0; i < es1->elements->dim; i++) | |
795 { Expression *ee1 = (Expression *)es1->elements->data[i]; | |
796 Expression *ee2 = (Expression *)es2->elements->data[i]; | |
797 | |
798 if (ee1 == ee2) | |
799 continue; | |
800 if (!ee1 || !ee2) | |
801 { cmp = 0; | |
802 break; | |
803 } | |
804 Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2); | |
805 if (v == EXP_CANT_INTERPRET) | |
806 return EXP_CANT_INTERPRET; | |
807 cmp = v->toInteger(); | |
808 if (cmp == 0) | |
809 break; | |
810 } | |
811 } | |
812 } | |
813 #if 0 // Should handle this | |
814 else if (e1->op == TOKarrayliteral && e2->op == TOKstring) | |
815 { | |
816 } | |
817 #endif | |
818 else if (e1->isConst() != 1 || e2->isConst() != 1) | |
819 return EXP_CANT_INTERPRET; | |
820 else if (e1->type->isreal()) | |
821 { | |
822 r1 = e1->toReal(); | |
823 r2 = e2->toReal(); | |
824 goto L1; | |
825 } | |
826 else if (e1->type->isimaginary()) | |
827 { | |
828 r1 = e1->toImaginary(); | |
829 r2 = e2->toImaginary(); | |
830 L1: | |
831 #if __DMC__ | |
832 cmp = (r1 == r2); | |
833 #else | |
834 if (isnan(r1) || isnan(r2)) // if unordered | |
835 { | |
836 cmp = 0; | |
837 } | |
838 else | |
839 { | |
840 cmp = (r1 == r2); | |
841 } | |
842 #endif | |
843 } | |
844 else if (e1->type->iscomplex()) | |
845 { | |
846 cmp = e1->toComplex() == e2->toComplex(); | |
847 } | |
848 else if (e1->type->isintegral()) | |
849 { | |
850 cmp = (e1->toInteger() == e2->toInteger()); | |
851 } | |
852 else | |
853 return EXP_CANT_INTERPRET; | |
854 if (op == TOKnotequal) | |
855 cmp ^= 1; | |
856 e = new IntegerExp(loc, cmp, type); | |
857 return e; | |
858 } | |
859 | |
860 Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
861 { Expression *e; | |
862 Loc loc = e1->loc; | |
863 int cmp; | |
864 | |
865 if (e1->op == TOKnull && e2->op == TOKnull) | |
866 { | |
867 cmp = 1; | |
868 } | |
869 else if (e1->op == TOKsymoff && e2->op == TOKsymoff) | |
870 { | |
871 SymOffExp *es1 = (SymOffExp *)e1; | |
872 SymOffExp *es2 = (SymOffExp *)e2; | |
873 | |
874 cmp = (es1->var == es2->var && es1->offset == es2->offset); | |
875 } | |
876 else if (e1->isConst() == 1 && e2->isConst() == 1) | |
877 return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, | |
878 type, e1, e2); | |
879 else | |
880 assert(0); | |
881 if (op == TOKnotidentity) | |
882 cmp ^= 1; | |
883 return new IntegerExp(loc, cmp, type); | |
884 } | |
885 | |
886 | |
887 Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2) | |
888 { Expression *e; | |
889 Loc loc = e1->loc; | |
890 integer_t n; | |
891 real_t r1; | |
892 real_t r2; | |
893 | |
894 if (e1->type->isreal()) | |
895 { | |
896 r1 = e1->toReal(); | |
897 r2 = e2->toReal(); | |
898 goto L1; | |
899 } | |
900 else if (e1->type->isimaginary()) | |
901 { | |
902 r1 = e1->toImaginary(); | |
903 r2 = e2->toImaginary(); | |
904 L1: | |
905 #if __DMC__ | |
906 // DMC is the only compiler I know of that handles NAN arguments | |
907 // correctly in comparisons. | |
908 switch (op) | |
909 { | |
910 case TOKlt: n = r1 < r2; break; | |
911 case TOKle: n = r1 <= r2; break; | |
912 case TOKgt: n = r1 > r2; break; | |
913 case TOKge: n = r1 >= r2; break; | |
914 | |
915 case TOKleg: n = r1 <>= r2; break; | |
916 case TOKlg: n = r1 <> r2; break; | |
917 case TOKunord: n = r1 !<>= r2; break; | |
918 case TOKue: n = r1 !<> r2; break; | |
919 case TOKug: n = r1 !<= r2; break; | |
920 case TOKuge: n = r1 !< r2; break; | |
921 case TOKul: n = r1 !>= r2; break; | |
922 case TOKule: n = r1 !> r2; break; | |
923 | |
924 default: | |
925 assert(0); | |
926 } | |
927 #else | |
928 // Don't rely on compiler, handle NAN arguments separately | |
929 #if IN_GCC | |
930 if (real_isnan(&r1) || real_isnan(&r2)) // if unordered | |
931 #else | |
932 if (isnan(r1) || isnan(r2)) // if unordered | |
933 #endif | |
934 { | |
935 switch (op) | |
936 { | |
937 case TOKlt: n = 0; break; | |
938 case TOKle: n = 0; break; | |
939 case TOKgt: n = 0; break; | |
940 case TOKge: n = 0; break; | |
941 | |
942 case TOKleg: n = 0; break; | |
943 case TOKlg: n = 0; break; | |
944 case TOKunord: n = 1; break; | |
945 case TOKue: n = 1; break; | |
946 case TOKug: n = 1; break; | |
947 case TOKuge: n = 1; break; | |
948 case TOKul: n = 1; break; | |
949 case TOKule: n = 1; break; | |
950 | |
951 default: | |
952 assert(0); | |
953 } | |
954 } | |
955 else | |
956 { | |
957 switch (op) | |
958 { | |
959 case TOKlt: n = r1 < r2; break; | |
960 case TOKle: n = r1 <= r2; break; | |
961 case TOKgt: n = r1 > r2; break; | |
962 case TOKge: n = r1 >= r2; break; | |
963 | |
964 case TOKleg: n = 1; break; | |
965 case TOKlg: n = r1 != r2; break; | |
966 case TOKunord: n = 0; break; | |
967 case TOKue: n = r1 == r2; break; | |
968 case TOKug: n = r1 > r2; break; | |
969 case TOKuge: n = r1 >= r2; break; | |
970 case TOKul: n = r1 < r2; break; | |
971 case TOKule: n = r1 <= r2; break; | |
972 | |
973 default: | |
974 assert(0); | |
975 } | |
976 } | |
977 #endif | |
978 } | |
979 else if (e1->type->iscomplex()) | |
980 { | |
981 assert(0); | |
982 } | |
983 else | |
984 { sinteger_t n1; | |
985 sinteger_t n2; | |
986 | |
987 n1 = e1->toInteger(); | |
988 n2 = e2->toInteger(); | |
989 if (e1->type->isunsigned() || e2->type->isunsigned()) | |
990 { | |
991 switch (op) | |
992 { | |
993 case TOKlt: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
994 case TOKle: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
995 case TOKgt: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
996 case TOKge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
997 | |
998 case TOKleg: n = 1; break; | |
999 case TOKlg: n = ((d_uns64) n1) != ((d_uns64) n2); break; | |
1000 case TOKunord: n = 0; break; | |
1001 case TOKue: n = ((d_uns64) n1) == ((d_uns64) n2); break; | |
1002 case TOKug: n = ((d_uns64) n1) > ((d_uns64) n2); break; | |
1003 case TOKuge: n = ((d_uns64) n1) >= ((d_uns64) n2); break; | |
1004 case TOKul: n = ((d_uns64) n1) < ((d_uns64) n2); break; | |
1005 case TOKule: n = ((d_uns64) n1) <= ((d_uns64) n2); break; | |
1006 | |
1007 default: | |
1008 assert(0); | |
1009 } | |
1010 } | |
1011 else | |
1012 { | |
1013 switch (op) | |
1014 { | |
1015 case TOKlt: n = n1 < n2; break; | |
1016 case TOKle: n = n1 <= n2; break; | |
1017 case TOKgt: n = n1 > n2; break; | |
1018 case TOKge: n = n1 >= n2; break; | |
1019 | |
1020 case TOKleg: n = 1; break; | |
1021 case TOKlg: n = n1 != n2; break; | |
1022 case TOKunord: n = 0; break; | |
1023 case TOKue: n = n1 == n2; break; | |
1024 case TOKug: n = n1 > n2; break; | |
1025 case TOKuge: n = n1 >= n2; break; | |
1026 case TOKul: n = n1 < n2; break; | |
1027 case TOKule: n = n1 <= n2; break; | |
1028 | |
1029 default: | |
1030 assert(0); | |
1031 } | |
1032 } | |
1033 } | |
1034 e = new IntegerExp(loc, n, type); | |
1035 return e; | |
1036 } | |
1037 | |
1038 /* Also returns EXP_CANT_INTERPRET if cannot be computed. | |
1039 * to: type to cast to | |
1040 * type: type to paint the result | |
1041 */ | |
1042 | |
1043 Expression *Cast(Type *type, Type *to, Expression *e1) | |
1044 { Expression *e = EXP_CANT_INTERPRET; | |
1045 Loc loc = e1->loc; | |
1046 | |
1047 //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); | |
1048 //printf("e1->type = %s\n", e1->type->toChars()); | |
1049 if (type->equals(e1->type) && to->equals(type)) | |
1050 return e1; | |
1051 | |
1052 if (e1->isConst() != 1) | |
1053 return EXP_CANT_INTERPRET; | |
1054 | |
1055 Type *tb = to->toBasetype(); | |
1056 if (tb->ty == Tbool) | |
1057 e = new IntegerExp(loc, e1->toInteger() != 0, type); | |
1058 else if (type->isintegral()) | |
1059 { | |
1060 if (e1->type->isfloating()) | |
1061 { integer_t result; | |
1062 real_t r = e1->toReal(); | |
1063 | |
1064 switch (type->toBasetype()->ty) | |
1065 { | |
1066 case Tint8: result = (d_int8)r; break; | |
1067 case Tchar: | |
1068 case Tuns8: result = (d_uns8)r; break; | |
1069 case Tint16: result = (d_int16)r; break; | |
1070 case Twchar: | |
1071 case Tuns16: result = (d_uns16)r; break; | |
1072 case Tint32: result = (d_int32)r; break; | |
1073 case Tdchar: | |
1074 case Tuns32: result = (d_uns32)r; break; | |
1075 case Tint64: result = (d_int64)r; break; | |
1076 case Tuns64: result = (d_uns64)r; break; | |
1077 default: | |
1078 assert(0); | |
1079 } | |
1080 | |
1081 e = new IntegerExp(loc, result, type); | |
1082 } | |
1083 else if (type->isunsigned()) | |
1084 e = new IntegerExp(loc, e1->toUInteger(), type); | |
1085 else | |
1086 e = new IntegerExp(loc, e1->toInteger(), type); | |
1087 } | |
1088 else if (tb->isreal()) | |
1089 { real_t value = e1->toReal(); | |
1090 | |
1091 e = new RealExp(loc, value, type); | |
1092 } | |
1093 else if (tb->isimaginary()) | |
1094 { real_t value = e1->toImaginary(); | |
1095 | |
1096 e = new RealExp(loc, value, type); | |
1097 } | |
1098 else if (tb->iscomplex()) | |
1099 { complex_t value = e1->toComplex(); | |
1100 | |
1101 e = new ComplexExp(loc, value, type); | |
1102 } | |
1103 else if (tb->isscalar()) | |
1104 e = new IntegerExp(loc, e1->toInteger(), type); | |
1105 else if (tb->ty == Tvoid) | |
1106 e = EXP_CANT_INTERPRET; | |
1107 else if (tb->ty == Tstruct && e1->op == TOKint64) | |
1108 { // Struct = 0; | |
1109 StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration(); | |
1110 assert(sd); | |
1111 Expressions *elements = new Expressions; | |
1112 for (size_t i = 0; i < sd->fields.dim; i++) | |
1113 { Dsymbol *s = (Dsymbol *)sd->fields.data[i]; | |
1114 VarDeclaration *v = s->isVarDeclaration(); | |
1115 assert(v); | |
1116 | |
1117 Expression *exp = new IntegerExp(0); | |
1118 exp = Cast(v->type, v->type, exp); | |
1119 if (exp == EXP_CANT_INTERPRET) | |
1120 return exp; | |
1121 elements->push(exp); | |
1122 } | |
1123 e = new StructLiteralExp(loc, sd, elements); | |
1124 e->type = type; | |
1125 } | |
1126 else | |
1127 { | |
1128 error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars()); | |
1129 e = new IntegerExp(loc, 0, type); | |
1130 } | |
1131 return e; | |
1132 } | |
1133 | |
1134 | |
1135 Expression *ArrayLength(Type *type, Expression *e1) | |
1136 { Expression *e; | |
1137 Loc loc = e1->loc; | |
1138 | |
1139 if (e1->op == TOKstring) | |
1140 { StringExp *es1 = (StringExp *)e1; | |
1141 | |
1142 e = new IntegerExp(loc, es1->len, type); | |
1143 } | |
1144 else if (e1->op == TOKarrayliteral) | |
1145 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1146 size_t dim; | |
1147 | |
1148 dim = ale->elements ? ale->elements->dim : 0; | |
1149 e = new IntegerExp(loc, dim, type); | |
1150 } | |
1151 else if (e1->op == TOKassocarrayliteral) | |
1152 { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1; | |
1153 size_t dim = ale->keys->dim; | |
1154 | |
1155 e = new IntegerExp(loc, dim, type); | |
1156 } | |
1157 else | |
1158 e = EXP_CANT_INTERPRET; | |
1159 return e; | |
1160 } | |
1161 | |
1162 /* Also return EXP_CANT_INTERPRET if this fails | |
1163 */ | |
1164 Expression *Index(Type *type, Expression *e1, Expression *e2) | |
1165 { Expression *e = EXP_CANT_INTERPRET; | |
1166 Loc loc = e1->loc; | |
1167 | |
1168 //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1169 assert(e1->type); | |
1170 if (e1->op == TOKstring && e2->op == TOKint64) | |
1171 { StringExp *es1 = (StringExp *)e1; | |
1172 uinteger_t i = e2->toInteger(); | |
1173 | |
1174 if (i >= es1->len) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
1175 e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len); |
336 | 1176 else |
1177 { unsigned value = es1->charAt(i); | |
1178 e = new IntegerExp(loc, value, type); | |
1179 } | |
1180 } | |
1181 else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64) | |
1182 { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype(); | |
1183 uinteger_t length = tsa->dim->toInteger(); | |
1184 uinteger_t i = e2->toInteger(); | |
1185 | |
1186 if (i >= length) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
1187 { e2->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length); |
336 | 1188 } |
1189 else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1190 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1191 e = (Expression *)ale->elements->data[i]; | |
1192 e->type = type; | |
1193 } | |
1194 } | |
1195 else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64) | |
1196 { | |
1197 uinteger_t i = e2->toInteger(); | |
1198 | |
1199 if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2)) | |
1200 { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1; | |
1201 if (i >= ale->elements->dim) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
1202 { e2->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim); |
336 | 1203 } |
1204 else | |
1205 { e = (Expression *)ale->elements->data[i]; | |
1206 e->type = type; | |
1207 } | |
1208 } | |
1209 } | |
1210 else if (e1->op == TOKassocarrayliteral && !e1->checkSideEffect(2)) | |
1211 { | |
1212 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1; | |
1213 /* Search the keys backwards, in case there are duplicate keys | |
1214 */ | |
1215 for (size_t i = ae->keys->dim; i;) | |
1216 { | |
1217 i--; | |
1218 Expression *ekey = (Expression *)ae->keys->data[i]; | |
1219 Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2); | |
1220 if (ex == EXP_CANT_INTERPRET) | |
1221 return ex; | |
1222 if (ex->isBool(TRUE)) | |
1223 { e = (Expression *)ae->values->data[i]; | |
1224 e->type = type; | |
1225 break; | |
1226 } | |
1227 } | |
1228 } | |
1229 return e; | |
1230 } | |
1231 | |
1232 /* Also return EXP_CANT_INTERPRET if this fails | |
1233 */ | |
1234 Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr) | |
1235 { Expression *e = EXP_CANT_INTERPRET; | |
1236 Loc loc = e1->loc; | |
1237 | |
1238 #if LOG | |
1239 printf("Slice()\n"); | |
1240 if (lwr) | |
1241 { printf("\te1 = %s\n", e1->toChars()); | |
1242 printf("\tlwr = %s\n", lwr->toChars()); | |
1243 printf("\tupr = %s\n", upr->toChars()); | |
1244 } | |
1245 #endif | |
1246 if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64) | |
1247 { StringExp *es1 = (StringExp *)e1; | |
1248 uinteger_t ilwr = lwr->toInteger(); | |
1249 uinteger_t iupr = upr->toInteger(); | |
1250 | |
1251 if (iupr > es1->len || ilwr > iupr) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
1252 e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr); |
336 | 1253 else |
1254 { integer_t value; | |
1255 void *s; | |
1256 size_t len = iupr - ilwr; | |
1257 int sz = es1->sz; | |
1258 StringExp *es; | |
1259 | |
1260 s = mem.malloc((len + 1) * sz); | |
1261 memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz); | |
1262 memset((unsigned char *)s + len * sz, 0, sz); | |
1263 | |
1264 es = new StringExp(loc, s, len, es1->postfix); | |
1265 es->sz = sz; | |
1266 es->committed = 1; | |
1267 es->type = type; | |
1268 e = es; | |
1269 } | |
1270 } | |
1271 else if (e1->op == TOKarrayliteral && | |
1272 lwr->op == TOKint64 && upr->op == TOKint64 && | |
1273 !e1->checkSideEffect(2)) | |
1274 { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1275 uinteger_t ilwr = lwr->toInteger(); | |
1276 uinteger_t iupr = upr->toInteger(); | |
1277 | |
1278 if (iupr > es1->elements->dim || ilwr > iupr) | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
735
diff
changeset
|
1279 e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr); |
336 | 1280 else |
1281 { | |
1282 Expressions *elements = new Expressions(); | |
1283 elements->setDim(iupr - ilwr); | |
1284 memcpy(elements->data, | |
1285 es1->elements->data + ilwr, | |
1286 (iupr - ilwr) * sizeof(es1->elements->data[0])); | |
1287 e = new ArrayLiteralExp(e1->loc, elements); | |
1288 e->type = type; | |
1289 } | |
1290 } | |
1291 return e; | |
1292 } | |
1293 | |
1294 /* Also return EXP_CANT_INTERPRET if this fails | |
1295 */ | |
1296 Expression *Cat(Type *type, Expression *e1, Expression *e2) | |
1297 { Expression *e = EXP_CANT_INTERPRET; | |
1298 Loc loc = e1->loc; | |
1299 Type *t; | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1300 Type *t1 = e1->type->toBasetype(); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1301 Type *t2 = e2->type->toBasetype(); |
336 | 1302 |
1303 //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars()); | |
1304 | |
1305 if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral)) | |
1306 { e = e2; | |
1307 goto L2; | |
1308 } | |
1309 else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull) | |
1310 { e = e1; | |
1311 L2: | |
1312 Type *tn = e->type->toBasetype(); | |
1313 if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) | |
1314 { | |
1315 // Create a StringExp | |
1316 void *s; | |
1317 StringExp *es; | |
1318 size_t len = 1; | |
1319 int sz = tn->size(); | |
1320 integer_t v = e->toInteger(); | |
1321 | |
1322 s = mem.malloc((len + 1) * sz); | |
1323 memcpy((unsigned char *)s, &v, sz); | |
1324 | |
1325 // Add terminating 0 | |
1326 memset((unsigned char *)s + len * sz, 0, sz); | |
1327 | |
1328 es = new StringExp(loc, s, len); | |
1329 es->sz = sz; | |
1330 es->committed = 1; | |
1331 e = es; | |
1332 } | |
1333 else | |
1334 { // Create an ArrayLiteralExp | |
1335 Expressions *elements = new Expressions(); | |
1336 elements->push(e); | |
1337 e = new ArrayLiteralExp(e->loc, elements); | |
1338 } | |
1339 e->type = type; | |
1340 return e; | |
1341 } | |
1342 else if (e1->op == TOKstring && e2->op == TOKstring) | |
1343 { | |
1344 // Concatenate the strings | |
1345 void *s; | |
1346 StringExp *es1 = (StringExp *)e1; | |
1347 StringExp *es2 = (StringExp *)e2; | |
1348 StringExp *es; | |
1349 Type *t; | |
1350 size_t len = es1->len + es2->len; | |
1351 int sz = es1->sz; | |
1352 | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1353 if (sz != es2->sz) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1354 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1355 /* Can happen with: |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1356 * auto s = "foo"d ~ "bar"c; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1357 */ |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1358 assert(global.errors); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1359 return e; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
637
diff
changeset
|
1360 } |
336 | 1361 s = mem.malloc((len + 1) * sz); |
1362 memcpy(s, es1->string, es1->len * sz); | |
1363 memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz); | |
1364 | |
1365 // Add terminating 0 | |
1366 memset((unsigned char *)s + len * sz, 0, sz); | |
1367 | |
1368 es = new StringExp(loc, s, len); | |
1369 es->sz = sz; | |
1370 es->committed = es1->committed | es2->committed; | |
1371 if (es1->committed) | |
1372 t = es1->type; | |
1373 else | |
1374 t = es2->type; | |
1375 es->type = type; | |
1376 e = es; | |
1377 } | |
1378 else if (e1->op == TOKstring && e2->op == TOKint64) | |
1379 { | |
1380 // Concatenate the strings | |
1381 void *s; | |
1382 StringExp *es1 = (StringExp *)e1; | |
1383 StringExp *es; | |
1384 Type *t; | |
1385 size_t len = es1->len + 1; | |
1386 int sz = es1->sz; | |
1387 integer_t v = e2->toInteger(); | |
1388 | |
1389 s = mem.malloc((len + 1) * sz); | |
1390 memcpy(s, es1->string, es1->len * sz); | |
1391 memcpy((unsigned char *)s + es1->len * sz, &v, sz); | |
1392 | |
1393 // Add terminating 0 | |
1394 memset((unsigned char *)s + len * sz, 0, sz); | |
1395 | |
1396 es = new StringExp(loc, s, len); | |
1397 es->sz = sz; | |
1398 es->committed = es1->committed; | |
1399 t = es1->type; | |
1400 es->type = type; | |
1401 e = es; | |
1402 } | |
1403 else if (e1->op == TOKint64 && e2->op == TOKstring) | |
1404 { | |
1405 // Concatenate the strings | |
1406 void *s; | |
1407 StringExp *es2 = (StringExp *)e2; | |
1408 StringExp *es; | |
1409 Type *t; | |
1410 size_t len = 1 + es2->len; | |
1411 int sz = es2->sz; | |
1412 integer_t v = e1->toInteger(); | |
1413 | |
1414 s = mem.malloc((len + 1) * sz); | |
1415 memcpy((unsigned char *)s, &v, sz); | |
1416 memcpy((unsigned char *)s + sz, es2->string, es2->len * sz); | |
1417 | |
1418 // Add terminating 0 | |
1419 memset((unsigned char *)s + len * sz, 0, sz); | |
1420 | |
1421 es = new StringExp(loc, s, len); | |
1422 es->sz = sz; | |
1423 es->committed = es2->committed; | |
1424 t = es2->type; | |
1425 es->type = type; | |
1426 e = es; | |
1427 } | |
1428 else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral && | |
1429 e1->type->equals(e2->type)) | |
1430 { | |
1431 // Concatenate the arrays | |
1432 ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1; | |
1433 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1434 | |
1435 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1436 es1->elements->insert(es1->elements->dim, es2->elements); | |
1437 e = es1; | |
1438 | |
1439 if (type->toBasetype()->ty == Tsarray) | |
1440 { | |
1441 e->type = new TypeSArray(e1->type->toBasetype()->next, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1442 e->type = e->type->semantic(loc, NULL); | |
1443 } | |
1444 else | |
1445 e->type = type; | |
1446 } | |
717
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1447 else if (e1->op == TOKarrayliteral && e2->op == TOKnull && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1448 t1->nextOf()->equals(t2->nextOf())) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1449 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1450 e = e1; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1451 goto L3; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1452 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1453 else if (e1->op == TOKnull && e2->op == TOKarrayliteral && |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1454 t1->nextOf()->equals(t2->nextOf())) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1455 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1456 e = e2; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1457 L3: |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1458 // Concatenate the array with null |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1459 ArrayLiteralExp *es = (ArrayLiteralExp *)e; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1460 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1461 es = new ArrayLiteralExp(es->loc, (Expressions *)es->elements->copy()); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1462 e = es; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1463 |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1464 if (type->toBasetype()->ty == Tsarray) |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1465 { |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1466 e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex)); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1467 e->type = e->type->semantic(loc, NULL); |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1468 } |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1469 else |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1470 e->type = type; |
a26b0c5d5942
Merged DMD 1.036.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1471 } |
336 | 1472 else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) && |
1473 e1->type->toBasetype()->nextOf()->equals(e2->type)) | |
1474 { | |
1475 ArrayLiteralExp *es1; | |
1476 if (e1->op == TOKarrayliteral) | |
1477 { es1 = (ArrayLiteralExp *)e1; | |
1478 es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy()); | |
1479 es1->elements->push(e2); | |
1480 } | |
1481 else | |
1482 { | |
1483 es1 = new ArrayLiteralExp(e1->loc, e2); | |
1484 } | |
1485 e = es1; | |
1486 | |
1487 if (type->toBasetype()->ty == Tsarray) | |
1488 { | |
1489 e->type = new TypeSArray(e2->type, new IntegerExp(0, es1->elements->dim, Type::tindex)); | |
1490 e->type = e->type->semantic(loc, NULL); | |
1491 } | |
1492 else | |
1493 e->type = type; | |
1494 } | |
1495 else if (e2->op == TOKarrayliteral && | |
1496 e2->type->toBasetype()->nextOf()->equals(e1->type)) | |
1497 { | |
1498 ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2; | |
1499 | |
1500 es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy()); | |
1501 es2->elements->shift(e1); | |
1502 e = es2; | |
1503 | |
1504 if (type->toBasetype()->ty == Tsarray) | |
1505 { | |
1506 e->type = new TypeSArray(e1->type, new IntegerExp(0, es2->elements->dim, Type::tindex)); | |
1507 e->type = e->type->semantic(loc, NULL); | |
1508 } | |
1509 else | |
1510 e->type = type; | |
1511 } | |
1512 else if (e1->op == TOKnull && e2->op == TOKstring) | |
1513 { | |
1514 t = e1->type; | |
1515 e = e2; | |
1516 goto L1; | |
1517 } | |
1518 else if (e1->op == TOKstring && e2->op == TOKnull) | |
1519 { e = e1; | |
1520 t = e2->type; | |
1521 L1: | |
1522 Type *tb = t->toBasetype(); | |
1523 if (tb->ty == Tarray && tb->nextOf()->equals(e->type)) | |
1524 { Expressions *expressions = new Expressions(); | |
1525 expressions->push(e); | |
1526 e = new ArrayLiteralExp(loc, expressions); | |
1527 e->type = t; | |
1528 } | |
1529 if (!e->type->equals(type)) | |
1530 { StringExp *se = (StringExp *)e->copy(); | |
1531 e = se->castTo(NULL, type); | |
1532 } | |
1533 } | |
1534 return e; | |
1535 } | |
1536 | |
1537 Expression *Ptr(Type *type, Expression *e1) | |
1538 { | |
1539 //printf("Ptr(e1 = %s)\n", e1->toChars()); | |
1540 if (e1->op == TOKadd) | |
1541 { AddExp *ae = (AddExp *)e1; | |
1542 if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64) | |
1543 { AddrExp *ade = (AddrExp *)ae->e1; | |
1544 if (ade->e1->op == TOKstructliteral) | |
1545 { StructLiteralExp *se = (StructLiteralExp *)ade->e1; | |
1546 unsigned offset = ae->e2->toInteger(); | |
1547 Expression *e = se->getField(type, offset); | |
1548 if (!e) | |
1549 e = EXP_CANT_INTERPRET; | |
1550 return e; | |
1551 } | |
1552 } | |
1553 } | |
1554 return EXP_CANT_INTERPRET; | |
1555 } | |
1556 |