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