static dt_t *createTsarrayDt(dt_t * dt, Type *t) { assert(dt != NULL); size_t eoa_size = dt_size(dt); if (eoa_size == t->size()) return dt; else { TypeSArray * tsa = (TypeSArray *) t->toBasetype(); assert(tsa->ty == Tsarray); size_t dim = tsa->dim->toInteger(); dt_t * adt = NULL; dt_t ** padt = & adt; if (eoa_size * dim == eoa_size) { for (size_t i = 0; i < dim; i++) padt = dtcontainer(padt, NULL, dt); } else { assert(tsa->size(0) % eoa_size == 0); for (size_t i = 0; i < dim; i++) padt = dtcontainer(padt, NULL, createTsarrayDt(dt, tsa->next)); } dt_t * cdt = NULL; dtcontainer(& cdt, t, adt); return cdt; } }
void StructDeclaration::toDt(dt_t **pdt) { if (zeroInit) { dtnzeros(pdt, structsize); return; } unsigned offset; dt_t *dt; dt_t *sdt = NULL; //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); offset = 0; // Note equivalence of this loop to class's for (size_t i = 0; i < fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)fields.data[i]; Initializer *init; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; init = v->init; if (init) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) v->type->toDt(&dt); if (dt) { if (v->offset < offset) error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); else { if (offset < v->offset) dtnzeros(&sdt, v->offset - offset); dtcat(&sdt, dt); offset = v->offset + v->type->size(); } } } if (offset < structsize) dtnzeros(&sdt, structsize - offset); #ifdef IN_GCC dtcontainer(pdt, type, sdt); #else dtcat(pdt, sdt); #endif dt_optimize(*pdt); }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); Type *tn = tb->next->toBasetype(); if (tn->ty == Tbit) return toDtBit(); Array dts; unsigned size; unsigned length; 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 (size_t i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = (Expression *)index.data[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = (Initializer *)value.data[i]; dt = val->toDt(); if (dts.data[length]) error(loc, "duplicate initializations for index %d", length); dts.data[length] = (void *)dt; length++; } Expression *edefault = tb->next->defaultInit(); #ifdef IN_GCC dt_t * sadefault = NULL; if (tn->ty == Tsarray) tn->toDt(& sadefault); else edefault->toDt(& sadefault); #else unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->next->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } #endif d = NULL; pdtend = &d; for (size_t i = 0; i < dim; i++) { dt = (dt_t *)dts.data[i]; #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault); #else if (dt) pdtend = dtcat(pdtend, dt); else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } 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 // (ok for GDC as well) pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (size_t i = dim; i < tadim; i++) #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, sadefault); #else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } } else if (dim > tadim) { #ifdef DEBUG printf("1: "); #endif error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(& cdt, type, d); d = cdt; #endif break; } case Tpointer: case Tarray: { // Create symbol, and then refer to it Symbol *s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); #ifdef IN_GCC dt_t * cdt; cdt = NULL; if (tb->ty == Tarray) { dtcontainer(& cdt, type, d); d = cdt; } #endif break; } default: assert(0); } return d; }
dt_t *StructInitializer::toDt() { Array dts; 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 (size_t i = 0; i < vars.dim; i++) { VarDeclaration *v = (VarDeclaration *)vars.data[i]; Initializer *val = (Initializer *)value.data[i]; //printf("vars[%d] = %s\n", i, v->toChars()); for (size_t j = 0; 1; j++) { assert(j < dts.dim); //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad->fields.data[j])->toChars()); if ((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] = (void *)val->toDt(); break; } } } dt = NULL; pdtend = &dt; offset = 0; for (size_t j = 0; j < dts.dim; j++) { VarDeclaration *v = (VarDeclaration *)ad->fields.data[j]; d = (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) { 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 = (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 { size_t sz = dt_size(d); size_t vsz = v->type->size(); size_t 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->next->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); #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(&cdt, ad->type, dt); dt = cdt; #endif return dt; }
dt_t *ArrayInitializer::toDt() { //printf("ArrayInitializer::toDt('%s')\n", toChars()); Type *tb = type->toBasetype(); if (tb->ty == Tvector) tb = ((TypeVector *)tb)->basetype; Type *tn = tb->nextOf()->toBasetype(); Dts dts; unsigned size; unsigned length; 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 (size_t i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = index[i]; if (idx) length = idx->toInteger(); //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); val = value[i]; dt = val->toDt(); if (dts[length]) error(loc, "duplicate initializations for index %d", length); if (tn->ty == Tsarray) dt = createTsarrayDt(dt, tb->nextOf()); dts[length] = dt; length++; } Expression *edefault = tb->nextOf()->defaultInit(); #ifdef IN_GCC dt_t * sadefault = NULL; if (tn->ty == Tsarray) tn->toDt(& sadefault); else edefault->toDt(& sadefault); #else unsigned n = 1; for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype()) { TypeSArray *tsa = (TypeSArray *)tbn; n *= tsa->dim->toInteger(); } #endif d = NULL; pdtend = &d; for (size_t i = 0; i < dim; i++) { dt = dts[i]; #ifdef IN_GCC pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault); #else if (dt) pdtend = dtcat(pdtend, dt); else { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } #endif } switch (tb->ty) { case Tsarray: { unsigned tadim; TypeSArray *ta = (TypeSArray *)tb; tadim = ta->dim->toInteger(); if (dim < tadim) { #ifdef IN_GCC // Pad out the rest of the array with single elements. // Otherwise breaks -fsection-anchors on ARM when // backend calculates field positions for array members. for (size_t i = dim; i < tadim; i++) pdtend = dtcontainer(pdtend, NULL, sadefault); #else if (edefault->isBool(FALSE)) // pad out end of array pdtend = dtnzeros(pdtend, size * (tadim - dim)); else { for (size_t i = dim; i < tadim; i++) { for (size_t j = 0; j < n; j++) pdtend = edefault->toDt(pdtend); } } #endif } else if (dim > tadim) { error(loc, "too many initializers, %d, for array[%d]", dim, tadim); } #ifdef IN_GCC dt_t * cdt = NULL; dtcontainer(& cdt, type, d); d = cdt; #endif break; } case Tpointer: case Tarray: { // Create symbol, and then refer to it Symbol *s = static_sym(); s->Sdt = d; outdata(s); d = NULL; if (tb->ty == Tarray) dtsize_t(&d, dim); dtxoff(&d, s, 0, TYnptr); #ifdef IN_GCC dt_t * cdt; cdt = NULL; if (tb->ty == Tarray) { dtcontainer(& cdt, type, d); d = cdt; } #endif break; } default: assert(0); } return d; }