Skip to content

Commit

Permalink
Merge pull request #5392 from WalterBright/membersToDt
Browse files Browse the repository at this point in the history
refactor: merge two membersToDt() into one
  • Loading branch information
ibuclaw committed Feb 1, 2016
2 parents cdb49cd + eb2dba5 commit f1042c4
Showing 1 changed file with 58 additions and 158 deletions.
216 changes: 58 additions & 158 deletions src/todt.c
@@ -1,6 +1,6 @@

/* Compiler implementation of the D programming language
* Copyright (c) 1999-2014 by Digital Mars
* Copyright (c) 1999-2016 by Digital Mars
* All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
Expand Down Expand Up @@ -42,8 +42,8 @@ dt_t **Type_toDt(Type *t, dt_t **pdt);
dt_t **toDtElem(TypeSArray *tsa, dt_t **pdt, Expression *e);
dt_t **ClassDeclaration_toDt(ClassDeclaration *cd, dt_t **pdt);
dt_t **StructDeclaration_toDt(StructDeclaration *sd, dt_t **pdt);
dt_t **membersToDt(AggregateDeclaration *cd, dt_t **pdt, ClassDeclaration * = NULL);
dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt, Expressions *elements, size_t = 0, ClassDeclaration * = NULL);
//static dt_t **membersToDt(AggregateDeclaration *cd, dt_t **pdt, ClassDeclaration * = NULL);
static dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt, Expressions *elements, size_t, ClassDeclaration *);
dt_t **ClassReferenceExp_toDt(ClassReferenceExp *e, dt_t **pdt, int off);
dt_t **ClassReferenceExp_toInstanceDt(ClassReferenceExp *ce, dt_t **pdt);
Symbol *toSymbol(Dsymbol *s);
Expand Down Expand Up @@ -459,7 +459,7 @@ dt_t **Expression_toDt(Expression *e, dt_t **pdt)
{
//printf("StructLiteralExp::toDt() %s, ctfe = %d\n", sle->toChars(), sle->ownedByCtfe);
assert(sle->sd->fields.dim - sle->sd->isNested() <= sle->elements->dim);
pdt = membersToDt(sle->sd, pdt, sle->elements);
pdt = membersToDt(sle->sd, pdt, sle->elements, 0, NULL);
}

void visit(SymOffExp *e)
Expand Down Expand Up @@ -596,7 +596,7 @@ dt_t **ClassDeclaration_toDt(ClassDeclaration *cd, dt_t **pdt)
pdt = dtsize_t(pdt, 0); // monitor

// Put in the rest
pdt = membersToDt(cd, pdt, cd);
pdt = membersToDt(cd, pdt, NULL, 0, cd);

//printf("-ClassDeclaration::toDt(this = '%s')\n", cd->toChars());
return pdt;
Expand All @@ -605,7 +605,7 @@ dt_t **ClassDeclaration_toDt(ClassDeclaration *cd, dt_t **pdt)
dt_t **StructDeclaration_toDt(StructDeclaration *sd, dt_t **pdt)
{
//printf("+StructDeclaration::toDt(), this='%s'\n", sd->toChars());
pdt = membersToDt(sd, pdt);
pdt = membersToDt(sd, pdt, NULL, 0, NULL);

//printf("-StructDeclaration::toDt(), this='%s'\n", sd->toChars());
return pdt;
Expand Down Expand Up @@ -642,19 +642,22 @@ dt_t **cpp_type_info_ptr_toDt(ClassDeclaration *cd, dt_t **pdt)
* have to use this optimized version to reduce memory footprint.
* Params:
* ad = aggregate with members
* pdt = tail of initializer list
* pdt = tail of initializer list to start appending initialized data to
* elements = values to use as initializers, NULL means use default initializers
* firstFieldIndex = starting place is elements[firstFieldIndex]
* concreteType = structs: null, classes: top level class
* Returns:
* updated tail of dt_t list
*/
dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
static dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
Expressions *elements, size_t firstFieldIndex,
ClassDeclaration *concreteType)
{
//printf("membersToDt(ad = '%s')\n", ad->toChars());
ClassDeclaration *cd = ad->isClassDeclaration();

/* Order:
* { base class } or { __vptr, __monitor)
* { base class } or { __vptr, __monitor }
* interfaces
* fields
*/
Expand All @@ -664,7 +667,10 @@ dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
{
if (ClassDeclaration *cdb = cd->baseClass)
{
pdt = membersToDt(cdb, pdt, concreteType);
size_t index = 0;
for (ClassDeclaration *c = cdb->baseClass; c; c = c->baseClass)
index += c->fields.dim;
pdt = membersToDt(cdb, pdt, elements, index, concreteType);
offset = cdb->structsize;
}
else
Expand Down Expand Up @@ -702,9 +708,15 @@ dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
}
}

assert(!elements ||
firstFieldIndex <= elements->dim &&
firstFieldIndex + ad->fields.dim <= elements->dim);

for (size_t i = 0; i < ad->fields.dim; i++)
{
if (ad->fields[i]->_init && ad->fields[i]->_init->isVoidInitializer())
if (elements && !(*elements)[firstFieldIndex + i])
continue;
else if (ad->fields[i]->_init && ad->fields[i]->_init->isVoidInitializer())
continue;

VarDeclaration *vd = NULL;
Expand All @@ -714,8 +726,12 @@ dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
VarDeclaration *v2 = ad->fields[j];
if (v2->offset < offset)
continue;

if (elements && !(*elements)[firstFieldIndex + j])
continue;
if (v2->_init && v2->_init->isVoidInitializer())
continue;

// find the nearest field
if (!vd || v2->offset < vd->offset)
{
Expand All @@ -732,164 +748,47 @@ dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
pdt = dtnzeros(pdt, vd->offset - offset);

dt_t *dt = NULL;
if (Initializer *init = vd->_init)
if (elements)
{
//printf("\t\t%s has initializer %s\n", vd->toChars(), init->toChars());
if (init->isVoidInitializer())
continue;

/* Because of issue 14666, function local import does not invoke
* semantic2 pass for the imported module, and surprisingly there's
* no opportunity to do it today.
* As a workaround for the issue 9057, have to resolve forward reference
* in `init` before its use.
*/
if (vd->sem < Semantic2Done && vd->_scope)
vd->semantic2(vd->_scope);

ExpInitializer *ei = init->isExpInitializer();
Expression *e = (*elements)[firstFieldIndex + k];
Type *tb = vd->type->toBasetype();
if (ei && tb->ty == Tsarray)
toDtElem(((TypeSArray *)tb), &dt, ei->exp);
if (tb->ty == Tsarray)
toDtElem(((TypeSArray *)tb), &dt, e);
else
Initializer_toDt(init, &dt);
}
else if (offset <= vd->offset)
{
//printf("\t\tdefault initializer\n");
Type_toDt(vd->type, &dt);
}
if (!dt)
continue;

pdt = dtcat(pdt, dt);
offset = vd->offset + vd->type->size();
}

if (cd && !cd->cpp)
{
// Interface vptr initializations
toSymbol(cd); // define csym

for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
{
BaseClass *b = (*cd->vtblInterfaces)[i];
for (ClassDeclaration *cd2 = concreteType; 1; cd2 = cd2->baseClass)
{
assert(cd2);
unsigned csymoffset = baseVtblOffset(cd2, b);
if (csymoffset != ~0)
{
if (offset < b->offset)
pdt = dtnzeros(pdt, b->offset - offset);
pdt = dtxoff(pdt, toSymbol(cd2), csymoffset);
break;
}
}
offset = b->offset + Target::ptrsize;
}
}

if (offset < ad->structsize)
pdt = dtnzeros(pdt, ad->structsize - offset);

return pdt;
}

/****************************************************
* Put out elements[].
*/
dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
Expressions *elements, size_t firstFieldIndex,
ClassDeclaration *concreteType)
{
//printf("membersToDt(ad = '%s', elements = %s)\n", ad->toChars(), elements->toChars());
ClassDeclaration *cd = ad->isClassDeclaration();

unsigned offset;
if (cd)
{
if (ClassDeclaration *cdb = cd->baseClass)
{
size_t index = 0;
for (ClassDeclaration *c = cdb->baseClass; c; c = c->baseClass)
index += c->fields.dim;
pdt = membersToDt(cdb, pdt, elements, index, concreteType);
offset = cdb->structsize;
Expression_toDt(e, &dt); // convert e to an initializer dt
}
else
{
if (cd->cpp)
offset = Target::ptrsize; // allow room for __vptr
else
offset = Target::ptrsize * 2; // allow room for __vptr and __monitor
}
}
else
offset = 0;

if (cd && cd->cpp)
{
// Interface vptr initializations
toSymbol(cd); // define csym

for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
{
BaseClass *b = (*cd->vtblInterfaces)[i];
for (ClassDeclaration *cd2 = concreteType; 1; cd2 = cd2->baseClass)
if (Initializer *init = vd->_init)
{
assert(cd2);
unsigned csymoffset = baseVtblOffset(cd2, b);
if (csymoffset != ~0)
{
if (offset < b->offset)
pdt = dtnzeros(pdt, b->offset - offset);
pdt = dtxoff(pdt, toSymbol(cd2), csymoffset);
break;
}
}
offset = b->offset + Target::ptrsize;
}
}

assert(firstFieldIndex <= elements->dim &&
firstFieldIndex + ad->fields.dim <= elements->dim);
for (size_t i = 0; i < ad->fields.dim; i++)
{
if (!(*elements)[firstFieldIndex + i])
continue;
//printf("\t\t%s has initializer %s\n", vd->toChars(), init->toChars());
if (init->isVoidInitializer())
continue;

/* Because of issue 14666, function local import does not invoke
* semantic2 pass for the imported module, and surprisingly there's
* no opportunity to do it today.
* As a workaround for the issue 9057, have to resolve forward reference
* in `init` before its use.
*/
if (vd->sem < Semantic2Done && vd->_scope)
vd->semantic2(vd->_scope);

VarDeclaration *vd = NULL;
size_t k;
for (size_t j = i; j < ad->fields.dim; j++)
{
VarDeclaration *v2 = ad->fields[j];
if (v2->offset < offset)
continue;
if (!(*elements)[firstFieldIndex + j])
continue;
// find the nearest field
if (!vd || v2->offset < vd->offset)
ExpInitializer *ei = init->isExpInitializer();
Type *tb = vd->type->toBasetype();
if (ei && tb->ty == Tsarray)
toDtElem(((TypeSArray *)tb), &dt, ei->exp);
else
Initializer_toDt(init, &dt);
}
else if (offset <= vd->offset)
{
vd = v2;
k = j;
assert(vd == v2 || !vd->isOverlappedWith(v2));
//printf("\t\tdefault initializer\n");
Type_toDt(vd->type, &dt);
}
if (!dt)
continue;
}
if (!vd)
continue;

assert(offset <= vd->offset);
if (offset < vd->offset)
pdt = dtnzeros(pdt, vd->offset - offset);

dt_t *dt = NULL;
Expression *e = (*elements)[firstFieldIndex + k];
Type *tb = vd->type->toBasetype();
if (tb->ty == Tsarray)
toDtElem(((TypeSArray *)tb), &dt, e);
else
Expression_toDt(e, &dt); // convert e to an initializer dt

pdt = dtcat(pdt, dt);
offset = vd->offset + vd->type->size();
Expand Down Expand Up @@ -925,6 +824,7 @@ dt_t **membersToDt(AggregateDeclaration *ad, dt_t **pdt,
return pdt;
}


/* ================================================================= */

dt_t **Type_toDt(Type *t, dt_t **pdt)
Expand Down

0 comments on commit f1042c4

Please sign in to comment.