Mercurial > projects > ddmd
diff dmd/CastExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 832f71e6f96c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/CastExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,1201 @@ +module dmd.CastExp; + +import dmd.Expression; +import dmd.TY; +import dmd.TypeStruct; +import dmd.TypeExp; +import dmd.DotIdExp; +import dmd.CallExp; +import dmd.Global; +import dmd.Id; +import dmd.Identifier; +import dmd.BinExp; +import dmd.backend.elem; +import dmd.UnaExp; +import dmd.VarExp; +import dmd.Token; +import dmd.VarDeclaration; +import dmd.InterState; +import dmd.MATCH; +import dmd.Type; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.Scope; +import dmd.IntRange; +import dmd.IRState; +import dmd.ArrayTypes; +import dmd.HdrGenState; +import dmd.MOD; +import dmd.TOK; +import dmd.WANT; +import dmd.ClassDeclaration; + +import dmd.Optimize; +import dmd.PREC; +import dmd.Cast; + +import dmd.backend.Util; +import dmd.expression.Util; +import dmd.backend.TYM; +import dmd.backend.OPER; +import dmd.codegen.Util; +import dmd.backend.RTLSYM; + +class CastExp : UnaExp +{ + // Possible to cast to one type while painting to another type + Type to; // type to cast to + MOD mod; // MODxxxxx + + this(Loc loc, Expression e, Type t) + { + super(loc, TOK.TOKcast, CastExp.sizeof, e); + to = t; + this.mod = cast(MOD)~0; + } + + this(Loc loc, Expression e, MOD mod) + { + super(loc, TOK.TOKcast, CastExp.sizeof, e); + to = null; + this.mod = mod; + } + + Expression syntaxCopy() + { + return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy()) + : new CastExp(loc, e1.syntaxCopy(), mod); + } + + Expression semantic(Scope sc) + { + Expression e; + BinExp b; + UnaExp u; + +version (LOGSEMANTIC) { + printf("CastExp.semantic('%s')\n", toChars()); +} + + //static int x; assert(++x < 10); + + if (type) + return this; + super.semantic(sc); + if (e1.type) // if not a tuple + { + e1 = resolveProperties(sc, e1); + + if (!to) + { + /* Handle cast(const) and cast(immutable), etc. + */ + to = e1.type.castMod(mod); + } + else + to = to.semantic(loc, sc); + + if (!to.equals(e1.type)) + { + e = op_overload(sc); + if (e) + { + return e.implicitCastTo(sc, to); + } + } + + Type t1b = e1.type.toBasetype(); + Type tob = to.toBasetype(); + if (tob.ty == TY.Tstruct && + !tob.equals(t1b) && + (cast(TypeStruct)tob).sym.search(Loc(0), Id.call, 0) + ) + { + /* Look to replace: + * cast(S)t + * with: + * S(t) + */ + + // Rewrite as to.call(e1) + e = new TypeExp(loc, to); + e = new DotIdExp(loc, e, Id.call); + e = new CallExp(loc, e, e1); + e = e.semantic(sc); + return e; + } + } + else if (!to) + { error("cannot cast tuple"); + to = Type.terror; + } + + if (global.params.safe && !sc.module_.safe && !sc.intypeof) + { // Disallow unsafe casts + Type tob = to.toBasetype(); + Type t1b = e1.type.toBasetype(); + if (!t1b.isMutable() && tob.isMutable()) + { // Cast not mutable to mutable + Lunsafe: + error("cast from %s to %s not allowed in safe mode", e1.type.toChars(), to.toChars()); + } + else if (t1b.isShared() && !tob.isShared()) + // Cast away shared + goto Lunsafe; + else if (tob.ty == TY.Tpointer) + { if (t1b.ty != TY.Tpointer) + goto Lunsafe; + Type tobn = tob.nextOf().toBasetype(); + Type t1bn = t1b.nextOf().toBasetype(); + + if (!t1bn.isMutable() && tobn.isMutable()) + // Cast away pointer to not mutable + goto Lunsafe; + + if (t1bn.isShared() && !tobn.isShared()) + // Cast away pointer to shared + goto Lunsafe; + + if (tobn.isTypeBasic() && tobn.size() < t1bn.size()) { + // Allow things like casting a long* to an int* + ; + } else if (tobn.ty != TY.Tvoid) { + // Cast to a pointer other than void* + goto Lunsafe; + } + } + + // BUG: Check for casting array types, such as void[] to int*[] + } + + e = e1.castTo(sc, to); + return e; + } + + MATCH implicitConvTo(Type t) + { + static if (false) { + printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); + } + MATCH result = type.implicitConvTo(t); + + if (result == MATCHnomatch) + { + if (t.isintegral() && + e1.type.isintegral() && + e1.implicitConvTo(t) != MATCHnomatch) + result = MATCHconvert; + else + result = Expression.implicitConvTo(t); + } + return result; + } + + IntRange getIntRange() + { + assert(false); + } + + Expression optimize(int result) + { + //printf("CastExp.optimize(result = %d) %s\n", result, toChars()); + //printf("from %s to %s\n", type.toChars(), to.toChars()); + //printf("from %s\n", type.toChars()); + //printf("e1.type %s\n", e1.type.toChars()); + //printf("type = %p\n", type); + assert(type); + TOK op1 = e1.op; + + Expression e1old = e1; + e1 = e1.optimize(result); + e1 = fromConstInitializer(result, e1); + + if (e1 == e1old && + e1.op == TOK.TOKarrayliteral && + type.toBasetype().ty == TY.Tpointer && + e1.type.toBasetype().ty != TY.Tsarray) + { + // Casting this will result in the same expression, and + // infinite loop because of Expression.implicitCastTo() + return this; // no change + } + + if ((e1.op == TOK.TOKstring || e1.op == TOK.TOKarrayliteral) && + (type.ty == TY.Tpointer || type.ty == TY.Tarray) && + e1.type.nextOf().size() == type.nextOf().size() + ) + { + Expression e = e1.castTo(null, type); + +static if (false) { + printf(" returning1 %s\n", e.toChars()); +} + return e; + } + + if (e1.op == TOK.TOKstructliteral && + e1.type.implicitConvTo(type) >= MATCH.MATCHconst) + { + e1.type = type; +static if (false) { + printf(" returning2 %s\n", e1.toChars()); +} + return e1; + } + + /* The first test here is to prevent infinite loops + */ + if (op1 != TOK.TOKarrayliteral && e1.op == TOK.TOKarrayliteral) + return e1.castTo(null, to); + if (e1.op == TOK.TOKnull && + (type.ty == TY.Tpointer || type.ty == TY.Tclass || type.ty == TY.Tarray)) + { + e1.type = type; +static if (false) { + printf(" returning3 %s\n", e1.toChars()); +} + return e1; + } + + if (result & WANT.WANTflags && type.ty == TY.Tclass && e1.type.ty == TY.Tclass) + { + // See if we can remove an unnecessary cast + ClassDeclaration cdfrom; + ClassDeclaration cdto; + int offset; + + cdfrom = e1.type.isClassHandle(); + cdto = type.isClassHandle(); + if (cdto.isBaseOf(cdfrom, &offset) && offset == 0) + { + e1.type = type; +static if (false) { + printf(" returning4 %s\n", e1.toChars()); +} + return e1; + } + } + + // We can convert 'head const' to mutable + if (to.constOf().equals(e1.type.constOf())) + // if (to.constConv(e1.type) >= MATCHconst) + { + e1.type = type; +static if (false) { + printf(" returning5 %s\n", e1.toChars()); +} + return e1; + } + + Expression e; + + if (e1.isConst()) + { + if (e1.op == TOK.TOKsymoff) + { + if (type.size() == e1.type.size() && + type.toBasetype().ty != TY.Tsarray) + { + e1.type = type; + return e1; + } + return this; + } + if (to.toBasetype().ty == TY.Tvoid) + e = this; + else + e = Cast(type, to, e1); + } + else + e = this; +static if (false) { + printf(" returning6 %s\n", e.toChars()); +} + return e; + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + bool checkSideEffect(int flag) + { + assert(false); + } + + void checkEscape() + { + Type tb = type.toBasetype(); + if (tb.ty == TY.Tarray && e1.op == TOK.TOKvar && e1.type.toBasetype().ty ==TY.Tsarray) + { + VarExp ve = cast(VarExp)e1; + VarDeclaration v = ve.var.isVarDeclaration(); + if (v) + { + if (!v.isDataseg() && !v.isParameter()) + error("escaping reference to local %s", v.toChars()); + } + } + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("cast("); + version (DMDV1) { + to.toCBuffer(buf, null, hgs); + } else { + if (to) + to.toCBuffer(buf, null, hgs); + else + { + switch (mod) + { + case MODundefined: + break; + case MODconst: + buf.writestring(Token.tochars[TOKconst]); + break; + case MODinvariant: + buf.writestring(Token.tochars[TOKimmutable]); + break; + case MODshared: + buf.writestring(Token.tochars[TOKshared]); + break; + case MODshared | MODconst: + buf.writestring(Token.tochars[TOKshared]); + buf.writeByte(' '); + buf.writestring(Token.tochars[TOKconst]); + break; + default: + assert(0); + } + } + } + buf.writeByte(')'); + expToCBuffer(buf, hgs, e1, precedence[op]); + } + + void buildArrayIdent(OutBuffer buf, Expressions arguments) + { + assert(false); + } + + Expression buildArrayLoop(Arguments fparams) + { + assert(false); + } + + static int X(int fty, int tty) { + return ((fty) * TY.TMAX + (tty)); + } + + elem* toElem(IRState* irs) + { + elem* e; + TY fty; + TY tty; + tym_t ftym; + tym_t ttym; + OPER eop; + Type t; + Type tfrom; + +static if (false) { + printf("CastExp::toElem()\n"); + print(); + printf("\tfrom: %s\n", e1.type.toChars()); + printf("\tto : %s\n", to.toChars()); +} + + e = e1.toElem(irs); + tfrom = e1.type.toBasetype(); + t = to.toBasetype(); // skip over typedef's + if (t.equals(tfrom)) + goto Lret; + + fty = tfrom.ty; + //printf("fty = %d\n", fty); + tty = t.ty; + + if (tty == TY.Tpointer && fty == TY.Tarray +///static if (false) { +/// && (t.next.ty == Tvoid || t.next.equals(e1.type.next)) +///} + ) + { + if (e.Eoper == OPER.OPvar) + { + // e1 . *(&e1 + 4) + e = el_una(OPER.OPaddr, TYM.TYnptr, e); + e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, 4)); + e = el_una(OPER.OPind, t.totym(),e); + } + else + { + // e1 . (unsigned)(e1 >> 32) + e = el_bin(OPER.OPshr, TYM.TYullong, e, el_long(TYM.TYint, 32)); + e = el_una(OPER.OP64_32, t.totym(), e); + } + goto Lret; + } + + if (tty == TY.Tpointer && fty == TY.Tsarray +///static if (false) { +/// && (t.next.ty == Tvoid || t.next.equals(e1.type.next)) +///} + ) + { + // e1 . &e1 + e = el_una(OPER.OPaddr, TYM.TYnptr, e); + goto Lret; + } + + // Convert from static array to dynamic array + if (tty == TY.Tarray && fty == TY.Tsarray) + { + e = sarray_toDarray(loc, tfrom, t, e); + goto Lret; + } + + // Convert from dynamic array to dynamic array + if (tty == TY.Tarray && fty == TY.Tarray) + { + uint fsize = cast(uint)tfrom.nextOf().size(); + uint tsize = cast(uint)t.nextOf().size(); + + if (fsize != tsize) + { + elem* ep = el_params(e, el_long(TYM.TYint, fsize), el_long(TYM.TYint, tsize), null); + e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCAST]), ep); + } + goto Lret; + } + +static if (false) { + // Convert from dynamic array string literal to static array + if (tty == TY.Tsarray && fty == TY.Tarray && e1.op == TOK.TOKstring) + { + goto Lret; // treat as a 'paint' + } +} + + // Casting from base class to derived class requires a runtime check + if (fty == TY.Tclass && tty == TY.Tclass) + { + // Casting from derived class to base class is a no-op + ClassDeclaration cdfrom; + ClassDeclaration cdto; + int offset; + int rtl = RTLSYM.RTLSYM_DYNAMIC_CAST; + + cdfrom = tfrom.isClassHandle(); + cdto = t.isClassHandle(); + if (cdfrom.isInterfaceDeclaration()) + { + rtl = RTLSYM.RTLSYM_INTERFACE_CAST; + if (cdfrom.isCPPinterface()) + { + if (cdto.isCPPinterface()) + { + /* Casting from a C++ interface to a C++ interface + * is always a 'paint' operation + */ + goto Lret; // no-op + } + + /* Casting from a C++ interface to a class + * always results in null because there is no runtime + * information available to do it. + * + * Casting from a C++ interface to a non-C++ interface + * always results in null because there's no way one + * can be derived from the other. + */ + e = el_bin(OPER.OPcomma, TYM.TYnptr, e, el_long(TYM.TYnptr, 0)); + goto Lret; + } + } + if (cdto.isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME) + { + /* The offset from cdfrom=>cdto is known at compile time. + */ + + //printf("offset = %d\n", offset); + if (offset) + { + /* Rewrite cast as (e ? e + offset : null) + */ + elem* etmp; + elem* ex; + + if (e1.op == TOK.TOKthis) + { + // Assume 'this' is never null, so skip null check + e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset)); + } + else + { + etmp = el_same(&e); + ex = el_bin(OPER.OPadd, TYM.TYnptr, etmp, el_long(TYM.TYint, offset)); + ex = el_bin(OPER.OPcolon, TYM.TYnptr, ex, el_long(TYM.TYnptr, 0)); + e = el_bin(OPER.OPcond, TYM.TYnptr, e, ex); + } + } + goto Lret; // no-op + } + + /* The offset from cdfrom=>cdto can only be determined at runtime. + */ + elem* ep; + + ep = el_param(el_ptr(cdto.toSymbol()), e); + e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[rtl]), ep); + goto Lret; + } + + ftym = e.Ety; + ttym = t.totym(); + if (ftym == ttym) + goto Lret; + + switch (tty) + { + case TY.Tpointer: + if (fty == TY.Tdelegate) + goto Lpaint; + tty = TY.Tuns32; + break; + + case TY.Tchar: + tty = TY.Tuns8; + break; + case TY.Twchar: + tty = TY.Tuns16; + break; + case TY.Tdchar: + tty = TY.Tuns32; + break; + case TY.Tvoid: + goto Lpaint; + + case TY.Tbool: + { + // Construct e?true:false + elem* eq; + + e = el_una(OPER.OPbool, ttym, e); + goto Lret; + } + + default: + break; /// + } + + switch (fty) + { + case TY.Tpointer: fty = TY.Tuns32; break; + case TY.Tchar: fty = TY.Tuns8; break; + case TY.Twchar: fty = TY.Tuns16; break; + case TY.Tdchar: fty = TY.Tuns32; break; + default: break; /// + } + + Lagain: + switch (X(fty,tty)) + { +static if (false) { + case X(TY.Tbit,TY.Tint8): + case X(TY.Tbit,TY.Tuns8): + goto Lpaint; + case X(TY.Tbit,TY.Tint16): + case X(TY.Tbit,TY.Tuns16): + case X(TY.Tbit,TY.Tint32): + case X(TY.Tbit,TY.Tuns32): + eop = OPu8_16; + goto Leop; + case X(TY.Tbit,TY.Tint64): + case X(TY.Tbit,TY.Tuns64): + case X(TY.Tbit,TY.Tfloat32): + case X(TY.Tbit,TY.Tfloat64): + case X(TY.Tbit,TY.Tfloat80): + case X(TY.Tbit,TY.Tcomplex32): + case X(TY.Tbit,TY.Tcomplex64): + case X(TY.Tbit,TY.Tcomplex80): + e = el_una(OPER.OPu8_16, TYM.TYuint, e); + fty = TY.Tuns32; + goto Lagain; + case X(Tbit,Timaginary32): + case X(Tbit,Timaginary64): + case X(Tbit,Timaginary80): + goto Lzero; +} + /* ============================= */ + + case X(TY.Tbool,TY.Tint8): + case X(TY.Tbool,TY.Tuns8): + goto Lpaint; + case X(TY.Tbool,TY.Tint16): + case X(TY.Tbool,TY.Tuns16): + case X(TY.Tbool,TY.Tint32): + case X(TY.Tbool,TY.Tuns32): + eop = OPER.OPu8_16; + goto Leop; + case X(TY.Tbool,TY.Tint64): + case X(TY.Tbool,TY.Tuns64): + case X(TY.Tbool,TY.Tfloat32): + case X(TY.Tbool,TY.Tfloat64): + case X(TY.Tbool,TY.Tfloat80): + case X(TY.Tbool,TY.Tcomplex32): + case X(TY.Tbool,TY.Tcomplex64): + case X(TY.Tbool,TY.Tcomplex80): + e = el_una(OPER.OPu8_16, TYM.TYuint, e); + fty = TY.Tuns32; + goto Lagain; + case X(TY.Tbool,TY.Timaginary32): + case X(TY.Tbool,TY.Timaginary64): + case X(TY.Tbool,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tint8,TY.Tuns8): + goto Lpaint; + case X(TY.Tint8,TY.Tint16): + case X(TY.Tint8,TY.Tuns16): + case X(TY.Tint8,TY.Tint32): + case X(TY.Tint8,TY.Tuns32): + eop = OPER.OPs8_16; + goto Leop; + case X(TY.Tint8,TY.Tint64): + case X(TY.Tint8,TY.Tuns64): + case X(TY.Tint8,TY.Tfloat32): + case X(TY.Tint8,TY.Tfloat64): + case X(TY.Tint8,TY.Tfloat80): + case X(TY.Tint8,TY.Tcomplex32): + case X(TY.Tint8,TY.Tcomplex64): + case X(TY.Tint8,TY.Tcomplex80): + e = el_una(OPER.OPs8_16, TYM.TYint, e); + fty = TY.Tint32; + goto Lagain; + case X(TY.Tint8,TY.Timaginary32): + case X(TY.Tint8,TY.Timaginary64): + case X(TY.Tint8,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tuns8,TY.Tint8): + goto Lpaint; + case X(TY.Tuns8,TY.Tint16): + case X(TY.Tuns8,TY.Tuns16): + case X(TY.Tuns8,TY.Tint32): + case X(TY.Tuns8,TY.Tuns32): + eop = OPER.OPu8_16; + goto Leop; + case X(TY.Tuns8,TY.Tint64): + case X(TY.Tuns8,TY.Tuns64): + case X(TY.Tuns8,TY.Tfloat32): + case X(TY.Tuns8,TY.Tfloat64): + case X(TY.Tuns8,TY.Tfloat80): + case X(TY.Tuns8,TY.Tcomplex32): + case X(TY.Tuns8,TY.Tcomplex64): + case X(TY.Tuns8,TY.Tcomplex80): + e = el_una(OPER.OPu8_16, TYM.TYuint, e); + fty = TY.Tuns32; + goto Lagain; + case X(TY.Tuns8,TY.Timaginary32): + case X(TY.Tuns8,TY.Timaginary64): + case X(TY.Tuns8,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tint16,TY.Tint8): + case X(TY.Tint16,TY.Tuns8): + eop = OPER.OP16_8; + goto Leop; + case X(TY.Tint16,TY.Tuns16): + goto Lpaint; + case X(TY.Tint16,TY.Tint32): + case X(TY.Tint16,TY.Tuns32): + eop = OPER.OPs16_32; + goto Leop; + case X(TY.Tint16,TY.Tint64): + case X(TY.Tint16,TY.Tuns64): + e = el_una(OPER.OPs16_32, TYM.TYint, e); + fty = TY.Tint32; + goto Lagain; + case X(TY.Tint16,TY.Tfloat32): + case X(TY.Tint16,TY.Tfloat64): + case X(TY.Tint16,TY.Tfloat80): + case X(TY.Tint16,TY.Tcomplex32): + case X(TY.Tint16,TY.Tcomplex64): + case X(TY.Tint16,TY.Tcomplex80): + e = el_una(OPER.OPs16_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tint16,TY.Timaginary32): + case X(TY.Tint16,TY.Timaginary64): + case X(TY.Tint16,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tuns16,TY.Tint8): + case X(TY.Tuns16,TY.Tuns8): + eop = OPER.OP16_8; + goto Leop; + case X(TY.Tuns16,TY.Tint16): + goto Lpaint; + case X(TY.Tuns16,TY.Tint32): + case X(TY.Tuns16,TY.Tuns32): + eop = OPER.OPu16_32; + goto Leop; + case X(TY.Tuns16,TY.Tint64): + case X(TY.Tuns16,TY.Tuns64): + case X(TY.Tuns16,TY.Tfloat64): + case X(TY.Tuns16,TY.Tfloat32): + case X(TY.Tuns16,TY.Tfloat80): + case X(TY.Tuns16,TY.Tcomplex32): + case X(TY.Tuns16,TY.Tcomplex64): + case X(TY.Tuns16,TY.Tcomplex80): + e = el_una(OPER.OPu16_32, TYM.TYuint, e); + fty = TY.Tuns32; + goto Lagain; + case X(TY.Tuns16,TY.Timaginary32): + case X(TY.Tuns16,TY.Timaginary64): + case X(TY.Tuns16,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tint32,TY.Tint8): + case X(TY.Tint32,TY.Tuns8): + e = el_una(OPER.OP32_16, TYM.TYshort, e); + fty = TY.Tint16; + goto Lagain; + case X(TY.Tint32,TY.Tint16): + case X(TY.Tint32,TY.Tuns16): + eop = OPER.OP32_16; + goto Leop; + case X(TY.Tint32,TY.Tuns32): + goto Lpaint; + case X(TY.Tint32,TY.Tint64): + case X(TY.Tint32,TY.Tuns64): + eop = OPER.OPs32_64; + goto Leop; + case X(TY.Tint32,TY.Tfloat32): + case X(TY.Tint32,TY.Tfloat64): + case X(TY.Tint32,TY.Tfloat80): + case X(TY.Tint32,TY.Tcomplex32): + case X(TY.Tint32,TY.Tcomplex64): + case X(TY.Tint32,TY.Tcomplex80): + e = el_una(OPER.OPs32_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tint32,TY.Timaginary32): + case X(TY.Tint32,TY.Timaginary64): + case X(TY.Tint32,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tuns32,TY.Tint8): + case X(TY.Tuns32,TY.Tuns8): + e = el_una(OPER.OP32_16, TYM.TYshort, e); + fty = TY.Tuns16; + goto Lagain; + case X(TY.Tuns32,TY.Tint16): + case X(TY.Tuns32,TY.Tuns16): + eop = OPER.OP32_16; + goto Leop; + case X(TY.Tuns32,TY.Tint32): + goto Lpaint; + case X(TY.Tuns32,TY.Tint64): + case X(TY.Tuns32,TY.Tuns64): + eop = OPER.OPu32_64; + goto Leop; + case X(TY.Tuns32,TY.Tfloat32): + case X(TY.Tuns32,TY.Tfloat64): + case X(TY.Tuns32,TY.Tfloat80): + case X(TY.Tuns32,TY.Tcomplex32): + case X(TY.Tuns32,TY.Tcomplex64): + case X(TY.Tuns32,TY.Tcomplex80): + e = el_una(OPER.OPu32_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tuns32,TY.Timaginary32): + case X(TY.Tuns32,TY.Timaginary64): + case X(TY.Tuns32,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tint64,TY.Tint8): + case X(TY.Tint64,TY.Tuns8): + case X(TY.Tint64,TY.Tint16): + case X(TY.Tint64,TY.Tuns16): + e = el_una(OPER.OP64_32, TYM.TYint, e); + fty = TY.Tint32; + goto Lagain; + case X(TY.Tint64,TY.Tint32): + case X(TY.Tint64,TY.Tuns32): + eop = OPER.OP64_32; + goto Leop; + case X(TY.Tint64,TY.Tuns64): + goto Lpaint; + case X(TY.Tint64,TY.Tfloat32): + case X(TY.Tint64,TY.Tfloat64): + case X(TY.Tint64,TY.Tfloat80): + case X(TY.Tint64,TY.Tcomplex32): + case X(TY.Tint64,TY.Tcomplex64): + case X(TY.Tint64,TY.Tcomplex80): + e = el_una(OPER.OPs64_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tint64,TY.Timaginary32): + case X(TY.Tint64,TY.Timaginary64): + case X(TY.Tint64,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tuns64,TY.Tint8): + case X(TY.Tuns64,TY.Tuns8): + case X(TY.Tuns64,TY.Tint16): + case X(TY.Tuns64,TY.Tuns16): + e = el_una(OPER.OP64_32, TYM.TYint, e); + fty = TY.Tint32; + goto Lagain; + case X(TY.Tuns64,TY.Tint32): + case X(TY.Tuns64,TY.Tuns32): + eop = OPER.OP64_32; + goto Leop; + case X(TY.Tuns64,TY.Tint64): + goto Lpaint; + case X(TY.Tuns64,TY.Tfloat32): + case X(TY.Tuns64,TY.Tfloat64): + case X(TY.Tuns64,TY.Tfloat80): + case X(TY.Tuns64,TY.Tcomplex32): + case X(TY.Tuns64,TY.Tcomplex64): + case X(TY.Tuns64,TY.Tcomplex80): + e = el_una(OPER.OPu64_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tuns64,TY.Timaginary32): + case X(TY.Tuns64,TY.Timaginary64): + case X(TY.Tuns64,TY.Timaginary80): + goto Lzero; + + /* ============================= */ + + case X(TY.Tfloat32,TY.Tint8): + case X(TY.Tfloat32,TY.Tuns8): + case X(TY.Tfloat32,TY.Tint16): + case X(TY.Tfloat32,TY.Tuns16): + case X(TY.Tfloat32,TY.Tint32): + case X(TY.Tfloat32,TY.Tuns32): + case X(TY.Tfloat32,TY.Tint64): + case X(TY.Tfloat32,TY.Tuns64): + case X(TY.Tfloat32,TY.Tfloat80): + e = el_una(OPER.OPf_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tfloat32,TY.Tfloat64): + eop = OPER.OPf_d; + goto Leop; + case X(TY.Tfloat32,TY.Timaginary32): + goto Lzero; + case X(TY.Tfloat32,TY.Timaginary64): + goto Lzero; + case X(TY.Tfloat32,TY.Timaginary80): + goto Lzero; + case X(TY.Tfloat32,TY.Tcomplex32): + case X(TY.Tfloat32,TY.Tcomplex64): + case X(TY.Tfloat32,TY.Tcomplex80): + e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYifloat,0),e); + fty = TY.Tcomplex32; + goto Lagain; + + /* ============================= */ + + case X(TY.Tfloat64,TY.Tint8): + case X(TY.Tfloat64,TY.Tuns8): + e = el_una(OPER.OPd_s16, TYM.TYshort, e); + fty = TY.Tint16; + goto Lagain; + case X(TY.Tfloat64,TY.Tint16): + eop = OPER.OPd_s16; + goto Leop; + case X(TY.Tfloat64,TY.Tuns16): + eop = OPER.OPd_u16; + goto Leop; + case X(TY.Tfloat64,TY.Tint32): + eop = OPER.OPd_s32; + goto Leop; + case X(TY.Tfloat64,TY.Tuns32): + eop = OPER.OPd_u32; + goto Leop; + case X(TY.Tfloat64,TY.Tint64): + eop = OPER.OPd_s64; + goto Leop; + case X(TY.Tfloat64,TY.Tuns64): + eop = OPER.OPd_u64; + goto Leop; + case X(TY.Tfloat64,TY.Tfloat32): + eop = OPER.OPd_f; + goto Leop; + case X(TY.Tfloat64,TY.Tfloat80): + eop = OPER.OPd_ld; + goto Leop; + case X(TY.Tfloat64,TY.Timaginary32): + goto Lzero; + case X(TY.Tfloat64,TY.Timaginary64): + goto Lzero; + case X(TY.Tfloat64,TY.Timaginary80): + goto Lzero; + case X(TY.Tfloat64,TY.Tcomplex32): + case X(TY.Tfloat64,TY.Tcomplex64): + case X(TY.Tfloat64,TY.Tcomplex80): + e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYidouble,0),e); + fty = TY.Tcomplex64; + goto Lagain; + + /* ============================= */ + + case X(TY.Tfloat80,TY.Tint8): + case X(TY.Tfloat80,TY.Tuns8): + case X(TY.Tfloat80,TY.Tint16): + case X(TY.Tfloat80,TY.Tuns16): + case X(TY.Tfloat80,TY.Tint32): + case X(TY.Tfloat80,TY.Tuns32): + case X(TY.Tfloat80,TY.Tint64): + case X(TY.Tfloat80,TY.Tfloat32): + e = el_una(OPER.OPld_d, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tfloat80,TY.Tuns64): + eop = OPER.OPld_u64; + goto Leop; + case X(TY.Tfloat80,TY.Tfloat64): + eop = OPER.OPld_d; + goto Leop; + case X(TY.Tfloat80,TY.Timaginary32): + goto Lzero; + case X(TY.Tfloat80,TY.Timaginary64): + goto Lzero; + case X(TY.Tfloat80,TY.Timaginary80): + goto Lzero; + case X(TY.Tfloat80,TY.Tcomplex32): + case X(TY.Tfloat80,TY.Tcomplex64): + case X(TY.Tfloat80,TY.Tcomplex80): + e = el_bin(OPER.OPadd,TYM.TYcldouble,e,el_long(TYM.TYildouble,0)); + fty = TY.Tcomplex80; + goto Lagain; + + /* ============================= */ + + case X(TY.Timaginary32,TY.Tint8): + case X(TY.Timaginary32,TY.Tuns8): + case X(TY.Timaginary32,TY.Tint16): + case X(TY.Timaginary32,TY.Tuns16): + case X(TY.Timaginary32,TY.Tint32): + case X(TY.Timaginary32,TY.Tuns32): + case X(TY.Timaginary32,TY.Tint64): + case X(TY.Timaginary32,TY.Tuns64): + case X(TY.Timaginary32,TY.Tfloat32): + case X(TY.Timaginary32,TY.Tfloat64): + case X(TY.Timaginary32,TY.Tfloat80): + goto Lzero; + case X(TY.Timaginary32,TY.Timaginary64): + eop = OPER.OPf_d; + goto Leop; + case X(TY.Timaginary32,TY.Timaginary80): + e = el_una(OPER.OPf_d, TYM.TYidouble, e); + fty = TY.Timaginary64; + goto Lagain; + case X(TY.Timaginary32,TY.Tcomplex32): + case X(TY.Timaginary32,TY.Tcomplex64): + case X(TY.Timaginary32,TY.Tcomplex80): + e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYfloat,0),e); + fty = TY.Tcomplex32; + goto Lagain; + + /* ============================= */ + + case X(TY.Timaginary64,TY.Tint8): + case X(TY.Timaginary64,TY.Tuns8): + case X(TY.Timaginary64,TY.Tint16): + case X(TY.Timaginary64,TY.Tuns16): + case X(TY.Timaginary64,TY.Tint32): + case X(TY.Timaginary64,TY.Tuns32): + case X(TY.Timaginary64,TY.Tint64): + case X(TY.Timaginary64,TY.Tuns64): + case X(TY.Timaginary64,TY.Tfloat32): + case X(TY.Timaginary64,TY.Tfloat64): + case X(TY.Timaginary64,TY.Tfloat80): + goto Lzero; + case X(TY.Timaginary64,TY.Timaginary32): + eop = OPER.OPd_f; + goto Leop; + case X(TY.Timaginary64,TY.Timaginary80): + eop = OPER.OPd_ld; + goto Leop; + case X(TY.Timaginary64,TY.Tcomplex32): + case X(TY.Timaginary64,TY.Tcomplex64): + case X(TY.Timaginary64,TY.Tcomplex80): + e = el_bin(OPER.OPadd, TYM.TYcdouble, el_long(TYM.TYdouble,0), e); + fty = TY.Tcomplex64; + goto Lagain; + + /* ============================= */ + + case X(TY.Timaginary80,TY.Tint8): + case X(TY.Timaginary80,TY.Tuns8): + case X(TY.Timaginary80,TY.Tint16): + case X(TY.Timaginary80,TY.Tuns16): + case X(TY.Timaginary80,TY.Tint32): + case X(TY.Timaginary80,TY.Tuns32): + case X(TY.Timaginary80,TY.Tint64): + case X(TY.Timaginary80,TY.Tuns64): + case X(TY.Timaginary80,TY.Tfloat32): + case X(TY.Timaginary80,TY.Tfloat64): + case X(TY.Timaginary80,TY.Tfloat80): + goto Lzero; + case X(TY.Timaginary80,TY.Timaginary32): + e = el_una(OPER.OPf_d, TYM.TYidouble, e); + fty = TY.Timaginary64; + goto Lagain; + case X(TY.Timaginary80,TY.Timaginary64): + eop = OPER.OPld_d; + goto Leop; + case X(TY.Timaginary80,TY.Tcomplex32): + case X(TY.Timaginary80,TY.Tcomplex64): + case X(TY.Timaginary80,TY.Tcomplex80): + e = el_bin(OPER.OPadd, TYM.TYcldouble, el_long(TYM.TYldouble,0), e); + fty = TY.Tcomplex80; + goto Lagain; + + /* ============================= */ + + case X(TY.Tcomplex32,TY.Tint8): + case X(TY.Tcomplex32,TY.Tuns8): + case X(TY.Tcomplex32,TY.Tint16): + case X(TY.Tcomplex32,TY.Tuns16): + case X(TY.Tcomplex32,TY.Tint32): + case X(TY.Tcomplex32,TY.Tuns32): + case X(TY.Tcomplex32,TY.Tint64): + case X(TY.Tcomplex32,TY.Tuns64): + case X(TY.Tcomplex32,TY.Tfloat32): + case X(TY.Tcomplex32,TY.Tfloat64): + case X(TY.Tcomplex32,TY.Tfloat80): + e = el_una(OPER.OPc_r, TYM.TYfloat, e); + fty = TY.Tfloat32; + goto Lagain; + case X(TY.Tcomplex32,TY.Timaginary32): + case X(TY.Tcomplex32,TY.Timaginary64): + case X(TY.Tcomplex32,TY.Timaginary80): + e = el_una(OPER.OPc_i, TYM.TYifloat, e); + fty = TY.Timaginary32; + goto Lagain; + case X(TY.Tcomplex32,TY.Tcomplex64): + case X(TY.Tcomplex32,TY.Tcomplex80): + e = el_una(OPER.OPf_d, TYM.TYcdouble, e); + fty = TY.Tcomplex64; + goto Lagain; + + /* ============================= */ + + case X(TY.Tcomplex64,TY.Tint8): + case X(TY.Tcomplex64,TY.Tuns8): + case X(TY.Tcomplex64,TY.Tint16): + case X(TY.Tcomplex64,TY.Tuns16): + case X(TY.Tcomplex64,TY.Tint32): + case X(TY.Tcomplex64,TY.Tuns32): + case X(TY.Tcomplex64,TY.Tint64): + case X(TY.Tcomplex64,TY.Tuns64): + case X(TY.Tcomplex64,TY.Tfloat32): + case X(TY.Tcomplex64,TY.Tfloat64): + case X(TY.Tcomplex64,TY.Tfloat80): + e = el_una(OPER.OPc_r, TYM.TYdouble, e); + fty = TY.Tfloat64; + goto Lagain; + case X(TY.Tcomplex64,TY.Timaginary32): + case X(TY.Tcomplex64,TY.Timaginary64): + case X(TY.Tcomplex64,TY.Timaginary80): + e = el_una(OPER.OPc_i, TYM.TYidouble, e); + fty = TY.Timaginary64; + goto Lagain; + case X(TY.Tcomplex64,TY.Tcomplex32): + eop = OPER.OPd_f; + goto Leop; + case X(TY.Tcomplex64,TY.Tcomplex80): + eop = OPER.OPd_ld; + goto Leop; + + /* ============================= */ + + case X(TY.Tcomplex80,TY.Tint8): + case X(TY.Tcomplex80,TY.Tuns8): + case X(TY.Tcomplex80,TY.Tint16): + case X(TY.Tcomplex80,TY.Tuns16): + case X(TY.Tcomplex80,TY.Tint32): + case X(TY.Tcomplex80,TY.Tuns32): + case X(TY.Tcomplex80,TY.Tint64): + case X(TY.Tcomplex80,TY.Tuns64): + case X(TY.Tcomplex80,TY.Tfloat32): + case X(TY.Tcomplex80,TY.Tfloat64): + case X(TY.Tcomplex80,TY.Tfloat80): + e = el_una(OPER.OPc_r, TYM.TYldouble, e); + fty = TY.Tfloat80; + goto Lagain; + case X(TY.Tcomplex80,TY.Timaginary32): + case X(TY.Tcomplex80,TY.Timaginary64): + case X(TY.Tcomplex80,TY.Timaginary80): + e = el_una(OPER.OPc_i, TYM.TYildouble, e); + fty = TY.Timaginary80; + goto Lagain; + case X(TY.Tcomplex80,TY.Tcomplex32): + case X(TY.Tcomplex80,TY.Tcomplex64): + e = el_una(OPER.OPld_d, TYM.TYcdouble, e); + fty = TY.Tcomplex64; + goto Lagain; + + /* ============================= */ + + default: + if (fty == tty) + goto Lpaint; + //dump(0); + //printf("fty = %d, tty = %d\n", fty, tty); + error("e2ir: cannot cast from %s to %s", e1.type.toChars(), t.toChars()); + goto Lzero; + + Lzero: + e = el_long(ttym, 0); + break; + + Lpaint: + e.Ety = ttym; + break; + + Leop: + e = el_una(eop, ttym, e); + break; + } + Lret: + // Adjust for any type paints + t = type.toBasetype(); + e.Ety = t.totym(); + + el_setLoc(e,loc); + return e; + } + + Identifier opId() + { + return Id.cast_; + } +} +