Mercurial > projects > ddmd
diff dmd/AssignExp.d @ 72:2e2a5c3f943a
reduced warnings by adding override to the methods
think this also normalizes different line endings used all over the place
author | Trass3r |
---|---|
date | Sat, 28 Aug 2010 16:19:48 +0200 |
parents | ee3a9f34dc48 |
children | be2ab491772e |
line wrap: on
line diff
--- a/dmd/AssignExp.d Sat Aug 28 16:14:07 2010 +0200 +++ b/dmd/AssignExp.d Sat Aug 28 16:19:48 2010 +0200 @@ -1,55 +1,55 @@ -module dmd.AssignExp; - -import dmd.Expression; -import dmd.Identifier; -import dmd.backend.elem; -import dmd.InterState; -import dmd.Argument; -import dmd.IndexExp; -import dmd.CallExp; -import dmd.CastExp; -import dmd.TypeSArray; -import dmd.StructLiteralExp; -import dmd.ArrayLengthExp; -import dmd.TypeStruct; -import dmd.StructDeclaration; -import dmd.VarExp; -import dmd.TY; -import dmd.SliceExp; -import dmd.CommaExp; -import dmd.ArrayExp; -import dmd.AggregateDeclaration; -import dmd.CondExp; -import dmd.DotVarExp; -import dmd.WANT; -import dmd.Id; -import dmd.TypeClass; -import dmd.OutBuffer; -import dmd.Loc; -import dmd.TypeNext; -import dmd.TupleExp; -import dmd.VarDeclaration; -import dmd.Scope; -import dmd.IRState; -import dmd.ArrayTypes; -import dmd.BinExp; -import dmd.TOK; -import dmd.Global; -import dmd.Declaration; -import dmd.TypeFunction; -import dmd.Type; -import dmd.RET; -import dmd.STC; -import dmd.DotIdExp; - -import dmd.backend.Util; -import dmd.backend.Symbol; -import dmd.backend.OPER; -import dmd.backend.TYM; -import dmd.backend.RTLSYM; -import dmd.codegen.Util; -import dmd.expression.Util; - +module dmd.AssignExp; + +import dmd.Expression; +import dmd.Identifier; +import dmd.backend.elem; +import dmd.InterState; +import dmd.Argument; +import dmd.IndexExp; +import dmd.CallExp; +import dmd.CastExp; +import dmd.TypeSArray; +import dmd.StructLiteralExp; +import dmd.ArrayLengthExp; +import dmd.TypeStruct; +import dmd.StructDeclaration; +import dmd.VarExp; +import dmd.TY; +import dmd.SliceExp; +import dmd.CommaExp; +import dmd.ArrayExp; +import dmd.AggregateDeclaration; +import dmd.CondExp; +import dmd.DotVarExp; +import dmd.WANT; +import dmd.Id; +import dmd.TypeClass; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.TypeNext; +import dmd.TupleExp; +import dmd.VarDeclaration; +import dmd.Scope; +import dmd.IRState; +import dmd.ArrayTypes; +import dmd.BinExp; +import dmd.TOK; +import dmd.Global; +import dmd.Declaration; +import dmd.TypeFunction; +import dmd.Type; +import dmd.RET; +import dmd.STC; +import dmd.DotIdExp; + +import dmd.backend.Util; +import dmd.backend.Symbol; +import dmd.backend.OPER; +import dmd.backend.TYM; +import dmd.backend.RTLSYM; +import dmd.codegen.Util; +import dmd.expression.Util; + class AssignExp : BinExp { int ismemset = 0; @@ -59,823 +59,823 @@ super(loc, TOK.TOKassign, AssignExp.sizeof, e1, e2); } - Expression semantic(Scope sc) + override Expression semantic(Scope sc) { - Expression e1old = e1; - -version (LOGSEMANTIC) { - printf("AssignExp.semantic('%s')\n", toChars()); -} - //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op)); - //printf("e2.op = %d, '%s'\n", e2.op, Token.toChars(e2.op)); - - if (type) - return this; - - if (e2.op == TOK.TOKcomma) - { - /* Rewrite to get rid of the comma from rvalue - */ - AssignExp ea = new AssignExp(loc, e1, (cast(CommaExp)e2).e2); - ea.op = op; - Expression e = new CommaExp(loc, (cast(CommaExp)e2).e1, ea); - return e.semantic(sc); - } - - /* Look for operator overloading of a[i]=value. - * Do it before semantic() otherwise the a[i] will have been - * converted to a.opIndex() already. - */ - if (e1.op == TOK.TOKarray) - { - ArrayExp ae = cast(ArrayExp)e1; - AggregateDeclaration ad; - Identifier id = Id.index; - - ae.e1 = ae.e1.semantic(sc); - Type t1 = ae.e1.type.toBasetype(); - if (t1.ty == TY.Tstruct) - { - ad = (cast(TypeStruct)t1).sym; - goto L1; - } - else if (t1.ty == TY.Tclass) - { - ad = (cast(TypeClass)t1).sym; - L1: - // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) - if (search_function(ad, Id.indexass)) - { - Expression e = new DotIdExp(loc, ae.e1, Id.indexass); - Expressions a = cast(Expressions)ae.arguments.copy(); - - a.insert(0, cast(void*)e2); - e = new CallExp(loc, e, a); - e = e.semantic(sc); - return e; - } - else - { - // Rewrite (a[i] = value) to (a.opIndex(i, value)) - if (search_function(ad, id)) - { - Expression e = new DotIdExp(loc, ae.e1, id); - - if (1 || !global.params.useDeprecated) - error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); - - e = new CallExp(loc, e, cast(Expression)ae.arguments.data[0], e2); - e = e.semantic(sc); - return e; - } - } - } - } - /* Look for operator overloading of a[i..j]=value. - * Do it before semantic() otherwise the a[i..j] will have been - * converted to a.opSlice() already. - */ - if (e1.op == TOK.TOKslice) - { - Type t1; - SliceExp ae = cast(SliceExp)e1; - AggregateDeclaration ad; - Identifier id = Id.index; - - ae.e1 = ae.e1.semantic(sc); - ae.e1 = resolveProperties(sc, ae.e1); - t1 = ae.e1.type.toBasetype(); - if (t1.ty == TY.Tstruct) - { - ad = (cast(TypeStruct)t1).sym; - goto L2; - } - else if (t1.ty == TY.Tclass) - { - ad = (cast(TypeClass)t1).sym; - L2: - // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) - if (search_function(ad, Id.sliceass)) - { - Expression e = new DotIdExp(loc, ae.e1, Id.sliceass); - Expressions a = new Expressions(); - - a.push(cast(void*)e2); - if (ae.lwr) - { - a.push(cast(void*)ae.lwr); - assert(ae.upr); - a.push(cast(void*)ae.upr); - } - else - assert(!ae.upr); - - e = new CallExp(loc, e, a); - e = e.semantic(sc); - return e; - } - } - } - - BinExp.semantic(sc); - - if (e1.op == TOK.TOKdottd) - { - // Rewrite a.b=e2, when b is a template, as a.b(e2) - Expression e = new CallExp(loc, e1, e2); - e = e.semantic(sc); - return e; - } - - e2 = resolveProperties(sc, e2); - assert(e1.type); - - /* Rewrite tuple assignment as a tuple of assignments. - */ - if (e1.op == TOK.TOKtuple && e2.op == TOK.TOKtuple) - { - TupleExp tup1 = cast(TupleExp)e1; - TupleExp tup2 = cast(TupleExp)e2; - size_t dim = tup1.exps.dim; - if (dim != tup2.exps.dim) - { - error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim); - } - else - { - Expressions exps = new Expressions; - exps.setDim(dim); - - for (int i = 0; i < dim; i++) - { - Expression ex1 = cast(Expression)tup1.exps.data[i]; - Expression ex2 = cast(Expression)tup2.exps.data[i]; - exps.data[i] = cast(void*) new AssignExp(loc, ex1, ex2); - } - Expression e = new TupleExp(loc, exps); - e = e.semantic(sc); - return e; - } - } - - // Determine if this is an initialization of a reference - int refinit = 0; - if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar) - { - VarExp ve = cast(VarExp)e1; - VarDeclaration v = ve.var.isVarDeclaration(); - if (v.storage_class & (STC.STCout | STC.STCref)) - refinit = 1; - } - - Type t1 = e1.type.toBasetype(); - - if (t1.ty == TY.Tfunction) - { - // Rewrite f=value to f(value) - Expression e = new CallExp(loc, e1, e2); - e = e.semantic(sc); - return e; - } - - /* If it is an assignment from a 'foreign' type, - * check for operator overloading. - */ - if (t1.ty == TY.Tstruct) - { - StructDeclaration sd = (cast(TypeStruct)t1).sym; - if (op == TOK.TOKassign) - { - Expression e = op_overload(sc); - if (e) - return e; - } - else if (op == TOK.TOKconstruct && !refinit) - { - Type t2 = e2.type.toBasetype(); - if (t2.ty == TY.Tstruct && sd == (cast(TypeStruct)t2).sym && sd.cpctor) - { - /* We have a copy constructor for this - */ - if (e2.op == TOK.TOKquestion) - { /* Write as: - * a ? e1 = b : e1 = c; - */ - CondExp ec = cast(CondExp)e2; - AssignExp ea1 = new AssignExp(ec.e1.loc, e1, ec.e1); - ea1.op = op; - AssignExp ea2 = new AssignExp(ec.e1.loc, e1, ec.e2); - ea2.op = op; - Expression e = new CondExp(loc, ec.econd, ea1, ea2); - return e.semantic(sc); - } - else if (e2.op == TOK.TOKvar || e2.op == TOK.TOKdotvar || e2.op == TOK.TOKstar || e2.op == TOK.TOKindex) - { /* Write as: - * e1.cpctor(e2); - */ - Expression e = new DotVarExp(loc, e1, sd.cpctor, 0); - e = new CallExp(loc, e, e2); - return e.semantic(sc); - } - } - } - } - else if (t1.ty == TY.Tclass) - { - // Disallow assignment operator overloads for same type - if (!e2.type.implicitConvTo(e1.type)) - { - Expression e = op_overload(sc); - if (e) - return e; - } - } - - if (t1.ty == TY.Tsarray && !refinit) - { - // Convert e1 to e1[] - Expression e = new SliceExp(e1.loc, e1, null, null); - e1 = e.semantic(sc); - t1 = e1.type.toBasetype(); - } - - e2.rvalue(); - - if (e1.op == TOK.TOKarraylength) - { - // e1 is not an lvalue, but we let code generator handle it - ArrayLengthExp ale = cast(ArrayLengthExp)e1; - ale.e1 = ale.e1.modifiableLvalue(sc, e1); - } - else if (e1.op == TOK.TOKslice) - { - Type tn = e1.type.nextOf(); - if (tn && !tn.isMutable() && op != TOK.TOKconstruct) - error("slice %s is not mutable", e1.toChars()); - } - else - { - // Try to do a decent error message with the expression - // before it got constant folded - if (e1.op != TOK.TOKvar) - e1 = e1.optimize(WANT.WANTvalue); - - if (op != TOK.TOKconstruct) - e1 = e1.modifiableLvalue(sc, e1old); - } - - Type t2 = e2.type; - if (e1.op == TOK.TOKslice && t1.nextOf() && e2.implicitConvTo(t1.nextOf())) - { - // memset - ismemset = 1; // make it easy for back end to tell what this is - e2 = e2.implicitCastTo(sc, t1.nextOf()); - } - else if (t1.ty == TY.Tsarray) - { - /* Should have already converted e1 => e1[] - */ - assert(op == TOK.TOKconstruct); - //error("cannot assign to static array %s", e1.toChars()); - } - else if (e1.op == TOK.TOKslice) - { - e2 = e2.implicitCastTo(sc, e1.type.constOf()); - } - else - { - e2 = e2.implicitCastTo(sc, e1.type); - } - - /* Look for array operations - */ - if (e1.op == TOK.TOKslice && !ismemset && - (e2.op == TOK.TOKadd || e2.op == TOK.TOKmin || - e2.op == TOK.TOKmul || e2.op == TOK.TOKdiv || - e2.op == TOK.TOKmod || e2.op == TOK.TOKxor || - e2.op == TOK.TOKand || e2.op == TOK.TOKor || - e2.op == TOK.TOKtilde || e2.op == TOK.TOKneg)) - { - type = e1.type; - return arrayOp(sc); - } - - type = e1.type; - assert(type); + Expression e1old = e1; + +version (LOGSEMANTIC) { + printf("AssignExp.semantic('%s')\n", toChars()); +} + //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op)); + //printf("e2.op = %d, '%s'\n", e2.op, Token.toChars(e2.op)); + + if (type) + return this; + + if (e2.op == TOK.TOKcomma) + { + /* Rewrite to get rid of the comma from rvalue + */ + AssignExp ea = new AssignExp(loc, e1, (cast(CommaExp)e2).e2); + ea.op = op; + Expression e = new CommaExp(loc, (cast(CommaExp)e2).e1, ea); + return e.semantic(sc); + } + + /* Look for operator overloading of a[i]=value. + * Do it before semantic() otherwise the a[i] will have been + * converted to a.opIndex() already. + */ + if (e1.op == TOK.TOKarray) + { + ArrayExp ae = cast(ArrayExp)e1; + AggregateDeclaration ad; + Identifier id = Id.index; + + ae.e1 = ae.e1.semantic(sc); + Type t1 = ae.e1.type.toBasetype(); + if (t1.ty == TY.Tstruct) + { + ad = (cast(TypeStruct)t1).sym; + goto L1; + } + else if (t1.ty == TY.Tclass) + { + ad = (cast(TypeClass)t1).sym; + L1: + // Rewrite (a[i] = value) to (a.opIndexAssign(value, i)) + if (search_function(ad, Id.indexass)) + { + Expression e = new DotIdExp(loc, ae.e1, Id.indexass); + Expressions a = cast(Expressions)ae.arguments.copy(); + + a.insert(0, cast(void*)e2); + e = new CallExp(loc, e, a); + e = e.semantic(sc); + return e; + } + else + { + // Rewrite (a[i] = value) to (a.opIndex(i, value)) + if (search_function(ad, id)) + { + Expression e = new DotIdExp(loc, ae.e1, id); + + if (1 || !global.params.useDeprecated) + error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)"); + + e = new CallExp(loc, e, cast(Expression)ae.arguments.data[0], e2); + e = e.semantic(sc); + return e; + } + } + } + } + /* Look for operator overloading of a[i..j]=value. + * Do it before semantic() otherwise the a[i..j] will have been + * converted to a.opSlice() already. + */ + if (e1.op == TOK.TOKslice) + { + Type t1; + SliceExp ae = cast(SliceExp)e1; + AggregateDeclaration ad; + Identifier id = Id.index; + + ae.e1 = ae.e1.semantic(sc); + ae.e1 = resolveProperties(sc, ae.e1); + t1 = ae.e1.type.toBasetype(); + if (t1.ty == TY.Tstruct) + { + ad = (cast(TypeStruct)t1).sym; + goto L2; + } + else if (t1.ty == TY.Tclass) + { + ad = (cast(TypeClass)t1).sym; + L2: + // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j)) + if (search_function(ad, Id.sliceass)) + { + Expression e = new DotIdExp(loc, ae.e1, Id.sliceass); + Expressions a = new Expressions(); + + a.push(cast(void*)e2); + if (ae.lwr) + { + a.push(cast(void*)ae.lwr); + assert(ae.upr); + a.push(cast(void*)ae.upr); + } + else + assert(!ae.upr); + + e = new CallExp(loc, e, a); + e = e.semantic(sc); + return e; + } + } + } + + BinExp.semantic(sc); + + if (e1.op == TOK.TOKdottd) + { + // Rewrite a.b=e2, when b is a template, as a.b(e2) + Expression e = new CallExp(loc, e1, e2); + e = e.semantic(sc); + return e; + } + + e2 = resolveProperties(sc, e2); + assert(e1.type); + + /* Rewrite tuple assignment as a tuple of assignments. + */ + if (e1.op == TOK.TOKtuple && e2.op == TOK.TOKtuple) + { + TupleExp tup1 = cast(TupleExp)e1; + TupleExp tup2 = cast(TupleExp)e2; + size_t dim = tup1.exps.dim; + if (dim != tup2.exps.dim) + { + error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim); + } + else + { + Expressions exps = new Expressions; + exps.setDim(dim); + + for (int i = 0; i < dim; i++) + { + Expression ex1 = cast(Expression)tup1.exps.data[i]; + Expression ex2 = cast(Expression)tup2.exps.data[i]; + exps.data[i] = cast(void*) new AssignExp(loc, ex1, ex2); + } + Expression e = new TupleExp(loc, exps); + e = e.semantic(sc); + return e; + } + } + + // Determine if this is an initialization of a reference + int refinit = 0; + if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar) + { + VarExp ve = cast(VarExp)e1; + VarDeclaration v = ve.var.isVarDeclaration(); + if (v.storage_class & (STC.STCout | STC.STCref)) + refinit = 1; + } + + Type t1 = e1.type.toBasetype(); + + if (t1.ty == TY.Tfunction) + { + // Rewrite f=value to f(value) + Expression e = new CallExp(loc, e1, e2); + e = e.semantic(sc); + return e; + } + + /* If it is an assignment from a 'foreign' type, + * check for operator overloading. + */ + if (t1.ty == TY.Tstruct) + { + StructDeclaration sd = (cast(TypeStruct)t1).sym; + if (op == TOK.TOKassign) + { + Expression e = op_overload(sc); + if (e) + return e; + } + else if (op == TOK.TOKconstruct && !refinit) + { + Type t2 = e2.type.toBasetype(); + if (t2.ty == TY.Tstruct && sd == (cast(TypeStruct)t2).sym && sd.cpctor) + { + /* We have a copy constructor for this + */ + if (e2.op == TOK.TOKquestion) + { /* Write as: + * a ? e1 = b : e1 = c; + */ + CondExp ec = cast(CondExp)e2; + AssignExp ea1 = new AssignExp(ec.e1.loc, e1, ec.e1); + ea1.op = op; + AssignExp ea2 = new AssignExp(ec.e1.loc, e1, ec.e2); + ea2.op = op; + Expression e = new CondExp(loc, ec.econd, ea1, ea2); + return e.semantic(sc); + } + else if (e2.op == TOK.TOKvar || e2.op == TOK.TOKdotvar || e2.op == TOK.TOKstar || e2.op == TOK.TOKindex) + { /* Write as: + * e1.cpctor(e2); + */ + Expression e = new DotVarExp(loc, e1, sd.cpctor, 0); + e = new CallExp(loc, e, e2); + return e.semantic(sc); + } + } + } + } + else if (t1.ty == TY.Tclass) + { + // Disallow assignment operator overloads for same type + if (!e2.type.implicitConvTo(e1.type)) + { + Expression e = op_overload(sc); + if (e) + return e; + } + } + + if (t1.ty == TY.Tsarray && !refinit) + { + // Convert e1 to e1[] + Expression e = new SliceExp(e1.loc, e1, null, null); + e1 = e.semantic(sc); + t1 = e1.type.toBasetype(); + } + + e2.rvalue(); + + if (e1.op == TOK.TOKarraylength) + { + // e1 is not an lvalue, but we let code generator handle it + ArrayLengthExp ale = cast(ArrayLengthExp)e1; + ale.e1 = ale.e1.modifiableLvalue(sc, e1); + } + else if (e1.op == TOK.TOKslice) + { + Type tn = e1.type.nextOf(); + if (tn && !tn.isMutable() && op != TOK.TOKconstruct) + error("slice %s is not mutable", e1.toChars()); + } + else + { + // Try to do a decent error message with the expression + // before it got constant folded + if (e1.op != TOK.TOKvar) + e1 = e1.optimize(WANT.WANTvalue); + + if (op != TOK.TOKconstruct) + e1 = e1.modifiableLvalue(sc, e1old); + } + + Type t2 = e2.type; + if (e1.op == TOK.TOKslice && t1.nextOf() && e2.implicitConvTo(t1.nextOf())) + { + // memset + ismemset = 1; // make it easy for back end to tell what this is + e2 = e2.implicitCastTo(sc, t1.nextOf()); + } + else if (t1.ty == TY.Tsarray) + { + /* Should have already converted e1 => e1[] + */ + assert(op == TOK.TOKconstruct); + //error("cannot assign to static array %s", e1.toChars()); + } + else if (e1.op == TOK.TOKslice) + { + e2 = e2.implicitCastTo(sc, e1.type.constOf()); + } + else + { + e2 = e2.implicitCastTo(sc, e1.type); + } + + /* Look for array operations + */ + if (e1.op == TOK.TOKslice && !ismemset && + (e2.op == TOK.TOKadd || e2.op == TOK.TOKmin || + e2.op == TOK.TOKmul || e2.op == TOK.TOKdiv || + e2.op == TOK.TOKmod || e2.op == TOK.TOKxor || + e2.op == TOK.TOKand || e2.op == TOK.TOKor || + e2.op == TOK.TOKtilde || e2.op == TOK.TOKneg)) + { + type = e1.type; + return arrayOp(sc); + } + + type = e1.type; + assert(type); return this; } - Expression checkToBoolean() + override Expression checkToBoolean() { assert(false); } - Expression interpret(InterState istate) + override Expression interpret(InterState istate) { return interpretAssignCommon(istate, null); } - Identifier opId() + override Identifier opId() { return Id.assign; } - void buildArrayIdent(OutBuffer buf, Expressions arguments) + override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - /* Evaluate assign expressions right to left - */ - e2.buildArrayIdent(buf, arguments); - e1.buildArrayIdent(buf, arguments); + /* Evaluate assign expressions right to left + */ + e2.buildArrayIdent(buf, arguments); + e1.buildArrayIdent(buf, arguments); buf.writestring("Assign"); } - Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Arguments fparams) { - /* Evaluate assign expressions right to left - */ - Expression ex2 = e2.buildArrayLoop(fparams); - version (DMDV2) { - /* Need the cast because: - * b = c + p[i]; - * where b is a byte fails because (c + p[i]) is an int - * which cannot be implicitly cast to byte. - */ - ex2 = new CastExp(Loc(0), ex2, e1.type.nextOf()); - } - Expression ex1 = e1.buildArrayLoop(fparams); - Argument param = cast(Argument)fparams.data[0]; - param.storageClass = STCundefined; - Expression e = new AssignExp(Loc(0), ex1, ex2); + /* Evaluate assign expressions right to left + */ + Expression ex2 = e2.buildArrayLoop(fparams); + version (DMDV2) { + /* Need the cast because: + * b = c + p[i]; + * where b is a byte fails because (c + p[i]) is an int + * which cannot be implicitly cast to byte. + */ + ex2 = new CastExp(Loc(0), ex2, e1.type.nextOf()); + } + Expression ex1 = e1.buildArrayLoop(fparams); + Argument param = cast(Argument)fparams.data[0]; + param.storageClass = STCundefined; + Expression e = new AssignExp(Loc(0), ex1, ex2); return e; } - elem* toElem(IRState* irs) + override elem* toElem(IRState* irs) { - elem* e; - IndexExp ae; - int r; - Type t1b; - - //printf("AssignExp.toElem('%s')\n", toChars()); - t1b = e1.type.toBasetype(); - - // Look for array.length = n - if (e1.op == TOK.TOKarraylength) - { - // Generate: - // _d_arraysetlength(e2, sizeelem, &ale.e1); - - ArrayLengthExp ale = cast(ArrayLengthExp)e1; - elem* p1; - elem* p2; - elem* p3; - elem* ep; - Type t1; - - p1 = e2.toElem(irs); - p3 = ale.e1.toElem(irs); - p3 = addressElem(p3, null); - t1 = ale.e1.type.toBasetype(); - -static if (true) { - // call _d_arraysetlengthT(ti, e2, &ale.e1); - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; -} else { - if (t1.next.isZeroInit()) - { - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = RTLSYM.RTLSYM_ARRAYSETLENGTHT; - } - else - { - p2 = el_long(TYM.TYint, t1.next.size()); - ep = el_params(p3, p2, p1, null); // c function - Expression init = t1.next.defaultInit(); - ep = el_param(el_long(TYM.TYint, init.type.size()), ep); - elem* ei = init.toElem(irs); - ep = el_param(ei, ep); - r = RTLSYM.RTLSYM_ARRAYSETLENGTH3; - } -} - e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); - el_setLoc(e, loc); - return e; - } - - // Look for array[]=n - if (e1.op == TOK.TOKslice) - { - Type t1 = t1b; - Type t2 = e2.type.toBasetype(); - - // which we do if the 'next' types match - if (ismemset) - { - // Do a memset for array[]=v - //printf("Lpair %s\n", toChars()); - SliceExp are = cast(SliceExp)e1; - elem* elwr; - elem* eupr; - elem* n1; - elem* evalue; - elem* enbytes; - elem* elength; - elem* einit; - long value; - Type ta = are.e1.type.toBasetype(); - Type tb = ta.nextOf().toBasetype(); - int sz = cast(uint)tb.size(); - tym_t tym = type.totym(); - - n1 = are.e1.toElem(irs); - elwr = are.lwr ? are.lwr.toElem(irs) : null; - eupr = are.upr ? are.upr.toElem(irs) : null; - - elem* n1x = n1; - - // Look for array[]=n - if (ta.ty == TY.Tsarray) - { - TypeSArray ts = cast(TypeSArray)ta; - n1 = array_toPtr(ta, n1); - enbytes = ts.dim.toElem(irs); - n1x = n1; - n1 = el_same(&n1x); - einit = resolveLengthVar(are.lengthVar, &n1, ta); - } - else if (ta.ty == TY.Tarray) - { - n1 = el_same(&n1x); - einit = resolveLengthVar(are.lengthVar, &n1, ta); - enbytes = el_copytree(n1); - n1 = array_toPtr(ta, n1); - enbytes = el_una(OPER.OP64_32, TYM.TYint, enbytes); - } - else if (ta.ty == TY.Tpointer) - { - n1 = el_same(&n1x); - enbytes = el_long(TYM.TYint, -1); // largest possible index - einit = null; - } - - // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr - elem* elwrx = elwr; - if (elwr) elwr = el_same(&elwrx); - elem* euprx = eupr; - if (eupr) eupr = el_same(&euprx); - - static if (false) { - printf("sz = %d\n", sz); - printf("n1x\n"); - elem_print(n1x); - printf("einit\n"); - elem_print(einit); - printf("elwrx\n"); - elem_print(elwrx); - printf("euprx\n"); - elem_print(euprx); - printf("n1\n"); - elem_print(n1); - printf("elwr\n"); - elem_print(elwr); - printf("eupr\n"); - elem_print(eupr); - printf("enbytes\n"); - elem_print(enbytes); - } - einit = el_combine(n1x, einit); - einit = el_combine(einit, elwrx); - einit = el_combine(einit, euprx); - - evalue = this.e2.toElem(irs); - - static if (false) { - printf("n1\n"); - elem_print(n1); - printf("enbytes\n"); - elem_print(enbytes); - } - - if (global.params.useArrayBounds && eupr && ta.ty != TY.Tpointer) - { - elem *c1; - elem *c2; - elem *ea; - elem *eb; - elem *enbytesx; - - assert(elwr); - enbytesx = enbytes; - enbytes = el_same(&enbytesx); - c1 = el_bin(OPER.OPle, TYM.TYint, el_copytree(eupr), enbytesx); - c2 = el_bin(OPER.OPle, TYM.TYint, el_copytree(elwr), el_copytree(eupr)); - c1 = el_bin(OPER.OPandand, TYM.TYint, c1, c2); - - // Construct: (c1 || ModuleArray(line)) - Symbol *sassert; - - sassert = irs.blx.module_.toModuleArray(); - ea = el_bin(OPER.OPcall,TYM.TYvoid,el_var(sassert), el_long(TYM.TYint, loc.linnum)); - eb = el_bin(OPER.OPoror,TYM.TYvoid,c1,ea); - einit = el_combine(einit, eb); - } - - if (elwr) - { - elem *elwr2; - - el_free(enbytes); - elwr2 = el_copytree(elwr); - elwr2 = el_bin(OPER.OPmul, TYM.TYint, elwr2, el_long(TYM.TYint, sz)); - n1 = el_bin(OPER.OPadd, TYM.TYnptr, n1, elwr2); - enbytes = el_bin(OPER.OPmin, TYM.TYint, eupr, elwr); - elength = el_copytree(enbytes); - } - else - elength = el_copytree(enbytes); - - e = setArray(n1, enbytes, tb, evalue, irs, op); - Lpair: - e = el_pair(TYM.TYullong, elength, e); - Lret2: - e = el_combine(einit, e); - //elem_print(e); - goto Lret; - } -///static if (false) { -/// else if (e2.op == TOK.TOKadd || e2.op == TOK.TOKmin) -/// { -/// /* It's ea[] = eb[] +- ec[] -/// */ -/// BinExp e2a = cast(BinExp)e2; -/// Type t = e2.type.toBasetype().nextOf().toBasetype(); -/// if (t.ty != TY.Tfloat32 && t.ty != TY.Tfloat64 && t.ty != TY.Tfloat80) -/// { -/// e2.error("array add/min for %s not supported", t.toChars()); -/// return el_long(TYM.TYint, 0); -/// } -/// elem* ea = e1.toElem(irs); -/// ea = array_toDarray(e1.type, ea); -/// elem* eb = e2a.e1.toElem(irs); -/// eb = array_toDarray(e2a.e1.type, eb); -/// elem* ec = e2a.e2.toElem(irs); -/// ec = array_toDarray(e2a.e2.type, ec); -/// -/// int rtl = RTLSYM.RTLSYM_ARRAYASSADDFLOAT; -/// if (t.ty == Tfloat64) -/// rtl = RTLSYM.RTLSYM_ARRAYASSADDDOUBLE; -/// else if (t.ty == Tfloat80) -/// rtl = RTLSYM.RTLSYM_ARRAYASSADDREAL; -/// if (e2.op == TOK.TOKmin) -/// { -/// rtl = RTLSYM.RTLSYM_ARRAYASSMINFLOAT; -/// if (t.ty == Tfloat64) -/// rtl = RTLSYM.RTLSYM_ARRAYASSMINDOUBLE; -/// else if (t.ty == Tfloat80) -/// rtl = RTLSYM.RTLSYM_ARRAYASSMINREAL; -/// } -/// -/// /* Set parameters so the order of evaluation is eb, ec, ea -/// */ -/// elem* ep = el_params(eb, ec, ea, null); -/// e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep); -/// goto Lret; -/// } -///} - else - { - /* It's array1[]=array2[] - * which is a memcpy - */ - elem* eto; - elem* efrom; - elem* esize; - elem* ep; - - eto = e1.toElem(irs); - efrom = e2.toElem(irs); - - uint size = cast(uint)t1.nextOf().size(); - esize = el_long(TYM.TYint, size); - - /* Determine if we need to do postblit - */ - int postblit = 0; - if (needsPostblit(t1)) - postblit = 1; - - assert(e2.type.ty != TY.Tpointer); - - if (!postblit && !global.params.useArrayBounds) - { - elem* epto; - elem* epfr; - elem* elen; - elem* ex; - - ex = el_same(&eto); - - // Determine if elen is a constant - if (eto.Eoper == OPER.OPpair && eto.E1.Eoper == OPER.OPconst) - { - elen = el_copytree(eto.E1); - } - else - { - // It's not a constant, so pull it from the dynamic array - elen = el_una(OPER.OP64_32, TYM.TYint, el_copytree(ex)); - } - - esize = el_bin(OPER.OPmul, TYM.TYint, elen, esize); - epto = array_toPtr(e1.type, ex); - epfr = array_toPtr(e2.type, efrom); - static if (true) { - // memcpy() is faster, so if we can't beat 'em, join 'em - e = el_params(esize, epfr, epto, null); - e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[RTLSYM.RTLSYM_MEMCPY]), e); - } else { - e = el_bin(OPER.OPmemcpy, TYM.TYnptr, epto, el_param(epfr, esize)); - } - e = el_pair(eto.Ety, el_copytree(elen), e); - e = el_combine(eto, e); - } -///version (DMDV2) { - else if (postblit && op != TOK.TOKblit) - { - /* Generate: - * _d_arrayassign(ti, efrom, eto) - * or: - * _d_arrayctor(ti, efrom, eto) - */ - el_free(esize); - Expression ti = t1.nextOf().toBasetype().getTypeInfo(null); - ep = el_params(eto, efrom, ti.toElem(irs), null); - int rtl = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYCTOR : RTLSYM.RTLSYM_ARRAYASSIGN; - e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep); - } -///} - else - { - // Generate: - // _d_arraycopy(eto, efrom, esize) - - ep = el_params(eto, efrom, esize, null); - e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCOPY]), ep); - } - el_setLoc(e, loc); - return e; - } - } - - if (e1.op == TOK.TOKindex) - { - elem* eb; - elem* ei; - elem* ev; - TY ty; - Type ta; - - ae = cast(IndexExp)e1; - ta = ae.e1.type.toBasetype(); - ty = ta.ty; - } - -version (DMDV2) { - /* Look for reference initializations - */ - if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar) - { - VarExp ve = cast(VarExp)e1; - Declaration s = ve.var; - if (s.storage_class & STC.STCref) - { -static if (false) { - Expression ae = e2.addressOf(null); - e = ae.toElem(irs); -} else { - e = e2.toElem(irs); - e = addressElem(e, e2.type); -} - elem* es = el_var(s.toSymbol()); - es.Ety = TYM.TYnptr; - e = el_bin(OPER.OPeq, TYM.TYnptr, es, e); - // BUG: type is struct, and e2 is TOKint64 - goto Lret; - } - } -} - -static if (true) { - /* This will work if we can distinguish an assignment from - * an initialization of the lvalue. It'll work if the latter. - * If the former, because of aliasing of the return value with - * function arguments, it'll fail. - */ - if (op == TOK.TOKconstruct && e2.op == TOK.TOKcall) - { - CallExp ce = cast(CallExp)e2; - - Type t = ce.e1.type.toBasetype(); - if (t.ty == TY.Tfunction) { - TypeFunction tf = cast(TypeFunction)t; - if (tf.retStyle() == RET.RETstack) - { - elem* ehidden = e1.toElem(irs); - ehidden = el_una(OPER.OPaddr, TYM.TYnptr, ehidden); - assert(!irs.ehidden); - irs.ehidden = ehidden; - e = e2.toElem(irs); - goto Lret; - } - } - } -} - //printf("test2 %d\n", op); - //if (op == TOK.TOKconstruct) printf("construct\n"); - if (t1b.ty == TY.Tstruct) - { - elem* eleft = e1.toElem(irs); - - if (e2.op == TOK.TOKint64) - { - /* Implement: - * (struct = 0) - * with: - * memset(&struct, 0, struct.sizeof) - */ - elem* ey = null; - int sz = cast(int)e1.type.size(); - StructDeclaration sd = (cast(TypeStruct)t1b).sym; - if (sd.isnested && op == TOK.TOKconstruct) - { - ey = el_una(OPER.OPaddr, TYM.TYnptr, eleft); - eleft = el_same(&ey); - ey = setEthis(loc, irs, ey, sd); - sz = sd.vthis.offset; - } - - elem *el = eleft; - elem *enbytes = el_long(TYM.TYint, sz); - elem *evalue = el_long(TYM.TYint, 0); - - if (!(sd.isnested && op == TOK.TOKconstruct)) - el = el_una(OPER.OPaddr, TYM.TYnptr, el); - - e = el_param(enbytes, evalue); - e = el_bin(OPER.OPmemset, TYM.TYnptr,el,e); - e = el_combine(ey, e); - el_setLoc(e, loc); - //e = el_una(OPER.OPind, TYM.TYstruct, e); - } - else - { - //printf("toElemBin() '%s'\n", toChars()); - - tym_t tym = type.totym(); - - elem* e1 = eleft; - elem* ex = e1; - if (e1.Eoper == OPER.OPind) - ex = e1.E1; - - if (this.e2.op == TOK.TOKstructliteral && ex.Eoper == OPER.OPvar && ex.EV.sp.Voffset == 0) - { - StructLiteralExp se = cast(StructLiteralExp)this.e2; - - Symbol* symSave = se.sym; - size_t soffsetSave = se.soffset; - int fillHolesSave = se.fillHoles; - - se.sym = ex.EV.sp.Vsym; - se.soffset = 0; - se.fillHoles = (op == TOK.TOKconstruct || op == TOK.TOKblit) ? 1 : 0; - - el_free(e1); - e = this.e2.toElem(irs); - - se.sym = symSave; - se.soffset = soffsetSave; - se.fillHoles = fillHolesSave; - } - else - { - elem* e2 = this.e2.toElem(irs); - e = el_bin(OPER.OPstreq,tym,e1,e2); - e.Enumbytes = cast(uint)this.e1.type.size(); - } - goto Lret; - } - } - else - e = toElemBin(irs,OPER.OPeq); - - return e; - - Lret: - el_setLoc(e,loc); + elem* e; + IndexExp ae; + int r; + Type t1b; + + //printf("AssignExp.toElem('%s')\n", toChars()); + t1b = e1.type.toBasetype(); + + // Look for array.length = n + if (e1.op == TOK.TOKarraylength) + { + // Generate: + // _d_arraysetlength(e2, sizeelem, &ale.e1); + + ArrayLengthExp ale = cast(ArrayLengthExp)e1; + elem* p1; + elem* p2; + elem* p3; + elem* ep; + Type t1; + + p1 = e2.toElem(irs); + p3 = ale.e1.toElem(irs); + p3 = addressElem(p3, null); + t1 = ale.e1.type.toBasetype(); + +static if (true) { + // call _d_arraysetlengthT(ti, e2, &ale.e1); + p2 = t1.getTypeInfo(null).toElem(irs); + ep = el_params(p3, p1, p2, null); // c function + r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; +} else { + if (t1.next.isZeroInit()) + { + p2 = t1.getTypeInfo(null).toElem(irs); + ep = el_params(p3, p1, p2, null); // c function + r = RTLSYM.RTLSYM_ARRAYSETLENGTHT; + } + else + { + p2 = el_long(TYM.TYint, t1.next.size()); + ep = el_params(p3, p2, p1, null); // c function + Expression init = t1.next.defaultInit(); + ep = el_param(el_long(TYM.TYint, init.type.size()), ep); + elem* ei = init.toElem(irs); + ep = el_param(ei, ep); + r = RTLSYM.RTLSYM_ARRAYSETLENGTH3; + } +} + e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); + el_setLoc(e, loc); + return e; + } + + // Look for array[]=n + if (e1.op == TOK.TOKslice) + { + Type t1 = t1b; + Type t2 = e2.type.toBasetype(); + + // which we do if the 'next' types match + if (ismemset) + { + // Do a memset for array[]=v + //printf("Lpair %s\n", toChars()); + SliceExp are = cast(SliceExp)e1; + elem* elwr; + elem* eupr; + elem* n1; + elem* evalue; + elem* enbytes; + elem* elength; + elem* einit; + long value; + Type ta = are.e1.type.toBasetype(); + Type tb = ta.nextOf().toBasetype(); + int sz = cast(uint)tb.size(); + tym_t tym = type.totym(); + + n1 = are.e1.toElem(irs); + elwr = are.lwr ? are.lwr.toElem(irs) : null; + eupr = are.upr ? are.upr.toElem(irs) : null; + + elem* n1x = n1; + + // Look for array[]=n + if (ta.ty == TY.Tsarray) + { + TypeSArray ts = cast(TypeSArray)ta; + n1 = array_toPtr(ta, n1); + enbytes = ts.dim.toElem(irs); + n1x = n1; + n1 = el_same(&n1x); + einit = resolveLengthVar(are.lengthVar, &n1, ta); + } + else if (ta.ty == TY.Tarray) + { + n1 = el_same(&n1x); + einit = resolveLengthVar(are.lengthVar, &n1, ta); + enbytes = el_copytree(n1); + n1 = array_toPtr(ta, n1); + enbytes = el_una(OPER.OP64_32, TYM.TYint, enbytes); + } + else if (ta.ty == TY.Tpointer) + { + n1 = el_same(&n1x); + enbytes = el_long(TYM.TYint, -1); // largest possible index + einit = null; + } + + // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr + elem* elwrx = elwr; + if (elwr) elwr = el_same(&elwrx); + elem* euprx = eupr; + if (eupr) eupr = el_same(&euprx); + + static if (false) { + printf("sz = %d\n", sz); + printf("n1x\n"); + elem_print(n1x); + printf("einit\n"); + elem_print(einit); + printf("elwrx\n"); + elem_print(elwrx); + printf("euprx\n"); + elem_print(euprx); + printf("n1\n"); + elem_print(n1); + printf("elwr\n"); + elem_print(elwr); + printf("eupr\n"); + elem_print(eupr); + printf("enbytes\n"); + elem_print(enbytes); + } + einit = el_combine(n1x, einit); + einit = el_combine(einit, elwrx); + einit = el_combine(einit, euprx); + + evalue = this.e2.toElem(irs); + + static if (false) { + printf("n1\n"); + elem_print(n1); + printf("enbytes\n"); + elem_print(enbytes); + } + + if (global.params.useArrayBounds && eupr && ta.ty != TY.Tpointer) + { + elem *c1; + elem *c2; + elem *ea; + elem *eb; + elem *enbytesx; + + assert(elwr); + enbytesx = enbytes; + enbytes = el_same(&enbytesx); + c1 = el_bin(OPER.OPle, TYM.TYint, el_copytree(eupr), enbytesx); + c2 = el_bin(OPER.OPle, TYM.TYint, el_copytree(elwr), el_copytree(eupr)); + c1 = el_bin(OPER.OPandand, TYM.TYint, c1, c2); + + // Construct: (c1 || ModuleArray(line)) + Symbol *sassert; + + sassert = irs.blx.module_.toModuleArray(); + ea = el_bin(OPER.OPcall,TYM.TYvoid,el_var(sassert), el_long(TYM.TYint, loc.linnum)); + eb = el_bin(OPER.OPoror,TYM.TYvoid,c1,ea); + einit = el_combine(einit, eb); + } + + if (elwr) + { + elem *elwr2; + + el_free(enbytes); + elwr2 = el_copytree(elwr); + elwr2 = el_bin(OPER.OPmul, TYM.TYint, elwr2, el_long(TYM.TYint, sz)); + n1 = el_bin(OPER.OPadd, TYM.TYnptr, n1, elwr2); + enbytes = el_bin(OPER.OPmin, TYM.TYint, eupr, elwr); + elength = el_copytree(enbytes); + } + else + elength = el_copytree(enbytes); + + e = setArray(n1, enbytes, tb, evalue, irs, op); + Lpair: + e = el_pair(TYM.TYullong, elength, e); + Lret2: + e = el_combine(einit, e); + //elem_print(e); + goto Lret; + } +///static if (false) { +/// else if (e2.op == TOK.TOKadd || e2.op == TOK.TOKmin) +/// { +/// /* It's ea[] = eb[] +- ec[] +/// */ +/// BinExp e2a = cast(BinExp)e2; +/// Type t = e2.type.toBasetype().nextOf().toBasetype(); +/// if (t.ty != TY.Tfloat32 && t.ty != TY.Tfloat64 && t.ty != TY.Tfloat80) +/// { +/// e2.error("array add/min for %s not supported", t.toChars()); +/// return el_long(TYM.TYint, 0); +/// } +/// elem* ea = e1.toElem(irs); +/// ea = array_toDarray(e1.type, ea); +/// elem* eb = e2a.e1.toElem(irs); +/// eb = array_toDarray(e2a.e1.type, eb); +/// elem* ec = e2a.e2.toElem(irs); +/// ec = array_toDarray(e2a.e2.type, ec); +/// +/// int rtl = RTLSYM.RTLSYM_ARRAYASSADDFLOAT; +/// if (t.ty == Tfloat64) +/// rtl = RTLSYM.RTLSYM_ARRAYASSADDDOUBLE; +/// else if (t.ty == Tfloat80) +/// rtl = RTLSYM.RTLSYM_ARRAYASSADDREAL; +/// if (e2.op == TOK.TOKmin) +/// { +/// rtl = RTLSYM.RTLSYM_ARRAYASSMINFLOAT; +/// if (t.ty == Tfloat64) +/// rtl = RTLSYM.RTLSYM_ARRAYASSMINDOUBLE; +/// else if (t.ty == Tfloat80) +/// rtl = RTLSYM.RTLSYM_ARRAYASSMINREAL; +/// } +/// +/// /* Set parameters so the order of evaluation is eb, ec, ea +/// */ +/// elem* ep = el_params(eb, ec, ea, null); +/// e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep); +/// goto Lret; +/// } +///} + else + { + /* It's array1[]=array2[] + * which is a memcpy + */ + elem* eto; + elem* efrom; + elem* esize; + elem* ep; + + eto = e1.toElem(irs); + efrom = e2.toElem(irs); + + uint size = cast(uint)t1.nextOf().size(); + esize = el_long(TYM.TYint, size); + + /* Determine if we need to do postblit + */ + int postblit = 0; + if (needsPostblit(t1)) + postblit = 1; + + assert(e2.type.ty != TY.Tpointer); + + if (!postblit && !global.params.useArrayBounds) + { + elem* epto; + elem* epfr; + elem* elen; + elem* ex; + + ex = el_same(&eto); + + // Determine if elen is a constant + if (eto.Eoper == OPER.OPpair && eto.E1.Eoper == OPER.OPconst) + { + elen = el_copytree(eto.E1); + } + else + { + // It's not a constant, so pull it from the dynamic array + elen = el_una(OPER.OP64_32, TYM.TYint, el_copytree(ex)); + } + + esize = el_bin(OPER.OPmul, TYM.TYint, elen, esize); + epto = array_toPtr(e1.type, ex); + epfr = array_toPtr(e2.type, efrom); + static if (true) { + // memcpy() is faster, so if we can't beat 'em, join 'em + e = el_params(esize, epfr, epto, null); + e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[RTLSYM.RTLSYM_MEMCPY]), e); + } else { + e = el_bin(OPER.OPmemcpy, TYM.TYnptr, epto, el_param(epfr, esize)); + } + e = el_pair(eto.Ety, el_copytree(elen), e); + e = el_combine(eto, e); + } +///version (DMDV2) { + else if (postblit && op != TOK.TOKblit) + { + /* Generate: + * _d_arrayassign(ti, efrom, eto) + * or: + * _d_arrayctor(ti, efrom, eto) + */ + el_free(esize); + Expression ti = t1.nextOf().toBasetype().getTypeInfo(null); + ep = el_params(eto, efrom, ti.toElem(irs), null); + int rtl = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYCTOR : RTLSYM.RTLSYM_ARRAYASSIGN; + e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep); + } +///} + else + { + // Generate: + // _d_arraycopy(eto, efrom, esize) + + ep = el_params(eto, efrom, esize, null); + e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCOPY]), ep); + } + el_setLoc(e, loc); + return e; + } + } + + if (e1.op == TOK.TOKindex) + { + elem* eb; + elem* ei; + elem* ev; + TY ty; + Type ta; + + ae = cast(IndexExp)e1; + ta = ae.e1.type.toBasetype(); + ty = ta.ty; + } + +version (DMDV2) { + /* Look for reference initializations + */ + if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar) + { + VarExp ve = cast(VarExp)e1; + Declaration s = ve.var; + if (s.storage_class & STC.STCref) + { +static if (false) { + Expression ae = e2.addressOf(null); + e = ae.toElem(irs); +} else { + e = e2.toElem(irs); + e = addressElem(e, e2.type); +} + elem* es = el_var(s.toSymbol()); + es.Ety = TYM.TYnptr; + e = el_bin(OPER.OPeq, TYM.TYnptr, es, e); + // BUG: type is struct, and e2 is TOKint64 + goto Lret; + } + } +} + +static if (true) { + /* This will work if we can distinguish an assignment from + * an initialization of the lvalue. It'll work if the latter. + * If the former, because of aliasing of the return value with + * function arguments, it'll fail. + */ + if (op == TOK.TOKconstruct && e2.op == TOK.TOKcall) + { + CallExp ce = cast(CallExp)e2; + + Type t = ce.e1.type.toBasetype(); + if (t.ty == TY.Tfunction) { + TypeFunction tf = cast(TypeFunction)t; + if (tf.retStyle() == RET.RETstack) + { + elem* ehidden = e1.toElem(irs); + ehidden = el_una(OPER.OPaddr, TYM.TYnptr, ehidden); + assert(!irs.ehidden); + irs.ehidden = ehidden; + e = e2.toElem(irs); + goto Lret; + } + } + } +} + //printf("test2 %d\n", op); + //if (op == TOK.TOKconstruct) printf("construct\n"); + if (t1b.ty == TY.Tstruct) + { + elem* eleft = e1.toElem(irs); + + if (e2.op == TOK.TOKint64) + { + /* Implement: + * (struct = 0) + * with: + * memset(&struct, 0, struct.sizeof) + */ + elem* ey = null; + int sz = cast(int)e1.type.size(); + StructDeclaration sd = (cast(TypeStruct)t1b).sym; + if (sd.isnested && op == TOK.TOKconstruct) + { + ey = el_una(OPER.OPaddr, TYM.TYnptr, eleft); + eleft = el_same(&ey); + ey = setEthis(loc, irs, ey, sd); + sz = sd.vthis.offset; + } + + elem *el = eleft; + elem *enbytes = el_long(TYM.TYint, sz); + elem *evalue = el_long(TYM.TYint, 0); + + if (!(sd.isnested && op == TOK.TOKconstruct)) + el = el_una(OPER.OPaddr, TYM.TYnptr, el); + + e = el_param(enbytes, evalue); + e = el_bin(OPER.OPmemset, TYM.TYnptr,el,e); + e = el_combine(ey, e); + el_setLoc(e, loc); + //e = el_una(OPER.OPind, TYM.TYstruct, e); + } + else + { + //printf("toElemBin() '%s'\n", toChars()); + + tym_t tym = type.totym(); + + elem* e1 = eleft; + elem* ex = e1; + if (e1.Eoper == OPER.OPind) + ex = e1.E1; + + if (this.e2.op == TOK.TOKstructliteral && ex.Eoper == OPER.OPvar && ex.EV.sp.Voffset == 0) + { + StructLiteralExp se = cast(StructLiteralExp)this.e2; + + Symbol* symSave = se.sym; + size_t soffsetSave = se.soffset; + int fillHolesSave = se.fillHoles; + + se.sym = ex.EV.sp.Vsym; + se.soffset = 0; + se.fillHoles = (op == TOK.TOKconstruct || op == TOK.TOKblit) ? 1 : 0; + + el_free(e1); + e = this.e2.toElem(irs); + + se.sym = symSave; + se.soffset = soffsetSave; + se.fillHoles = fillHolesSave; + } + else + { + elem* e2 = this.e2.toElem(irs); + e = el_bin(OPER.OPstreq,tym,e1,e2); + e.Enumbytes = cast(uint)this.e1.type.size(); + } + goto Lret; + } + } + else + e = toElemBin(irs,OPER.OPeq); + + return e; + + Lret: + el_setLoc(e,loc); return e; } }