diff 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 diff
--- a/dmd/StructLiteralExp.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/StructLiteralExp.d	Mon Aug 23 21:21:05 2010 +0400
@@ -3,11 +3,14 @@
 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;
@@ -27,6 +30,13 @@
 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
 {
@@ -158,7 +168,169 @@
 
 	elem* toElem(IRState* irs)
 	{
-		assert(false);
+		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)