Mercurial > projects > ddmd
view dmd/StructLiteralExp.d @ 67:f708f0452e81
some of the backend/codegen stuff implemented
author | korDen |
---|---|
date | Mon, 23 Aug 2010 21:21:05 +0400 |
parents | 4290d870944a |
children | 2e2a5c3f943a |
line wrap: on
line source
module dmd.StructLiteralExp; import dmd.Expression; import dmd.MOD; import dmd.TypeStruct; import dmd.TypeSArray; import dmd.expression.Util; import dmd.ErrorExp; import dmd.Dsymbol; import dmd.VarDeclaration; import dmd.StructDeclaration; import dmd.FuncDeclaration; import dmd.ThisDeclaration; import dmd.backend.elem; import dmd.InterState; import dmd.MATCH; import dmd.WANT; import dmd.TY; import dmd.Type; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; import dmd.InlineCostState; import dmd.IRState; import dmd.InlineDoState; import dmd.backend.Symbol; import dmd.HdrGenState; import dmd.backend.dt_t; import dmd.InlineScanState; import dmd.ArrayTypes; import dmd.TOK; import dmd.codegen.Util; import dmd.backend.Util; import dmd.backend.RTLSYM; import dmd.backend.TYM; import dmd.backend.mTY; import dmd.backend.OPER; class StructLiteralExp : Expression { StructDeclaration sd; // which aggregate this is for Expressions elements; // parallels sd->fields[] with // NULL entries for fields to skip Symbol* sym; // back end symbol to initialize with literal size_t soffset; // offset from start of s int fillHoles; // fill alignment 'holes' with zero this(Loc loc, StructDeclaration sd, Expressions elements) { super(loc, TOKstructliteral, StructLiteralExp.sizeof); this.sd = sd; this.elements = elements; this.sym = null; this.soffset = 0; this.fillHoles = 1; } Expression syntaxCopy() { assert(false); } Expression semantic(Scope sc) { Expression e; int nfields = sd.fields.dim - sd.isnested; version (LOGSEMANTIC) { printf("StructLiteralExp.semantic('%s')\n", toChars()); } if (type) return this; // Run semantic() on each element for (size_t i = 0; i < elements.dim; i++) { e = cast(Expression)elements.data[i]; if (!e) continue; e = e.semantic(sc); elements.data[i] = cast(void*)e; } expandTuples(elements); size_t offset = 0; for (size_t i = 0; i < elements.dim; i++) { e = cast(Expression)elements.data[i]; if (!e) continue; if (!e.type) error("%s has no value", e.toChars()); e = resolveProperties(sc, e); if (i >= nfields) { error("more initializers than fields of %s", sd.toChars()); return new ErrorExp(); } Dsymbol s = cast(Dsymbol)sd.fields.data[i]; VarDeclaration v = s.isVarDeclaration(); assert(v); if (v.offset < offset) error("overlapping initialization for %s", v.toChars()); offset = v.offset + cast(uint)v.type.size(); Type telem = v.type; while (!e.implicitConvTo(telem) && telem.toBasetype().ty == Tsarray) { /* Static array initialization, as in: * T[3][5] = e; */ telem = telem.toBasetype().nextOf(); } e = e.implicitCastTo(sc, telem); elements.data[i] = cast(void*)e; } /* Fill out remainder of elements[] with default initializers for fields[] */ for (size_t i = elements.dim; i < nfields; i++) { Dsymbol s = cast(Dsymbol)sd.fields.data[i]; VarDeclaration v = s.isVarDeclaration(); assert(v); assert(!v.isThisDeclaration()); if (v.offset < offset) { e = null; sd.hasUnions = 1; } else { if (v.init) { e = v.init.toExpression(); if (!e) error("cannot make expression out of initializer for %s", v.toChars()); } else { e = v.type.defaultInit(Loc(0)); e.loc = loc; } offset = v.offset + cast(uint)v.type.size(); } elements.push(cast(void*)e); } type = sd.type; return this; } Expression getField(Type type, uint offset) { assert(false); } int getFieldIndex(Type type, uint offset) { assert(false); } elem* toElem(IRState* irs) { elem* e; size_t dim; //printf("StructLiteralExp.toElem() %s\n", toChars()); // struct symbol to initialize with the literal Symbol* stmp = sym ? sym : symbol_genauto(sd.type.toCtype()); e = null; if (fillHoles) { /* Initialize all alignment 'holes' to zero. * Do before initializing fields, as the hole filling process * can spill over into the fields. */ size_t offset = 0; for (size_t i = 0; i < sd.fields.dim; i++) { Dsymbol s = cast(Dsymbol)sd.fields.data[i]; VarDeclaration v = s.isVarDeclaration(); assert(v); e = el_combine(e, fillHole(stmp, &offset, v.offset, sd.structsize)); size_t vend = v.offset + cast(uint)v.type.size(); if (offset < vend) offset = vend; } e = el_combine(e, fillHole(stmp, &offset, sd.structsize, sd.structsize)); } if (elements) { dim = elements.dim; assert(dim <= sd.fields.dim); for (size_t i = 0; i < dim; i++) { Expression el = cast(Expression)elements.data[i]; if (!el) continue; Dsymbol s = cast(Dsymbol)sd.fields.data[i]; VarDeclaration v = s.isVarDeclaration(); assert(v); assert(!v.isThisDeclaration()); elem* e1; if (tybasic(stmp.Stype.Tty) == TYnptr) { e1 = el_var(stmp); e1.EV.sp.Voffset = soffset; } else { e1 = el_ptr(stmp); if (soffset) e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); } e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset)); elem* ec = e1; // pointer to destination elem* ep = el.toElem(irs); Type t1b = v.type.toBasetype(); Type t2b = el.type.toBasetype(); if (t1b.ty == Tsarray) { if (t2b.implicitConvTo(t1b)) { ///version (DMDV2) { // Determine if postblit is needed int postblit = 0; if (needsPostblit(t1b)) postblit = 1; if (postblit) { /* Generate: * _d_arrayctor(ti, From: ep, To: e1) */ Expression ti = t1b.nextOf().toBasetype().getTypeInfo(null); elem* esize = el_long(TYsize_t, (cast(TypeSArray)t1b).dim.toInteger()); e1 = el_pair(TYdarray, esize, e1); ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el.type, ep)); ep = el_params(e1, ep, ti.toElem(irs), null); int rtl = RTLSYM_ARRAYCTOR; e1 = el_bin(OPcall, type.totym(), el_var(rtlsym[rtl]), ep); } else ///} { elem* esize = el_long(TYsize_t, t1b.size()); ep = array_toPtr(el.type, ep); e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize)); } } else { elem* edim = el_long(TYsize_t, t1b.size() / t2b.size()); e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct); } } else { tym_t ty = v.type.totym(); e1 = el_una(OPind, ty, e1); if (tybasic(ty) == TYstruct) e1.Enumbytes = cast(uint)v.type.size(); e1 = el_bin(OPeq, ty, e1, ep); if (tybasic(ty) == TYstruct) { e1.Eoper = OPstreq; e1.Enumbytes = cast(uint)v.type.size(); } version (DMDV2) { /* Call postblit() on e1 */ StructDeclaration sd = needsPostblit(v.type); if (sd) { FuncDeclaration fd = sd.postblit; ec = el_copytree(ec); ec = callfunc(loc, irs, 1, Type.tvoid, ec, sd.type.pointerTo(), fd, fd.type, null, null); e1 = el_bin(OPcomma, ec.Ety, e1, ec); } } } e = el_combine(e, e1); } } version (DMDV2) { if (sd.isnested) { // Initialize the hidden 'this' pointer assert(sd.fields.dim); Dsymbol s = cast(Dsymbol)sd.fields.data[sd.fields.dim - 1]; ThisDeclaration v = s.isThisDeclaration(); assert(v); elem* e1; if (tybasic(stmp.Stype.Tty) == TYnptr) { e1 = el_var(stmp); e1.EV.sp.Voffset = soffset; } else { e1 = el_ptr(stmp); if (soffset) e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); } e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset)); e1 = setEthis(loc, irs, e1, sd); e = el_combine(e, e1); } } elem* ev = el_var(stmp); ev.Enumbytes = sd.structsize; e = el_combine(e, ev); el_setLoc(e,loc); return e; } bool checkSideEffect(int flag) { assert(false); } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); } void toMangleBuffer(OutBuffer buf) { assert(false); } void scanForNestedRef(Scope sc) { assert(false); } Expression optimize(int result) { if (elements) { for (size_t i = 0; i < elements.dim; i++) { Expression e = cast(Expression)elements.data[i]; if (!e) continue; e = e.optimize(WANTvalue | (result & WANTinterpret)); elements.data[i] = cast(void*)e; } } return this; } Expression interpret(InterState istate) { assert(false); } dt_t** toDt(dt_t** pdt) { assert(false); } int isLvalue() { assert(false); } Expression toLvalue(Scope sc, Expression e) { assert(false); } bool canThrow() { return arrayExpressionCanThrow(elements); } MATCH implicitConvTo(Type t) { static if (false) { printf("StructLiteralExp.implicitConvTo(this=%.*s, type=%.*s, t=%.*s)\n", toChars(), type.toChars(), t.toChars()); } MATCH m = Expression.implicitConvTo(t); if (m != MATCHnomatch) return m; if (type.ty == t.ty && type.ty == Tstruct && (cast(TypeStruct)type).sym == (cast(TypeStruct)t).sym) { m = MATCHconst; for (int i = 0; i < elements.dim; i++) { Expression e = cast(Expression)elements.data[i]; Type te = e.type; if (t.mod == 0) te = te.mutableOf(); else { assert(t.mod == MODinvariant); te = te.invariantOf(); } MATCH m2 = e.implicitConvTo(te); //printf("\t%s => %s, match = %d\n", e.toChars(), te.toChars(), m2); if (m2 < m) m = m2; } } return m; } int inlineCost(InlineCostState* ics) { assert(false); } Expression doInline(InlineDoState ids) { assert(false); } Expression inlineScan(InlineScanState* iss) { assert(false); } }