Mercurial > projects > ddmd
annotate dmd/CastExp.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | 010eb8f0e18d |
children | af1bebfd96a4 |
rev | line source |
---|---|
72 | 1 module dmd.CastExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
129 | 5 import dmd.GlobalExpressions; |
72 | 6 import dmd.TY; |
7 import dmd.TypeStruct; | |
73 | 8 import dmd.ErrorExp; |
72 | 9 import dmd.TypeExp; |
10 import dmd.DotIdExp; | |
11 import dmd.CallExp; | |
12 import dmd.Global; | |
13 import dmd.Id; | |
14 import dmd.Identifier; | |
15 import dmd.BinExp; | |
16 import dmd.UnaExp; | |
17 import dmd.VarExp; | |
18 import dmd.Token; | |
19 import dmd.VarDeclaration; | |
20 import dmd.InterState; | |
21 import dmd.MATCH; | |
22 import dmd.Type; | |
23 import dmd.OutBuffer; | |
24 import dmd.Loc; | |
25 import dmd.Scope; | |
26 import dmd.IntRange; | |
27 import dmd.IRState; | |
28 import dmd.ArrayTypes; | |
29 import dmd.HdrGenState; | |
30 import dmd.MOD; | |
31 import dmd.TOK; | |
32 import dmd.WANT; | |
33 import dmd.ClassDeclaration; | |
34 | |
35 import dmd.Optimize; | |
36 import dmd.PREC; | |
37 import dmd.Cast; | |
38 | |
79 | 39 import dmd.codegen.Util; |
40 import dmd.backend.elem; | |
41 import dmd.backend.mTY; | |
72 | 42 import dmd.backend.Util; |
43 import dmd.backend.TYM; | |
44 import dmd.backend.OPER; | |
45 import dmd.backend.RTLSYM; | |
79 | 46 import dmd.expression.Util; |
72 | 47 |
0 | 48 class CastExp : UnaExp |
49 { | |
72 | 50 // Possible to cast to one type while painting to another type |
0 | 51 Type to; // type to cast to |
52 MOD mod; // MODxxxxx | |
53 | |
54 this(Loc loc, Expression e, Type t) | |
55 { | |
72 | 56 super(loc, TOK.TOKcast, CastExp.sizeof, e); |
57 to = t; | |
0 | 58 this.mod = cast(MOD)~0; |
59 } | |
60 | |
61 this(Loc loc, Expression e, MOD mod) | |
72 | 62 { |
63 super(loc, TOK.TOKcast, CastExp.sizeof, e); | |
64 to = null; | |
0 | 65 this.mod = mod; |
66 } | |
67 | |
72 | 68 override Expression syntaxCopy() |
0 | 69 { |
72 | 70 return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy()) |
0 | 71 : new CastExp(loc, e1.syntaxCopy(), mod); |
72 } | |
73 | |
72 | 74 override Expression semantic(Scope sc) |
0 | 75 { |
72 | 76 Expression e; |
77 BinExp b; | |
78 UnaExp u; | |
79 | |
80 version (LOGSEMANTIC) { | |
81 printf("CastExp.semantic('%s')\n", toChars()); | |
82 } | |
83 | |
84 //static int x; assert(++x < 10); | |
85 | |
86 if (type) | |
87 return this; | |
88 super.semantic(sc); | |
89 if (e1.type) // if not a tuple | |
90 { | |
73 | 91 e1 = resolveProperties(sc, e1); |
92 | |
93 if (!to) | |
94 { | |
95 /* Handle cast(const) and cast(immutable), etc. | |
96 */ | |
97 to = e1.type.castMod(mod); | |
98 } | |
99 else | |
100 to = to.semantic(loc, sc); | |
101 | |
102 if (!to.equals(e1.type)) | |
103 { | |
104 e = op_overload(sc); | |
105 if (e) | |
106 { | |
107 return e.implicitCastTo(sc, to); | |
108 } | |
109 } | |
72 | 110 |
109 | 111 if (e1.op == TOKtemplate) |
112 { | |
113 error("cannot cast template %s to type %s", e1.toChars(), to.toChars()); | |
114 return new ErrorExp(); | |
115 } | |
116 | |
73 | 117 Type t1b = e1.type.toBasetype(); |
118 Type tob = to.toBasetype(); | |
119 if (tob.ty == TY.Tstruct && | |
120 !tob.equals(t1b) && | |
121 (cast(TypeStruct)tob).sym.search(Loc(0), Id.call, 0) | |
122 ) | |
123 { | |
124 /* Look to replace: | |
125 * cast(S)t | |
126 * with: | |
127 * S(t) | |
128 */ | |
72 | 129 |
73 | 130 // Rewrite as to.call(e1) |
131 e = new TypeExp(loc, to); | |
132 e = new DotIdExp(loc, e, Id.call); | |
133 e = new CallExp(loc, e, e1); | |
134 e = e.semantic(sc); | |
135 return e; | |
136 } | |
137 | |
138 // Struct casts are possible only when the sizes match | |
139 if (tob.ty == Tstruct || t1b.ty == Tstruct) | |
72 | 140 { |
73 | 141 size_t fromsize = cast(size_t)t1b.size(loc); |
142 size_t tosize = cast(size_t)tob.size(loc); | |
143 if (fromsize != tosize) | |
144 { | |
145 error("cannot cast from %s to %s", e1.type.toChars(), to.toChars()); | |
146 return new ErrorExp(); | |
147 } | |
72 | 148 } |
149 } | |
150 else if (!to) | |
73 | 151 { |
152 error("cannot cast tuple"); | |
153 to = Type.terror; | |
72 | 154 } |
155 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
156 //static if (true) { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
157 if (sc.func && sc.func.isSafe() && !sc.intypeof) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
158 //} else { |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
159 // if (global.params.safe && !sc.module_.safe && !sc.intypeof) |
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
160 //} |
72 | 161 { // Disallow unsafe casts |
162 Type tob = to.toBasetype(); | |
163 Type t1b = e1.type.toBasetype(); | |
164 if (!t1b.isMutable() && tob.isMutable()) | |
165 { // Cast not mutable to mutable | |
166 Lunsafe: | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
167 error("cast from %s to %s not allowed in safe code", e1.type.toChars(), to.toChars()); |
72 | 168 } |
169 else if (t1b.isShared() && !tob.isShared()) | |
170 // Cast away shared | |
171 goto Lunsafe; | |
172 else if (tob.ty == TY.Tpointer) | |
173 { if (t1b.ty != TY.Tpointer) | |
174 goto Lunsafe; | |
175 Type tobn = tob.nextOf().toBasetype(); | |
176 Type t1bn = t1b.nextOf().toBasetype(); | |
177 | |
178 if (!t1bn.isMutable() && tobn.isMutable()) | |
179 // Cast away pointer to not mutable | |
180 goto Lunsafe; | |
181 | |
182 if (t1bn.isShared() && !tobn.isShared()) | |
183 // Cast away pointer to shared | |
184 goto Lunsafe; | |
185 | |
186 if (tobn.isTypeBasic() && tobn.size() < t1bn.size()) { | |
187 // Allow things like casting a long* to an int* | |
188 ; | |
189 } else if (tobn.ty != TY.Tvoid) { | |
190 // Cast to a pointer other than void* | |
191 goto Lunsafe; | |
192 } | |
193 } | |
194 | |
195 // BUG: Check for casting array types, such as void[] to int*[] | |
196 } | |
197 | |
198 e = e1.castTo(sc, to); | |
0 | 199 return e; |
200 } | |
201 | |
72 | 202 override MATCH implicitConvTo(Type t) |
0 | 203 { |
72 | 204 static if (false) { |
205 printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); | |
206 } | |
207 MATCH result = type.implicitConvTo(t); | |
208 | |
209 if (result == MATCHnomatch) | |
210 { | |
211 if (t.isintegral() && | |
212 e1.type.isintegral() && | |
213 e1.implicitConvTo(t) != MATCHnomatch) | |
214 result = MATCHconvert; | |
215 else | |
216 result = Expression.implicitConvTo(t); | |
217 } | |
0 | 218 return result; |
219 } | |
220 | |
72 | 221 override IntRange getIntRange() |
0 | 222 { |
72 | 223 IntRange ir; |
224 ir = e1.getIntRange(); | |
225 // Do sign extension | |
226 switch (e1.type.toBasetype().ty) | |
227 { | |
228 case Tint8: | |
229 if (ir.imax & 0x80) | |
230 ir.imax |= 0xFFFFFFFFFFFFFF00UL; | |
231 break; | |
232 case Tint16: | |
233 if (ir.imax & 0x8000) | |
234 ir.imax |= 0xFFFFFFFFFFFF0000UL; | |
235 break; | |
236 case Tint32: | |
237 if (ir.imax & 0x80000000) | |
238 ir.imax |= 0xFFFFFFFF00000000UL; | |
239 break; | |
240 default: | |
241 } | |
73 | 242 |
243 if (type.isintegral()) | |
244 { | |
245 ir.imin &= type.sizemask(); | |
246 ir.imax &= type.sizemask(); | |
247 } | |
248 | |
249 //printf("CastExp: imin = x%llx, imax = x%llx\n", ir.imin, ir.imax); | |
53 | 250 return ir; |
0 | 251 } |
252 | |
72 | 253 override Expression optimize(int result) |
254 { | |
255 //printf("CastExp.optimize(result = %d) %s\n", result, toChars()); | |
256 //printf("from %s to %s\n", type.toChars(), to.toChars()); | |
257 //printf("from %s\n", type.toChars()); | |
258 //printf("e1.type %s\n", e1.type.toChars()); | |
259 //printf("type = %p\n", type); | |
260 assert(type); | |
261 TOK op1 = e1.op; | |
262 | |
263 Expression e1old = e1; | |
264 e1 = e1.optimize(result); | |
265 e1 = fromConstInitializer(result, e1); | |
266 | |
267 if (e1 == e1old && | |
268 e1.op == TOK.TOKarrayliteral && | |
269 type.toBasetype().ty == TY.Tpointer && | |
270 e1.type.toBasetype().ty != TY.Tsarray) | |
271 { | |
272 // Casting this will result in the same expression, and | |
273 // infinite loop because of Expression.implicitCastTo() | |
274 return this; // no change | |
275 } | |
276 | |
277 if ((e1.op == TOK.TOKstring || e1.op == TOK.TOKarrayliteral) && | |
278 (type.ty == TY.Tpointer || type.ty == TY.Tarray) && | |
279 e1.type.nextOf().size() == type.nextOf().size() | |
280 ) | |
281 { | |
282 Expression e = e1.castTo(null, type); | |
283 | |
284 static if (false) { | |
285 printf(" returning1 %s\n", e.toChars()); | |
286 } | |
287 return e; | |
288 } | |
289 | |
290 if (e1.op == TOK.TOKstructliteral && | |
291 e1.type.implicitConvTo(type) >= MATCH.MATCHconst) | |
292 { | |
293 e1.type = type; | |
294 static if (false) { | |
295 printf(" returning2 %s\n", e1.toChars()); | |
296 } | |
297 return e1; | |
298 } | |
299 | |
300 /* The first test here is to prevent infinite loops | |
301 */ | |
302 if (op1 != TOK.TOKarrayliteral && e1.op == TOK.TOKarrayliteral) | |
303 return e1.castTo(null, to); | |
304 if (e1.op == TOK.TOKnull && | |
305 (type.ty == TY.Tpointer || type.ty == TY.Tclass || type.ty == TY.Tarray)) | |
306 { | |
307 e1.type = type; | |
308 static if (false) { | |
309 printf(" returning3 %s\n", e1.toChars()); | |
310 } | |
311 return e1; | |
312 } | |
313 | |
314 if (result & WANT.WANTflags && type.ty == TY.Tclass && e1.type.ty == TY.Tclass) | |
315 { | |
316 // See if we can remove an unnecessary cast | |
317 ClassDeclaration cdfrom; | |
318 ClassDeclaration cdto; | |
319 int offset; | |
320 | |
321 cdfrom = e1.type.isClassHandle(); | |
322 cdto = type.isClassHandle(); | |
323 if (cdto.isBaseOf(cdfrom, &offset) && offset == 0) | |
324 { | |
325 e1.type = type; | |
326 static if (false) { | |
327 printf(" returning4 %s\n", e1.toChars()); | |
328 } | |
329 return e1; | |
330 } | |
331 } | |
332 | |
333 // We can convert 'head const' to mutable | |
334 if (to.constOf().equals(e1.type.constOf())) | |
335 // if (to.constConv(e1.type) >= MATCHconst) | |
336 { | |
337 e1.type = type; | |
338 static if (false) { | |
339 printf(" returning5 %s\n", e1.toChars()); | |
340 } | |
341 return e1; | |
342 } | |
343 | |
344 Expression e; | |
345 | |
346 if (e1.isConst()) | |
347 { | |
348 if (e1.op == TOK.TOKsymoff) | |
349 { | |
350 if (type.size() == e1.type.size() && | |
351 type.toBasetype().ty != TY.Tsarray) | |
352 { | |
353 e1.type = type; | |
354 return e1; | |
355 } | |
356 return this; | |
357 } | |
358 if (to.toBasetype().ty == TY.Tvoid) | |
359 e = this; | |
360 else | |
361 e = Cast(type, to, e1); | |
362 } | |
363 else | |
364 e = this; | |
365 static if (false) { | |
366 printf(" returning6 %s\n", e.toChars()); | |
367 } | |
0 | 368 return e; |
369 } | |
370 | |
72 | 371 override Expression interpret(InterState istate) |
0 | 372 { |
129 | 373 Expression e; |
374 Expression e1; | |
375 | |
376 version (LOG) { | |
377 printf("CastExp.interpret() %.*s\n", toChars()); | |
378 } | |
379 e1 = this.e1.interpret(istate); | |
380 if (e1 is EXP_CANT_INTERPRET) | |
381 goto Lcant; | |
382 return Cast(type, to, e1); | |
383 | |
384 Lcant: | |
385 version (LOG) { | |
386 printf("CastExp.interpret() %.*s CANT\n", toChars()); | |
387 } | |
388 return EXP_CANT_INTERPRET; | |
0 | 389 } |
390 | |
72 | 391 override bool checkSideEffect(int flag) |
0 | 392 { |
123 | 393 /* if not: |
394 * cast(void) | |
395 * cast(classtype)func() | |
396 */ | |
397 if (!to.equals(Type.tvoid) && !(to.ty == Tclass && e1.op == TOKcall && e1.type.ty == Tclass)) | |
398 return Expression.checkSideEffect(flag); | |
399 | |
400 return true; | |
0 | 401 } |
402 | |
72 | 403 override void checkEscape() |
0 | 404 { |
72 | 405 Type tb = type.toBasetype(); |
406 if (tb.ty == TY.Tarray && e1.op == TOK.TOKvar && e1.type.toBasetype().ty ==TY.Tsarray) | |
407 { | |
408 VarExp ve = cast(VarExp)e1; | |
409 VarDeclaration v = ve.var.isVarDeclaration(); | |
410 if (v) | |
411 { | |
412 if (!v.isDataseg() && !v.isParameter()) | |
413 error("escaping reference to local %s", v.toChars()); | |
414 } | |
0 | 415 } |
416 } | |
417 | |
72 | 418 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 419 { |
72 | 420 buf.writestring("cast("); |
421 version (DMDV1) { | |
422 to.toCBuffer(buf, null, hgs); | |
423 } else { | |
424 if (to) | |
425 to.toCBuffer(buf, null, hgs); | |
426 else | |
427 { | |
428 switch (mod) | |
429 { | |
430 case MODundefined: | |
431 break; | |
432 case MODconst: | |
433 buf.writestring(Token.tochars[TOKconst]); | |
434 break; | |
435 case MODinvariant: | |
436 buf.writestring(Token.tochars[TOKimmutable]); | |
437 break; | |
438 case MODshared: | |
439 buf.writestring(Token.tochars[TOKshared]); | |
440 break; | |
441 case MODshared | MODconst: | |
442 buf.writestring(Token.tochars[TOKshared]); | |
443 buf.writeByte(' '); | |
444 buf.writestring(Token.tochars[TOKconst]); | |
445 break; | |
446 default: | |
447 assert(0); | |
448 } | |
449 } | |
450 } | |
451 buf.writeByte(')'); | |
0 | 452 expToCBuffer(buf, hgs, e1, precedence[op]); |
453 } | |
454 | |
72 | 455 override void buildArrayIdent(OutBuffer buf, Expressions arguments) |
0 | 456 { |
72 | 457 Type tb = type.toBasetype(); |
458 if (tb.ty == Tarray || tb.ty == Tsarray) | |
459 { | |
460 e1.buildArrayIdent(buf, arguments); | |
461 } | |
462 else | |
12
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
463 Expression.buildArrayIdent(buf, arguments); |
0 | 464 } |
465 | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
129
diff
changeset
|
466 override Expression buildArrayLoop(Parameters fparams) |
0 | 467 { |
72 | 468 Type tb = type.toBasetype(); |
469 if (tb.ty == Tarray || tb.ty == Tsarray) | |
470 { | |
471 return e1.buildArrayLoop(fparams); | |
472 } | |
473 else | |
12
832f71e6f96c
*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete)
korDen
parents:
0
diff
changeset
|
474 return Expression.buildArrayLoop(fparams); |
72 | 475 } |
476 | |
477 static int X(int fty, int tty) { | |
478 return ((fty) * TY.TMAX + (tty)); | |
0 | 479 } |
480 | |
72 | 481 override elem* toElem(IRState* irs) |
0 | 482 { |
72 | 483 TY fty; |
484 TY tty; | |
485 tym_t ftym; | |
486 tym_t ttym; | |
487 OPER eop; | |
488 | |
79 | 489 static if (false) |
490 { | |
72 | 491 printf("CastExp::toElem()\n"); |
492 print(); | |
493 printf("\tfrom: %s\n", e1.type.toChars()); | |
494 printf("\tto : %s\n", to.toChars()); | |
495 } | |
496 | |
79 | 497 elem* e = e1.toElem(irs); |
498 Type tfrom = e1.type.toBasetype(); | |
499 Type t = to.toBasetype(); // skip over typedef's | |
72 | 500 if (t.equals(tfrom)) |
501 goto Lret; | |
502 | |
503 fty = tfrom.ty; | |
504 //printf("fty = %d\n", fty); | |
505 tty = t.ty; | |
506 | |
507 if (tty == TY.Tpointer && fty == TY.Tarray | |
508 ///static if (false) { | |
509 /// && (t.next.ty == Tvoid || t.next.equals(e1.type.next)) | |
510 ///} | |
511 ) | |
512 { | |
513 if (e.Eoper == OPER.OPvar) | |
514 { | |
515 // e1 . *(&e1 + 4) | |
516 e = el_una(OPER.OPaddr, TYM.TYnptr, e); | |
517 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, 4)); | |
518 e = el_una(OPER.OPind, t.totym(),e); | |
519 } | |
520 else | |
521 { | |
522 // e1 . (unsigned)(e1 >> 32) | |
523 e = el_bin(OPER.OPshr, TYM.TYullong, e, el_long(TYM.TYint, 32)); | |
524 e = el_una(OPER.OP64_32, t.totym(), e); | |
525 } | |
526 goto Lret; | |
527 } | |
528 | |
529 if (tty == TY.Tpointer && fty == TY.Tsarray | |
530 ///static if (false) { | |
531 /// && (t.next.ty == Tvoid || t.next.equals(e1.type.next)) | |
532 ///} | |
533 ) | |
534 { | |
535 // e1 . &e1 | |
536 e = el_una(OPER.OPaddr, TYM.TYnptr, e); | |
537 goto Lret; | |
538 } | |
539 | |
540 // Convert from static array to dynamic array | |
541 if (tty == TY.Tarray && fty == TY.Tsarray) | |
542 { | |
543 e = sarray_toDarray(loc, tfrom, t, e); | |
544 goto Lret; | |
545 } | |
546 | |
547 // Convert from dynamic array to dynamic array | |
548 if (tty == TY.Tarray && fty == TY.Tarray) | |
549 { | |
550 uint fsize = cast(uint)tfrom.nextOf().size(); | |
551 uint tsize = cast(uint)t.nextOf().size(); | |
552 | |
553 if (fsize != tsize) | |
554 { | |
555 elem* ep = el_params(e, el_long(TYM.TYint, fsize), el_long(TYM.TYint, tsize), null); | |
556 e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCAST]), ep); | |
557 } | |
558 goto Lret; | |
559 } | |
560 | |
79 | 561 static if (false) |
562 { | |
72 | 563 // Convert from dynamic array string literal to static array |
564 if (tty == TY.Tsarray && fty == TY.Tarray && e1.op == TOK.TOKstring) | |
565 { | |
566 goto Lret; // treat as a 'paint' | |
567 } | |
568 } | |
569 | |
570 // Casting from base class to derived class requires a runtime check | |
571 if (fty == TY.Tclass && tty == TY.Tclass) | |
572 { | |
573 // Casting from derived class to base class is a no-op | |
574 ClassDeclaration cdfrom; | |
575 ClassDeclaration cdto; | |
576 int offset; | |
577 int rtl = RTLSYM.RTLSYM_DYNAMIC_CAST; | |
578 | |
579 cdfrom = tfrom.isClassHandle(); | |
580 cdto = t.isClassHandle(); | |
581 if (cdfrom.isInterfaceDeclaration()) | |
582 { | |
583 rtl = RTLSYM.RTLSYM_INTERFACE_CAST; | |
584 if (cdfrom.isCPPinterface()) | |
585 { | |
586 if (cdto.isCPPinterface()) | |
587 { | |
588 /* Casting from a C++ interface to a C++ interface | |
589 * is always a 'paint' operation | |
590 */ | |
591 goto Lret; // no-op | |
592 } | |
593 | |
594 /* Casting from a C++ interface to a class | |
595 * always results in null because there is no runtime | |
596 * information available to do it. | |
597 * | |
598 * Casting from a C++ interface to a non-C++ interface | |
599 * always results in null because there's no way one | |
600 * can be derived from the other. | |
601 */ | |
602 e = el_bin(OPER.OPcomma, TYM.TYnptr, e, el_long(TYM.TYnptr, 0)); | |
603 goto Lret; | |
604 } | |
605 } | |
606 if (cdto.isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME) | |
607 { | |
608 /* The offset from cdfrom=>cdto is known at compile time. | |
609 */ | |
610 | |
611 //printf("offset = %d\n", offset); | |
612 if (offset) | |
613 { | |
614 /* Rewrite cast as (e ? e + offset : null) | |
615 */ | |
616 elem* etmp; | |
617 elem* ex; | |
618 | |
619 if (e1.op == TOK.TOKthis) | |
620 { | |
621 // Assume 'this' is never null, so skip null check | |
622 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset)); | |
623 } | |
624 else | |
625 { | |
626 etmp = el_same(&e); | |
627 ex = el_bin(OPER.OPadd, TYM.TYnptr, etmp, el_long(TYM.TYint, offset)); | |
628 ex = el_bin(OPER.OPcolon, TYM.TYnptr, ex, el_long(TYM.TYnptr, 0)); | |
629 e = el_bin(OPER.OPcond, TYM.TYnptr, e, ex); | |
630 } | |
631 } | |
632 goto Lret; // no-op | |
633 } | |
634 | |
635 /* The offset from cdfrom=>cdto can only be determined at runtime. | |
636 */ | |
637 elem* ep; | |
638 | |
639 ep = el_param(el_ptr(cdto.toSymbol()), e); | |
640 e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[rtl]), ep); | |
641 goto Lret; | |
642 } | |
643 | |
79 | 644 ftym = tybasic(e.Ety); |
645 ttym = tybasic(t.totym()); | |
72 | 646 if (ftym == ttym) |
647 goto Lret; | |
648 | |
649 switch (tty) | |
650 { | |
651 case TY.Tpointer: | |
652 if (fty == TY.Tdelegate) | |
653 goto Lpaint; | |
654 tty = TY.Tuns32; | |
655 break; | |
656 | |
657 case TY.Tchar: | |
658 tty = TY.Tuns8; | |
659 break; | |
660 case TY.Twchar: | |
661 tty = TY.Tuns16; | |
662 break; | |
663 case TY.Tdchar: | |
664 tty = TY.Tuns32; | |
665 break; | |
666 case TY.Tvoid: | |
667 goto Lpaint; | |
668 | |
669 case TY.Tbool: | |
670 { | |
671 // Construct e?true:false | |
672 elem* eq; | |
673 | |
674 e = el_una(OPER.OPbool, ttym, e); | |
675 goto Lret; | |
676 } | |
677 | |
678 default: | |
679 break; /// | |
680 } | |
681 | |
682 switch (fty) | |
683 { | |
684 case TY.Tpointer: fty = TY.Tuns32; break; | |
685 case TY.Tchar: fty = TY.Tuns8; break; | |
686 case TY.Twchar: fty = TY.Tuns16; break; | |
687 case TY.Tdchar: fty = TY.Tuns32; break; | |
688 default: break; /// | |
689 } | |
690 | |
691 Lagain: | |
692 switch (X(fty,tty)) | |
693 { | |
79 | 694 static if (false) |
695 { | |
72 | 696 case X(TY.Tbit,TY.Tint8): |
697 case X(TY.Tbit,TY.Tuns8): | |
698 goto Lpaint; | |
699 case X(TY.Tbit,TY.Tint16): | |
700 case X(TY.Tbit,TY.Tuns16): | |
701 case X(TY.Tbit,TY.Tint32): | |
702 case X(TY.Tbit,TY.Tuns32): | |
703 eop = OPu8_16; | |
704 goto Leop; | |
705 case X(TY.Tbit,TY.Tint64): | |
706 case X(TY.Tbit,TY.Tuns64): | |
707 case X(TY.Tbit,TY.Tfloat32): | |
708 case X(TY.Tbit,TY.Tfloat64): | |
709 case X(TY.Tbit,TY.Tfloat80): | |
710 case X(TY.Tbit,TY.Tcomplex32): | |
711 case X(TY.Tbit,TY.Tcomplex64): | |
712 case X(TY.Tbit,TY.Tcomplex80): | |
713 e = el_una(OPER.OPu8_16, TYM.TYuint, e); | |
714 fty = TY.Tuns32; | |
715 goto Lagain; | |
716 case X(Tbit,Timaginary32): | |
717 case X(Tbit,Timaginary64): | |
718 case X(Tbit,Timaginary80): | |
719 goto Lzero; | |
720 } | |
721 /* ============================= */ | |
722 | |
723 case X(TY.Tbool,TY.Tint8): | |
724 case X(TY.Tbool,TY.Tuns8): | |
725 goto Lpaint; | |
726 case X(TY.Tbool,TY.Tint16): | |
727 case X(TY.Tbool,TY.Tuns16): | |
728 case X(TY.Tbool,TY.Tint32): | |
729 case X(TY.Tbool,TY.Tuns32): | |
730 eop = OPER.OPu8_16; | |
731 goto Leop; | |
732 case X(TY.Tbool,TY.Tint64): | |
733 case X(TY.Tbool,TY.Tuns64): | |
734 case X(TY.Tbool,TY.Tfloat32): | |
735 case X(TY.Tbool,TY.Tfloat64): | |
736 case X(TY.Tbool,TY.Tfloat80): | |
737 case X(TY.Tbool,TY.Tcomplex32): | |
738 case X(TY.Tbool,TY.Tcomplex64): | |
739 case X(TY.Tbool,TY.Tcomplex80): | |
740 e = el_una(OPER.OPu8_16, TYM.TYuint, e); | |
741 fty = TY.Tuns32; | |
742 goto Lagain; | |
743 case X(TY.Tbool,TY.Timaginary32): | |
744 case X(TY.Tbool,TY.Timaginary64): | |
745 case X(TY.Tbool,TY.Timaginary80): | |
746 goto Lzero; | |
747 | |
748 /* ============================= */ | |
749 | |
750 case X(TY.Tint8,TY.Tuns8): | |
751 goto Lpaint; | |
752 case X(TY.Tint8,TY.Tint16): | |
753 case X(TY.Tint8,TY.Tuns16): | |
754 case X(TY.Tint8,TY.Tint32): | |
755 case X(TY.Tint8,TY.Tuns32): | |
756 eop = OPER.OPs8_16; | |
757 goto Leop; | |
758 case X(TY.Tint8,TY.Tint64): | |
759 case X(TY.Tint8,TY.Tuns64): | |
760 case X(TY.Tint8,TY.Tfloat32): | |
761 case X(TY.Tint8,TY.Tfloat64): | |
762 case X(TY.Tint8,TY.Tfloat80): | |
763 case X(TY.Tint8,TY.Tcomplex32): | |
764 case X(TY.Tint8,TY.Tcomplex64): | |
765 case X(TY.Tint8,TY.Tcomplex80): | |
766 e = el_una(OPER.OPs8_16, TYM.TYint, e); | |
767 fty = TY.Tint32; | |
768 goto Lagain; | |
769 case X(TY.Tint8,TY.Timaginary32): | |
770 case X(TY.Tint8,TY.Timaginary64): | |
771 case X(TY.Tint8,TY.Timaginary80): | |
772 goto Lzero; | |
773 | |
774 /* ============================= */ | |
775 | |
776 case X(TY.Tuns8,TY.Tint8): | |
777 goto Lpaint; | |
778 case X(TY.Tuns8,TY.Tint16): | |
779 case X(TY.Tuns8,TY.Tuns16): | |
780 case X(TY.Tuns8,TY.Tint32): | |
781 case X(TY.Tuns8,TY.Tuns32): | |
782 eop = OPER.OPu8_16; | |
783 goto Leop; | |
784 case X(TY.Tuns8,TY.Tint64): | |
785 case X(TY.Tuns8,TY.Tuns64): | |
786 case X(TY.Tuns8,TY.Tfloat32): | |
787 case X(TY.Tuns8,TY.Tfloat64): | |
788 case X(TY.Tuns8,TY.Tfloat80): | |
789 case X(TY.Tuns8,TY.Tcomplex32): | |
790 case X(TY.Tuns8,TY.Tcomplex64): | |
791 case X(TY.Tuns8,TY.Tcomplex80): | |
792 e = el_una(OPER.OPu8_16, TYM.TYuint, e); | |
793 fty = TY.Tuns32; | |
794 goto Lagain; | |
795 case X(TY.Tuns8,TY.Timaginary32): | |
796 case X(TY.Tuns8,TY.Timaginary64): | |
797 case X(TY.Tuns8,TY.Timaginary80): | |
798 goto Lzero; | |
799 | |
800 /* ============================= */ | |
801 | |
802 case X(TY.Tint16,TY.Tint8): | |
803 case X(TY.Tint16,TY.Tuns8): | |
804 eop = OPER.OP16_8; | |
805 goto Leop; | |
806 case X(TY.Tint16,TY.Tuns16): | |
807 goto Lpaint; | |
808 case X(TY.Tint16,TY.Tint32): | |
809 case X(TY.Tint16,TY.Tuns32): | |
810 eop = OPER.OPs16_32; | |
811 goto Leop; | |
812 case X(TY.Tint16,TY.Tint64): | |
813 case X(TY.Tint16,TY.Tuns64): | |
814 e = el_una(OPER.OPs16_32, TYM.TYint, e); | |
815 fty = TY.Tint32; | |
816 goto Lagain; | |
817 case X(TY.Tint16,TY.Tfloat32): | |
818 case X(TY.Tint16,TY.Tfloat64): | |
819 case X(TY.Tint16,TY.Tfloat80): | |
820 case X(TY.Tint16,TY.Tcomplex32): | |
821 case X(TY.Tint16,TY.Tcomplex64): | |
822 case X(TY.Tint16,TY.Tcomplex80): | |
823 e = el_una(OPER.OPs16_d, TYM.TYdouble, e); | |
824 fty = TY.Tfloat64; | |
825 goto Lagain; | |
826 case X(TY.Tint16,TY.Timaginary32): | |
827 case X(TY.Tint16,TY.Timaginary64): | |
828 case X(TY.Tint16,TY.Timaginary80): | |
829 goto Lzero; | |
830 | |
831 /* ============================= */ | |
832 | |
833 case X(TY.Tuns16,TY.Tint8): | |
834 case X(TY.Tuns16,TY.Tuns8): | |
835 eop = OPER.OP16_8; | |
836 goto Leop; | |
837 case X(TY.Tuns16,TY.Tint16): | |
838 goto Lpaint; | |
839 case X(TY.Tuns16,TY.Tint32): | |
840 case X(TY.Tuns16,TY.Tuns32): | |
841 eop = OPER.OPu16_32; | |
842 goto Leop; | |
843 case X(TY.Tuns16,TY.Tint64): | |
844 case X(TY.Tuns16,TY.Tuns64): | |
845 case X(TY.Tuns16,TY.Tfloat64): | |
846 case X(TY.Tuns16,TY.Tfloat32): | |
847 case X(TY.Tuns16,TY.Tfloat80): | |
848 case X(TY.Tuns16,TY.Tcomplex32): | |
849 case X(TY.Tuns16,TY.Tcomplex64): | |
850 case X(TY.Tuns16,TY.Tcomplex80): | |
851 e = el_una(OPER.OPu16_32, TYM.TYuint, e); | |
852 fty = TY.Tuns32; | |
853 goto Lagain; | |
854 case X(TY.Tuns16,TY.Timaginary32): | |
855 case X(TY.Tuns16,TY.Timaginary64): | |
856 case X(TY.Tuns16,TY.Timaginary80): | |
857 goto Lzero; | |
858 | |
859 /* ============================= */ | |
860 | |
861 case X(TY.Tint32,TY.Tint8): | |
862 case X(TY.Tint32,TY.Tuns8): | |
863 e = el_una(OPER.OP32_16, TYM.TYshort, e); | |
864 fty = TY.Tint16; | |
865 goto Lagain; | |
866 case X(TY.Tint32,TY.Tint16): | |
867 case X(TY.Tint32,TY.Tuns16): | |
868 eop = OPER.OP32_16; | |
869 goto Leop; | |
870 case X(TY.Tint32,TY.Tuns32): | |
871 goto Lpaint; | |
872 case X(TY.Tint32,TY.Tint64): | |
873 case X(TY.Tint32,TY.Tuns64): | |
874 eop = OPER.OPs32_64; | |
875 goto Leop; | |
876 case X(TY.Tint32,TY.Tfloat32): | |
877 case X(TY.Tint32,TY.Tfloat64): | |
878 case X(TY.Tint32,TY.Tfloat80): | |
879 case X(TY.Tint32,TY.Tcomplex32): | |
880 case X(TY.Tint32,TY.Tcomplex64): | |
881 case X(TY.Tint32,TY.Tcomplex80): | |
882 e = el_una(OPER.OPs32_d, TYM.TYdouble, e); | |
883 fty = TY.Tfloat64; | |
884 goto Lagain; | |
885 case X(TY.Tint32,TY.Timaginary32): | |
886 case X(TY.Tint32,TY.Timaginary64): | |
887 case X(TY.Tint32,TY.Timaginary80): | |
888 goto Lzero; | |
889 | |
890 /* ============================= */ | |
891 | |
892 case X(TY.Tuns32,TY.Tint8): | |
893 case X(TY.Tuns32,TY.Tuns8): | |
894 e = el_una(OPER.OP32_16, TYM.TYshort, e); | |
895 fty = TY.Tuns16; | |
896 goto Lagain; | |
897 case X(TY.Tuns32,TY.Tint16): | |
898 case X(TY.Tuns32,TY.Tuns16): | |
899 eop = OPER.OP32_16; | |
900 goto Leop; | |
901 case X(TY.Tuns32,TY.Tint32): | |
902 goto Lpaint; | |
903 case X(TY.Tuns32,TY.Tint64): | |
904 case X(TY.Tuns32,TY.Tuns64): | |
905 eop = OPER.OPu32_64; | |
906 goto Leop; | |
907 case X(TY.Tuns32,TY.Tfloat32): | |
908 case X(TY.Tuns32,TY.Tfloat64): | |
909 case X(TY.Tuns32,TY.Tfloat80): | |
910 case X(TY.Tuns32,TY.Tcomplex32): | |
911 case X(TY.Tuns32,TY.Tcomplex64): | |
912 case X(TY.Tuns32,TY.Tcomplex80): | |
913 e = el_una(OPER.OPu32_d, TYM.TYdouble, e); | |
914 fty = TY.Tfloat64; | |
915 goto Lagain; | |
916 case X(TY.Tuns32,TY.Timaginary32): | |
917 case X(TY.Tuns32,TY.Timaginary64): | |
918 case X(TY.Tuns32,TY.Timaginary80): | |
919 goto Lzero; | |
920 | |
921 /* ============================= */ | |
922 | |
923 case X(TY.Tint64,TY.Tint8): | |
924 case X(TY.Tint64,TY.Tuns8): | |
925 case X(TY.Tint64,TY.Tint16): | |
926 case X(TY.Tint64,TY.Tuns16): | |
927 e = el_una(OPER.OP64_32, TYM.TYint, e); | |
928 fty = TY.Tint32; | |
929 goto Lagain; | |
930 case X(TY.Tint64,TY.Tint32): | |
931 case X(TY.Tint64,TY.Tuns32): | |
932 eop = OPER.OP64_32; | |
933 goto Leop; | |
934 case X(TY.Tint64,TY.Tuns64): | |
935 goto Lpaint; | |
936 case X(TY.Tint64,TY.Tfloat32): | |
937 case X(TY.Tint64,TY.Tfloat64): | |
938 case X(TY.Tint64,TY.Tfloat80): | |
939 case X(TY.Tint64,TY.Tcomplex32): | |
940 case X(TY.Tint64,TY.Tcomplex64): | |
941 case X(TY.Tint64,TY.Tcomplex80): | |
942 e = el_una(OPER.OPs64_d, TYM.TYdouble, e); | |
943 fty = TY.Tfloat64; | |
944 goto Lagain; | |
945 case X(TY.Tint64,TY.Timaginary32): | |
946 case X(TY.Tint64,TY.Timaginary64): | |
947 case X(TY.Tint64,TY.Timaginary80): | |
948 goto Lzero; | |
949 | |
950 /* ============================= */ | |
951 | |
952 case X(TY.Tuns64,TY.Tint8): | |
953 case X(TY.Tuns64,TY.Tuns8): | |
954 case X(TY.Tuns64,TY.Tint16): | |
955 case X(TY.Tuns64,TY.Tuns16): | |
956 e = el_una(OPER.OP64_32, TYM.TYint, e); | |
957 fty = TY.Tint32; | |
958 goto Lagain; | |
959 case X(TY.Tuns64,TY.Tint32): | |
960 case X(TY.Tuns64,TY.Tuns32): | |
961 eop = OPER.OP64_32; | |
962 goto Leop; | |
963 case X(TY.Tuns64,TY.Tint64): | |
964 goto Lpaint; | |
965 case X(TY.Tuns64,TY.Tfloat32): | |
966 case X(TY.Tuns64,TY.Tfloat64): | |
967 case X(TY.Tuns64,TY.Tfloat80): | |
968 case X(TY.Tuns64,TY.Tcomplex32): | |
969 case X(TY.Tuns64,TY.Tcomplex64): | |
970 case X(TY.Tuns64,TY.Tcomplex80): | |
971 e = el_una(OPER.OPu64_d, TYM.TYdouble, e); | |
972 fty = TY.Tfloat64; | |
973 goto Lagain; | |
974 case X(TY.Tuns64,TY.Timaginary32): | |
975 case X(TY.Tuns64,TY.Timaginary64): | |
976 case X(TY.Tuns64,TY.Timaginary80): | |
977 goto Lzero; | |
978 | |
979 /* ============================= */ | |
980 | |
981 case X(TY.Tfloat32,TY.Tint8): | |
982 case X(TY.Tfloat32,TY.Tuns8): | |
983 case X(TY.Tfloat32,TY.Tint16): | |
984 case X(TY.Tfloat32,TY.Tuns16): | |
985 case X(TY.Tfloat32,TY.Tint32): | |
986 case X(TY.Tfloat32,TY.Tuns32): | |
987 case X(TY.Tfloat32,TY.Tint64): | |
988 case X(TY.Tfloat32,TY.Tuns64): | |
989 case X(TY.Tfloat32,TY.Tfloat80): | |
990 e = el_una(OPER.OPf_d, TYM.TYdouble, e); | |
991 fty = TY.Tfloat64; | |
992 goto Lagain; | |
993 case X(TY.Tfloat32,TY.Tfloat64): | |
994 eop = OPER.OPf_d; | |
995 goto Leop; | |
996 case X(TY.Tfloat32,TY.Timaginary32): | |
997 goto Lzero; | |
998 case X(TY.Tfloat32,TY.Timaginary64): | |
999 goto Lzero; | |
1000 case X(TY.Tfloat32,TY.Timaginary80): | |
1001 goto Lzero; | |
1002 case X(TY.Tfloat32,TY.Tcomplex32): | |
1003 case X(TY.Tfloat32,TY.Tcomplex64): | |
1004 case X(TY.Tfloat32,TY.Tcomplex80): | |
1005 e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYifloat,0),e); | |
1006 fty = TY.Tcomplex32; | |
1007 goto Lagain; | |
1008 | |
1009 /* ============================= */ | |
1010 | |
1011 case X(TY.Tfloat64,TY.Tint8): | |
1012 case X(TY.Tfloat64,TY.Tuns8): | |
1013 e = el_una(OPER.OPd_s16, TYM.TYshort, e); | |
1014 fty = TY.Tint16; | |
1015 goto Lagain; | |
1016 case X(TY.Tfloat64,TY.Tint16): | |
1017 eop = OPER.OPd_s16; | |
1018 goto Leop; | |
1019 case X(TY.Tfloat64,TY.Tuns16): | |
1020 eop = OPER.OPd_u16; | |
1021 goto Leop; | |
1022 case X(TY.Tfloat64,TY.Tint32): | |
1023 eop = OPER.OPd_s32; | |
1024 goto Leop; | |
1025 case X(TY.Tfloat64,TY.Tuns32): | |
1026 eop = OPER.OPd_u32; | |
1027 goto Leop; | |
1028 case X(TY.Tfloat64,TY.Tint64): | |
1029 eop = OPER.OPd_s64; | |
1030 goto Leop; | |
1031 case X(TY.Tfloat64,TY.Tuns64): | |
1032 eop = OPER.OPd_u64; | |
1033 goto Leop; | |
1034 case X(TY.Tfloat64,TY.Tfloat32): | |
1035 eop = OPER.OPd_f; | |
1036 goto Leop; | |
1037 case X(TY.Tfloat64,TY.Tfloat80): | |
1038 eop = OPER.OPd_ld; | |
1039 goto Leop; | |
1040 case X(TY.Tfloat64,TY.Timaginary32): | |
1041 goto Lzero; | |
1042 case X(TY.Tfloat64,TY.Timaginary64): | |
1043 goto Lzero; | |
1044 case X(TY.Tfloat64,TY.Timaginary80): | |
1045 goto Lzero; | |
1046 case X(TY.Tfloat64,TY.Tcomplex32): | |
1047 case X(TY.Tfloat64,TY.Tcomplex64): | |
1048 case X(TY.Tfloat64,TY.Tcomplex80): | |
1049 e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYidouble,0),e); | |
1050 fty = TY.Tcomplex64; | |
1051 goto Lagain; | |
1052 | |
1053 /* ============================= */ | |
1054 | |
1055 case X(TY.Tfloat80,TY.Tint8): | |
1056 case X(TY.Tfloat80,TY.Tuns8): | |
1057 case X(TY.Tfloat80,TY.Tint16): | |
1058 case X(TY.Tfloat80,TY.Tuns16): | |
1059 case X(TY.Tfloat80,TY.Tint32): | |
1060 case X(TY.Tfloat80,TY.Tuns32): | |
1061 case X(TY.Tfloat80,TY.Tint64): | |
1062 case X(TY.Tfloat80,TY.Tfloat32): | |
1063 e = el_una(OPER.OPld_d, TYM.TYdouble, e); | |
1064 fty = TY.Tfloat64; | |
1065 goto Lagain; | |
1066 case X(TY.Tfloat80,TY.Tuns64): | |
1067 eop = OPER.OPld_u64; | |
1068 goto Leop; | |
1069 case X(TY.Tfloat80,TY.Tfloat64): | |
1070 eop = OPER.OPld_d; | |
1071 goto Leop; | |
1072 case X(TY.Tfloat80,TY.Timaginary32): | |
1073 goto Lzero; | |
1074 case X(TY.Tfloat80,TY.Timaginary64): | |
1075 goto Lzero; | |
1076 case X(TY.Tfloat80,TY.Timaginary80): | |
1077 goto Lzero; | |
1078 case X(TY.Tfloat80,TY.Tcomplex32): | |
1079 case X(TY.Tfloat80,TY.Tcomplex64): | |
1080 case X(TY.Tfloat80,TY.Tcomplex80): | |
1081 e = el_bin(OPER.OPadd,TYM.TYcldouble,e,el_long(TYM.TYildouble,0)); | |
1082 fty = TY.Tcomplex80; | |
1083 goto Lagain; | |
1084 | |
1085 /* ============================= */ | |
1086 | |
1087 case X(TY.Timaginary32,TY.Tint8): | |
1088 case X(TY.Timaginary32,TY.Tuns8): | |
1089 case X(TY.Timaginary32,TY.Tint16): | |
1090 case X(TY.Timaginary32,TY.Tuns16): | |
1091 case X(TY.Timaginary32,TY.Tint32): | |
1092 case X(TY.Timaginary32,TY.Tuns32): | |
1093 case X(TY.Timaginary32,TY.Tint64): | |
1094 case X(TY.Timaginary32,TY.Tuns64): | |
1095 case X(TY.Timaginary32,TY.Tfloat32): | |
1096 case X(TY.Timaginary32,TY.Tfloat64): | |
1097 case X(TY.Timaginary32,TY.Tfloat80): | |
1098 goto Lzero; | |
1099 case X(TY.Timaginary32,TY.Timaginary64): | |
1100 eop = OPER.OPf_d; | |
1101 goto Leop; | |
1102 case X(TY.Timaginary32,TY.Timaginary80): | |
1103 e = el_una(OPER.OPf_d, TYM.TYidouble, e); | |
1104 fty = TY.Timaginary64; | |
1105 goto Lagain; | |
1106 case X(TY.Timaginary32,TY.Tcomplex32): | |
1107 case X(TY.Timaginary32,TY.Tcomplex64): | |
1108 case X(TY.Timaginary32,TY.Tcomplex80): | |
1109 e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYfloat,0),e); | |
1110 fty = TY.Tcomplex32; | |
1111 goto Lagain; | |
1112 | |
1113 /* ============================= */ | |
1114 | |
1115 case X(TY.Timaginary64,TY.Tint8): | |
1116 case X(TY.Timaginary64,TY.Tuns8): | |
1117 case X(TY.Timaginary64,TY.Tint16): | |
1118 case X(TY.Timaginary64,TY.Tuns16): | |
1119 case X(TY.Timaginary64,TY.Tint32): | |
1120 case X(TY.Timaginary64,TY.Tuns32): | |
1121 case X(TY.Timaginary64,TY.Tint64): | |
1122 case X(TY.Timaginary64,TY.Tuns64): | |
1123 case X(TY.Timaginary64,TY.Tfloat32): | |
1124 case X(TY.Timaginary64,TY.Tfloat64): | |
1125 case X(TY.Timaginary64,TY.Tfloat80): | |
1126 goto Lzero; | |
1127 case X(TY.Timaginary64,TY.Timaginary32): | |
1128 eop = OPER.OPd_f; | |
1129 goto Leop; | |
1130 case X(TY.Timaginary64,TY.Timaginary80): | |
1131 eop = OPER.OPd_ld; | |
1132 goto Leop; | |
1133 case X(TY.Timaginary64,TY.Tcomplex32): | |
1134 case X(TY.Timaginary64,TY.Tcomplex64): | |
1135 case X(TY.Timaginary64,TY.Tcomplex80): | |
1136 e = el_bin(OPER.OPadd, TYM.TYcdouble, el_long(TYM.TYdouble,0), e); | |
1137 fty = TY.Tcomplex64; | |
1138 goto Lagain; | |
1139 | |
1140 /* ============================= */ | |
1141 | |
1142 case X(TY.Timaginary80,TY.Tint8): | |
1143 case X(TY.Timaginary80,TY.Tuns8): | |
1144 case X(TY.Timaginary80,TY.Tint16): | |
1145 case X(TY.Timaginary80,TY.Tuns16): | |
1146 case X(TY.Timaginary80,TY.Tint32): | |
1147 case X(TY.Timaginary80,TY.Tuns32): | |
1148 case X(TY.Timaginary80,TY.Tint64): | |
1149 case X(TY.Timaginary80,TY.Tuns64): | |
1150 case X(TY.Timaginary80,TY.Tfloat32): | |
1151 case X(TY.Timaginary80,TY.Tfloat64): | |
1152 case X(TY.Timaginary80,TY.Tfloat80): | |
1153 goto Lzero; | |
1154 case X(TY.Timaginary80,TY.Timaginary32): | |
1155 e = el_una(OPER.OPf_d, TYM.TYidouble, e); | |
1156 fty = TY.Timaginary64; | |
1157 goto Lagain; | |
1158 case X(TY.Timaginary80,TY.Timaginary64): | |
1159 eop = OPER.OPld_d; | |
1160 goto Leop; | |
1161 case X(TY.Timaginary80,TY.Tcomplex32): | |
1162 case X(TY.Timaginary80,TY.Tcomplex64): | |
1163 case X(TY.Timaginary80,TY.Tcomplex80): | |
1164 e = el_bin(OPER.OPadd, TYM.TYcldouble, el_long(TYM.TYldouble,0), e); | |
1165 fty = TY.Tcomplex80; | |
1166 goto Lagain; | |
1167 | |
1168 /* ============================= */ | |
1169 | |
1170 case X(TY.Tcomplex32,TY.Tint8): | |
1171 case X(TY.Tcomplex32,TY.Tuns8): | |
1172 case X(TY.Tcomplex32,TY.Tint16): | |
1173 case X(TY.Tcomplex32,TY.Tuns16): | |
1174 case X(TY.Tcomplex32,TY.Tint32): | |
1175 case X(TY.Tcomplex32,TY.Tuns32): | |
1176 case X(TY.Tcomplex32,TY.Tint64): | |
1177 case X(TY.Tcomplex32,TY.Tuns64): | |
1178 case X(TY.Tcomplex32,TY.Tfloat32): | |
1179 case X(TY.Tcomplex32,TY.Tfloat64): | |
1180 case X(TY.Tcomplex32,TY.Tfloat80): | |
1181 e = el_una(OPER.OPc_r, TYM.TYfloat, e); | |
1182 fty = TY.Tfloat32; | |
1183 goto Lagain; | |
1184 case X(TY.Tcomplex32,TY.Timaginary32): | |
1185 case X(TY.Tcomplex32,TY.Timaginary64): | |
1186 case X(TY.Tcomplex32,TY.Timaginary80): | |
1187 e = el_una(OPER.OPc_i, TYM.TYifloat, e); | |
1188 fty = TY.Timaginary32; | |
1189 goto Lagain; | |
1190 case X(TY.Tcomplex32,TY.Tcomplex64): | |
1191 case X(TY.Tcomplex32,TY.Tcomplex80): | |
1192 e = el_una(OPER.OPf_d, TYM.TYcdouble, e); | |
1193 fty = TY.Tcomplex64; | |
1194 goto Lagain; | |
1195 | |
1196 /* ============================= */ | |
1197 | |
1198 case X(TY.Tcomplex64,TY.Tint8): | |
1199 case X(TY.Tcomplex64,TY.Tuns8): | |
1200 case X(TY.Tcomplex64,TY.Tint16): | |
1201 case X(TY.Tcomplex64,TY.Tuns16): | |
1202 case X(TY.Tcomplex64,TY.Tint32): | |
1203 case X(TY.Tcomplex64,TY.Tuns32): | |
1204 case X(TY.Tcomplex64,TY.Tint64): | |
1205 case X(TY.Tcomplex64,TY.Tuns64): | |
1206 case X(TY.Tcomplex64,TY.Tfloat32): | |
1207 case X(TY.Tcomplex64,TY.Tfloat64): | |
1208 case X(TY.Tcomplex64,TY.Tfloat80): | |
1209 e = el_una(OPER.OPc_r, TYM.TYdouble, e); | |
1210 fty = TY.Tfloat64; | |
1211 goto Lagain; | |
1212 case X(TY.Tcomplex64,TY.Timaginary32): | |
1213 case X(TY.Tcomplex64,TY.Timaginary64): | |
1214 case X(TY.Tcomplex64,TY.Timaginary80): | |
1215 e = el_una(OPER.OPc_i, TYM.TYidouble, e); | |
1216 fty = TY.Timaginary64; | |
1217 goto Lagain; | |
1218 case X(TY.Tcomplex64,TY.Tcomplex32): | |
1219 eop = OPER.OPd_f; | |
1220 goto Leop; | |
1221 case X(TY.Tcomplex64,TY.Tcomplex80): | |
1222 eop = OPER.OPd_ld; | |
1223 goto Leop; | |
1224 | |
1225 /* ============================= */ | |
1226 | |
1227 case X(TY.Tcomplex80,TY.Tint8): | |
1228 case X(TY.Tcomplex80,TY.Tuns8): | |
1229 case X(TY.Tcomplex80,TY.Tint16): | |
1230 case X(TY.Tcomplex80,TY.Tuns16): | |
1231 case X(TY.Tcomplex80,TY.Tint32): | |
1232 case X(TY.Tcomplex80,TY.Tuns32): | |
1233 case X(TY.Tcomplex80,TY.Tint64): | |
1234 case X(TY.Tcomplex80,TY.Tuns64): | |
1235 case X(TY.Tcomplex80,TY.Tfloat32): | |
1236 case X(TY.Tcomplex80,TY.Tfloat64): | |
1237 case X(TY.Tcomplex80,TY.Tfloat80): | |
1238 e = el_una(OPER.OPc_r, TYM.TYldouble, e); | |
1239 fty = TY.Tfloat80; | |
1240 goto Lagain; | |
1241 case X(TY.Tcomplex80,TY.Timaginary32): | |
1242 case X(TY.Tcomplex80,TY.Timaginary64): | |
1243 case X(TY.Tcomplex80,TY.Timaginary80): | |
1244 e = el_una(OPER.OPc_i, TYM.TYildouble, e); | |
1245 fty = TY.Timaginary80; | |
1246 goto Lagain; | |
1247 case X(TY.Tcomplex80,TY.Tcomplex32): | |
1248 case X(TY.Tcomplex80,TY.Tcomplex64): | |
1249 e = el_una(OPER.OPld_d, TYM.TYcdouble, e); | |
1250 fty = TY.Tcomplex64; | |
1251 goto Lagain; | |
1252 | |
1253 /* ============================= */ | |
1254 | |
1255 default: | |
1256 if (fty == tty) | |
1257 goto Lpaint; | |
1258 //dump(0); | |
79 | 1259 //writef("fty = %d, tty = %d, %d\n", fty, tty, t.ty); |
1260 error("e2ir: cannot cast %s of type %s to type %s", e1.toChars(), e1.type.toChars(), t.toChars()); | |
72 | 1261 goto Lzero; |
1262 | |
1263 Lzero: | |
1264 e = el_long(ttym, 0); | |
1265 break; | |
1266 | |
1267 Lpaint: | |
1268 e.Ety = ttym; | |
1269 break; | |
1270 | |
1271 Leop: | |
1272 e = el_una(eop, ttym, e); | |
1273 break; | |
1274 } | |
1275 Lret: | |
1276 // Adjust for any type paints | |
1277 t = type.toBasetype(); | |
1278 e.Ety = t.totym(); | |
1279 | |
1280 el_setLoc(e,loc); | |
0 | 1281 return e; |
1282 } | |
1283 | |
72 | 1284 override Identifier opId() |
0 | 1285 { |
1286 return Id.cast_; | |
1287 } | |
1288 } | |
1289 |