diff dmd/StructInitializer.d @ 67:f708f0452e81

some of the backend/codegen stuff implemented
author korDen
date Mon, 23 Aug 2010 21:21:05 +0400
parents 51605de93870
children 2e2a5c3f943a
line wrap: on
line diff
--- a/dmd/StructInitializer.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/StructInitializer.d	Mon Aug 23 21:21:05 2010 +0400
@@ -2,6 +2,7 @@
 
 import dmd.Initializer;
 import dmd.TOK;
+import dmd.TypeSArray;
 import dmd.FuncLiteralDeclaration;
 import dmd.TypeFunction;
 import dmd.StructDeclaration;
@@ -27,6 +28,7 @@
 import dmd.LINK;
 
 import dmd.backend.dt_t;
+import dmd.backend.Util;
 
 class StructInitializer : Initializer
 {
@@ -219,7 +221,122 @@
 
     dt_t* toDt()
 	{
-		assert(false);
+		scope Array dts = new Array();
+		uint i;
+		uint j;
+		dt_t* dt;
+		dt_t* d;
+		dt_t** pdtend;
+		uint offset;
+
+		//printf("StructInitializer.toDt('%s')\n", toChars());
+		dts.setDim(ad.fields.dim);
+		dts.zero();
+
+		for (i = 0; i < vars.dim; i++)
+		{
+			VarDeclaration v = cast(VarDeclaration)vars.data[i];
+			Initializer val = cast(Initializer)value.data[i];
+
+			//printf("vars[%d] = %s\n", i, v.toChars());
+
+			for (j = 0; 1; j++)
+			{
+				assert(j < dts.dim);
+				//printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad.fields.data[j]).toChars());
+				if (cast(VarDeclaration)ad.fields.data[j] == v)
+				{
+					if (dts.data[j])
+						error(loc, "field %s of %s already initialized", v.toChars(), ad.toChars());
+					dts.data[j] = cast(void*)val.toDt();
+					break;
+				}
+			}
+		}
+
+		dt = null;
+		pdtend = &dt;
+		offset = 0;
+		for (j = 0; j < dts.dim; j++)
+		{
+			VarDeclaration v = cast(VarDeclaration)ad.fields.data[j];
+
+			d = cast(dt_t*)dts.data[j];
+			if (!d)
+			{   
+				// An instance specific initializer was not provided.
+				// Look to see if there's a default initializer from the
+				// struct definition
+				if (v.init)
+				{
+					d = v.init.toDt();
+				}
+				else if (v.offset >= offset)
+				{
+					uint k;
+					uint offset2 = v.offset + cast(uint)v.type.size();
+					// Make sure this field does not overlap any explicitly
+					// initialized field.
+					for (k = j + 1; 1; k++)
+					{
+						if (k == dts.dim)		// didn't find any overlap
+						{
+							v.type.toDt(&d);
+							break;
+						}
+						VarDeclaration v2 = cast(VarDeclaration)ad.fields.data[k];
+
+						if (v2.offset < offset2 && dts.data[k])
+							break;			// overlap
+					}
+				}
+			}
+			if (d)
+			{
+				if (v.offset < offset)
+					error(loc, "duplicate union initialization for %s", v.toChars());
+				else
+				{	
+					uint sz = dt_size(d);
+					uint vsz = cast(uint)v.type.size();
+					uint voffset = v.offset;
+
+					uint dim = 1;
+					for (Type vt = v.type.toBasetype();
+						 vt.ty == Tsarray;
+						 vt = vt.nextOf().toBasetype())
+					{   
+						TypeSArray tsa = cast(TypeSArray)vt;
+						dim *= tsa.dim.toInteger();
+					}
+					assert(sz == vsz || sz * dim <= vsz);
+
+					for (size_t k = 0; k < dim; k++)
+					{
+						if (offset < voffset)
+							pdtend = dtnzeros(pdtend, voffset - offset);
+						if (!d)
+						{
+							if (v.init)
+								d = v.init.toDt();
+							else
+								v.type.toDt(&d);
+						}
+						pdtend = dtcat(pdtend, d);
+						d = null;
+						offset = voffset + sz;
+						voffset += vsz / dim;
+						if (sz == vsz)
+							break;
+					}
+				}
+			}
+		}
+		
+		if (offset < ad.structsize)
+			dtnzeros(pdtend, ad.structsize - offset);
+
+		return dt;
 	}
 
     StructInitializer isStructInitializer() { return this; }