Mercurial > projects > ddmd
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; }