dt_t *StructInitializer::toDt() { Dts dts; unsigned i; unsigned j; dt_t *dt; dt_t *d; dt_t **pdtend; unsigned offset; //printf("StructInitializer::toDt('%s')\n", toChars()); dts.setDim(ad->fields.dim); dts.zero(); for (i = 0; i < vars.dim; i++) { VarDeclaration *v = vars.tdata()[i]; Initializer *val = value.tdata()[i]; //printf("vars[%d] = %s\n", i, v->toChars()); for (j = 0; 1; j++) { assert(j < dts.dim); //printf(" adfield[%d] = %s\n", j, (ad->fields.tdata()[j])->toChars()); if (ad->fields.tdata()[j] == v) { if (dts.tdata()[j]) error(loc, "field %s of %s already initialized", v->toChars(), ad->toChars()); dts.tdata()[j] = val->toDt(); break; } } } dt = NULL; pdtend = &dt; offset = 0; for (j = 0; j < dts.dim; j++) { VarDeclaration *v = ad->fields.tdata()[j]; d = dts.tdata()[j]; if (!d) { // An instance specific initializer was not provided. // Look to see if there's a default initializer from the // struct definition VarDeclaration *v = ad->fields.tdata()[j]; if (v->init) { d = v->init->toDt(); } else if (v->offset >= offset) { unsigned k; unsigned offset2 = v->offset + 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 = ad->fields.tdata()[k]; if (v2->offset < offset2 && dts.tdata()[k]) break; // overlap } } } if (d) { if (v->offset < offset) error(loc, "duplicate union initialization for %s", v->toChars()); else { unsigned sz = dt_size(d); unsigned vsz = v->type->size(); unsigned voffset = v->offset; if (sz > vsz) { assert(v->type->ty == Tsarray && vsz == 0); error(loc, "zero length array %s has non-zero length initializer", v->toChars()); } unsigned dim = 1; for (Type *vt = v->type->toBasetype(); vt->ty == Tsarray; vt = vt->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)vt; dim *= tsa->dim->toInteger(); } //printf("sz = %d, dim = %d, vsz = %d\n", sz, dim, vsz); assert(sz == vsz || sz * dim <= vsz); for (size_t i = 0; i < dim; i++) { 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; }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); Type *tn = tb->nextOf()->toBasetype(); Dts dts; unsigned size; unsigned length; unsigned i; dt_t *dt; dt_t *d; dt_t **pdtend; //printf("\tdim = %d\n", dim); dts.setDim(dim); dts.zero(); size = tn->size(); length = 0; for (i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = index.tdata()[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = value.tdata()[i]; dt = val->toDt(); if (dts.tdata()[length]) error(loc, "duplicate initializations for index %d", length); dts.tdata()[length] = dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } d = NULL; pdtend = &d; for (i = 0; i < dim; i++) { dt = dts.tdata()[i]; if (dt) pdtend = dtcat(pdtend, dt); else { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { if (edefault->isBool(FALSE)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (i = dim; i < tadim; i++) { for (int j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } } else if (dim > tadim) { #ifdef DEBUG printf("1: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } break; } case Tpointer: case Tarray: // Create symbol, and then refer to it Symbol *s; s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); break; default: assert(0); } return d; }