Mercurial > projects > ddmd
annotate dmd/IntegerExp.d @ 68:ee3a9f34dc48
final bits of codegen implementation to compile Phobos
author | korDen |
---|---|
date | Tue, 24 Aug 2010 16:44:34 +0400 |
parents | cab4c37afb89 |
children | 2e2a5c3f943a |
rev | line source |
---|---|
0 | 1 module dmd.IntegerExp; |
2 | |
3 import dmd.Expression; | |
4 import dmd.backend.elem; | |
5 import dmd.TY; | |
6 import dmd.TypeEnum; | |
7 import dmd.TypeTypedef; | |
8 import dmd.Global; | |
9 import dmd.InterState; | |
10 import dmd.MATCH; | |
11 import dmd.Type; | |
12 import dmd.OutBuffer; | |
13 import dmd.Loc; | |
14 import dmd.Scope; | |
15 import dmd.IntRange; | |
16 import dmd.IRState; | |
17 import dmd.HdrGenState; | |
18 import dmd.TOK; | |
19 import dmd.Complex; | |
20 | |
21 import dmd.backend.dt_t; | |
22 import dmd.backend.Util; | |
23 | |
24 import core.stdc.ctype : isprint; | |
25 | |
26 class IntegerExp : Expression | |
27 { | |
28 ulong value; | |
29 | |
30 this(Loc loc, ulong value, Type type) | |
31 { | |
32 super(loc, TOK.TOKint64, IntegerExp.sizeof); | |
33 | |
34 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : ""); | |
35 if (type && !type.isscalar()) | |
36 { | |
37 //printf("%s, loc = %d\n", toChars(), loc.linnum); | |
38 error("integral constant must be scalar type, not %s", type.toChars()); | |
39 type = Type.terror; | |
40 } | |
41 this.type = type; | |
42 this.value = value; | |
43 } | |
44 | |
45 this(ulong value) | |
46 { | |
47 super(Loc(0), TOK.TOKint64, IntegerExp.sizeof); | |
48 this.type = Type.tint32; | |
49 this.value = value; | |
50 } | |
51 | |
45 | 52 bool equals(Object o) |
0 | 53 { |
54 IntegerExp ne; | |
55 | |
56 if (this == o || | |
57 ((cast(Expression)o).op == TOKint64 && | |
58 ((ne = cast(IntegerExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) && | |
59 value == ne.value) | |
60 ) | |
61 return 1; | |
62 | |
63 return 0; | |
64 } | |
65 | |
66 Expression semantic(Scope sc) | |
67 { | |
68 if (!type) | |
69 { | |
70 // Determine what the type of this number is | |
71 ulong number = value; | |
72 | |
73 if (number & 0x8000000000000000) | |
74 type = Type.tuns64; | |
75 else if (number & 0xFFFFFFFF80000000) | |
76 type = Type.tint64; | |
77 else | |
78 type = Type.tint32; | |
79 } | |
80 else | |
81 { if (!type.deco) | |
82 type = type.semantic(loc, sc); | |
83 } | |
84 return this; | |
85 } | |
86 | |
63 | 87 Expression interpret(InterState istate) |
0 | 88 { |
63 | 89 version (LOG) { |
90 printf("IntegerExp.interpret() %s\n", toChars()); | |
91 } | |
92 return this; | |
0 | 93 } |
94 | |
95 string toChars() | |
96 { | |
97 static if (true) { | |
98 return Expression.toChars(); | |
99 } else { | |
100 static char buffer[value.sizeof * 3 + 1]; | |
101 int len = sprintf(buffer.ptr, "%jd", value); | |
102 return buffer[0..len].idup; | |
103 } | |
104 } | |
105 | |
106 void dump(int indent) | |
107 { | |
108 assert(false); | |
109 } | |
110 | |
111 IntRange getIntRange() | |
112 { | |
53 | 113 IntRange ir; |
114 ir.imin = value & type.sizemask(); | |
115 ir.imax = ir.imin; | |
116 return ir; | |
0 | 117 } |
118 | |
119 ulong toInteger() | |
120 { | |
121 Type t; | |
122 | |
123 t = type; | |
124 while (t) | |
125 { | |
126 switch (t.ty) | |
127 { | |
128 case TY.Tbit: | |
129 case TY.Tbool: value = (value != 0); break; | |
130 case TY.Tint8: value = cast(byte) value; break; | |
131 case TY.Tchar: | |
132 case TY.Tuns8: value = cast(ubyte) value; break; | |
133 case TY.Tint16: value = cast(short) value; break; | |
134 case TY.Twchar: | |
135 case TY.Tuns16: value = cast(ushort)value; break; | |
136 case TY.Tint32: value = cast(int) value; break; | |
137 case TY.Tdchar: | |
138 case TY.Tuns32: value = cast(uint) value; break; | |
139 case TY.Tint64: value = cast(long) value; break; | |
140 case TY.Tuns64: value = cast(ulong) value; break; | |
141 case TY.Tpointer: | |
142 if (PTRSIZE == 4) | |
143 value = cast(uint) value; | |
144 else if (PTRSIZE == 8) | |
145 value = cast(ulong) value; | |
146 else | |
147 assert(0); | |
148 break; | |
149 | |
150 case TY.Tenum: | |
151 { | |
152 TypeEnum te = cast(TypeEnum)t; | |
153 t = te.sym.memtype; | |
154 continue; | |
155 } | |
156 | |
157 case TY.Ttypedef: | |
158 { | |
159 TypeTypedef tt = cast(TypeTypedef)t; | |
160 t = tt.sym.basetype; | |
161 continue; | |
162 } | |
163 | |
164 default: | |
165 /* This can happen if errors, such as | |
166 * the type is painted on like in fromConstInitializer(). | |
167 */ | |
168 if (!global.errors) | |
169 { | |
170 ///type.print(); | |
171 assert(0); | |
172 } | |
173 break; | |
174 } | |
175 break; | |
176 } | |
177 return value; | |
178 } | |
179 | |
180 real toReal() | |
181 { | |
182 Type t; | |
183 | |
184 toInteger(); | |
185 t = type.toBasetype(); | |
186 if (t.ty == Tuns64) | |
187 return cast(real)cast(ulong)value; | |
188 else | |
189 return cast(real)cast(long)value; | |
190 } | |
191 | |
192 real toImaginary() | |
193 { | |
194 assert(false); | |
195 } | |
196 | |
197 Complex!(real) toComplex() | |
198 { | |
199 assert(false); | |
200 } | |
201 | |
202 int isConst() | |
203 { | |
204 return 1; | |
205 } | |
206 | |
207 bool isBool(bool result) | |
208 { | |
209 return result ? value != 0 : value == 0; | |
210 } | |
211 | |
212 MATCH implicitConvTo(Type t) | |
213 { | |
214 static if (false) { | |
215 printf("IntegerExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
216 toChars(), type.toChars(), t.toChars()); | |
217 } | |
218 | |
219 MATCH m = type.implicitConvTo(t); | |
220 if (m >= MATCH.MATCHconst) | |
221 return m; | |
222 | |
223 TY ty = type.toBasetype().ty; | |
224 TY toty = t.toBasetype().ty; | |
225 | |
226 if (m == MATCH.MATCHnomatch && t.ty == TY.Tenum) | |
227 goto Lno; | |
228 | |
229 switch (ty) | |
230 { | |
231 case TY.Tbit: | |
232 case TY.Tbool: | |
233 value &= 1; | |
234 ty = TY.Tint32; | |
235 break; | |
236 | |
237 case TY.Tint8: | |
238 value = cast(byte)value; | |
239 ty = TY.Tint32; | |
240 break; | |
241 | |
242 case TY.Tchar: | |
243 case TY.Tuns8: | |
244 value &= 0xFF; | |
245 ty = TY.Tint32; | |
246 break; | |
247 | |
248 case TY.Tint16: | |
249 value = cast(short)value; | |
250 ty = TY.Tint32; | |
251 break; | |
252 | |
253 case TY.Tuns16: | |
254 case TY.Twchar: | |
255 value &= 0xFFFF; | |
256 ty = TY.Tint32; | |
257 break; | |
258 | |
259 case TY.Tint32: | |
260 value = cast(int)value; | |
261 break; | |
262 | |
263 case TY.Tuns32: | |
264 case TY.Tdchar: | |
265 value &= 0xFFFFFFFF; | |
266 ty = TY.Tuns32; | |
267 break; | |
268 | |
269 default: | |
270 break; | |
271 } | |
272 | |
273 // Only allow conversion if no change in value | |
274 switch (toty) | |
275 { | |
276 case TY.Tbit: | |
277 case TY.Tbool: | |
278 if ((value & 1) != value) | |
279 goto Lno; | |
280 goto Lyes; | |
281 | |
282 case TY.Tint8: | |
283 if (cast(byte)value != value) | |
284 goto Lno; | |
285 goto Lyes; | |
286 | |
287 case TY.Tchar: | |
288 case TY.Tuns8: | |
289 //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); | |
290 if (cast(ubyte)value != value) | |
291 goto Lno; | |
292 goto Lyes; | |
293 | |
294 case TY.Tint16: | |
295 if (cast(short)value != value) | |
296 goto Lno; | |
297 goto Lyes; | |
298 | |
299 case TY.Tuns16: | |
300 if (cast(ushort)value != value) | |
301 goto Lno; | |
302 goto Lyes; | |
303 | |
304 case TY.Tint32: | |
305 if (ty == TY.Tuns32) { | |
306 ; | |
307 } | |
308 else if (cast(int)value != value) { | |
309 goto Lno; | |
310 } | |
311 goto Lyes; | |
312 | |
313 case TY.Tuns32: | |
314 if (ty == TY.Tint32) { | |
315 } else if (cast(uint)value != value) { | |
316 goto Lno; | |
317 } | |
318 goto Lyes; | |
319 | |
320 case TY.Tdchar: | |
321 if (value > 0x10FFFF) { | |
322 goto Lno; | |
323 } | |
324 goto Lyes; | |
325 | |
326 case TY.Twchar: | |
327 if (cast(ushort)value != value) { | |
328 goto Lno; | |
329 } | |
330 goto Lyes; | |
331 | |
332 case TY.Tfloat32: | |
333 { | |
334 /*volatile*/ float f; /// | |
335 if (type.isunsigned()) { | |
336 f = cast(float)value; | |
337 if (f != value) { | |
338 goto Lno; | |
339 } | |
340 } else { | |
341 f = cast(float)cast(long)value; | |
342 if (f != cast(long)value) { | |
343 goto Lno; | |
344 } | |
345 } | |
346 goto Lyes; | |
347 } | |
348 | |
349 case TY.Tfloat64: | |
350 { | |
351 /*volatile*/ double f; /// | |
352 if (type.isunsigned()) { | |
353 f = cast(double)value; | |
354 if (f != value) | |
355 goto Lno; | |
356 } else { | |
357 f = cast(double)cast(long)value; | |
358 if (f != cast(long)value) | |
359 goto Lno; | |
360 } | |
361 goto Lyes; | |
362 } | |
363 | |
364 case TY.Tfloat80: | |
365 { | |
366 /*volatile*/ real f; /// | |
367 if (type.isunsigned()) { | |
368 f = cast(real)value; | |
369 if (f != value) | |
370 goto Lno; | |
371 } else { | |
372 f = cast(real)cast(long)value; | |
373 if (f != cast(long)value) | |
374 goto Lno; | |
375 } | |
376 goto Lyes; | |
377 } | |
378 | |
379 case TY.Tpointer: | |
380 //printf("type = %s\n", type.toBasetype().toChars()); | |
381 //printf("t = %s\n", t.toBasetype().toChars()); | |
382 if (ty == TY.Tpointer && type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty) | |
383 { | |
384 /* Allow things like: | |
385 * const char* P = cast(char *)3; | |
386 * char* q = P; | |
387 */ | |
388 goto Lyes; | |
389 } | |
390 break; | |
391 | |
392 default: | |
393 break; /// | |
394 } | |
395 | |
396 return Expression.implicitConvTo(t); | |
397 | |
398 Lyes: | |
399 //printf("MATCHconvert\n"); | |
400 return MATCH.MATCHconvert; | |
401 | |
402 Lno: | |
403 //printf("MATCHnomatch\n"); | |
404 return MATCH.MATCHnomatch; | |
405 } | |
406 | |
407 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
408 { | |
409 long v = toInteger(); | |
410 | |
411 if (type) | |
412 { | |
413 Type t = type; | |
414 | |
415 L1: | |
416 switch (t.ty) | |
417 { | |
418 case TY.Tenum: | |
419 { | |
420 TypeEnum te = cast(TypeEnum)t; | |
421 buf.printf("cast(%s)", te.sym.toChars()); | |
422 t = te.sym.memtype; | |
423 goto L1; | |
424 } | |
425 | |
426 case TY.Ttypedef: | |
427 { | |
428 TypeTypedef tt = cast(TypeTypedef)t; | |
429 buf.printf("cast(%s)", tt.sym.toChars()); | |
430 t = tt.sym.basetype; | |
431 goto L1; | |
432 } | |
433 | |
434 case TY.Twchar: // BUG: need to cast(wchar) | |
435 case TY.Tdchar: // BUG: need to cast(dchar) | |
436 if (cast(ulong)v > 0xFF) | |
437 { | |
438 buf.printf("'\\U%08x'", v); | |
439 break; | |
440 } | |
441 case TY.Tchar: | |
442 if (v == '\'') | |
443 buf.writestring("'\\''"); | |
444 else if (isprint(cast(int)v) && v != '\\') | |
445 buf.printf("'%c'", cast(int)v); | |
446 else | |
447 buf.printf("'\\x%02x'", cast(int)v); | |
448 break; | |
449 | |
450 case TY.Tint8: | |
451 buf.writestring("cast(byte)"); | |
452 goto L2; | |
453 | |
454 case TY.Tint16: | |
455 buf.writestring("cast(short)"); | |
456 goto L2; | |
457 | |
458 case TY.Tint32: | |
459 L2: | |
460 buf.printf("%d", cast(int)v); | |
461 break; | |
462 | |
463 case TY.Tuns8: | |
464 buf.writestring("cast(ubyte)"); | |
465 goto L3; | |
466 | |
467 case TY.Tuns16: | |
468 buf.writestring("cast(ushort)"); | |
469 goto L3; | |
470 | |
471 case TY.Tuns32: | |
472 L3: | |
473 buf.printf("%du", cast(uint)v); | |
474 break; | |
475 | |
476 case TY.Tint64: | |
68
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
63
diff
changeset
|
477 //buf.printf("%jdL", v); |
ee3a9f34dc48
final bits of codegen implementation to compile Phobos
korDen
parents:
63
diff
changeset
|
478 buf.printf("%sL", v); |
0 | 479 break; |
480 | |
481 case TY.Tuns64: | |
482 L4: | |
50 | 483 //buf.printf("%juLU", v); |
484 buf.printf("%sLU", v); | |
0 | 485 break; |
486 | |
487 case TY.Tbit: | |
488 case TY.Tbool: | |
489 buf.writestring(v ? "true" : "false"); | |
490 break; | |
491 | |
492 case TY.Tpointer: | |
493 buf.writestring("cast("); | |
494 buf.writestring(t.toChars()); | |
495 buf.writeByte(')'); | |
496 if (PTRSIZE == 4) | |
497 goto L3; | |
498 else if (PTRSIZE == 8) | |
499 goto L4; | |
500 else | |
501 assert(0); | |
502 | |
503 default: | |
504 /* This can happen if errors, such as | |
505 * the type is painted on like in fromConstInitializer(). | |
506 */ | |
507 if (!global.errors) | |
508 { | |
509 debug { | |
510 writef("%s\n", t.toChars()); | |
511 } | |
512 assert(0); | |
513 } | |
514 break; | |
515 } | |
516 } | |
517 else if (v & 0x8000000000000000L) | |
518 buf.printf("0x%jx", v); | |
519 else | |
520 buf.printf("%jd", v); | |
521 } | |
522 | |
523 void toMangleBuffer(OutBuffer buf) | |
524 { | |
20
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
525 if (cast(long)value < 0) |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
526 buf.printf("N%d", -value); |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
527 else |
1628b221808d
Fleshed out more unimplemented methods.
Robert Clipsham <robert@octarineparrot.com>
parents:
0
diff
changeset
|
528 buf.printf("%d", value); |
0 | 529 } |
530 | |
531 Expression toLvalue(Scope sc, Expression e) | |
532 { | |
533 if (!e) | |
534 e = this; | |
535 else if (!loc.filename) | |
536 loc = e.loc; | |
537 e.error("constant %s is not an lvalue", e.toChars()); | |
538 return this; | |
539 } | |
540 | |
541 elem* toElem(IRState* irs) | |
542 { | |
543 elem* e = el_long(type.totym(), value); | |
544 el_setLoc(e,loc); | |
545 return e; | |
546 } | |
547 | |
548 dt_t** toDt(dt_t** pdt) | |
549 { | |
550 //printf("IntegerExp.toDt() %d\n", op); | |
551 uint sz = cast(uint)type.size(); | |
552 if (value == 0) | |
553 pdt = dtnzeros(pdt, sz); | |
554 else | |
555 pdt = dtnbytes(pdt, sz, cast(char*)&value); | |
556 | |
557 return pdt; | |
558 } | |
559 } | |
560 |