Expression *scanVar(Dsymbol *s, InlineScanState *iss) { //printf("scanVar(%s %s)\n", s->kind(), s->toPrettyChars()); VarDeclaration *vd = s->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { for (size_t i = 0; i < td->objects->dim; i++) { DsymbolExp *se = (DsymbolExp *)(*td->objects)[i]; assert(se->op == TOKdsymbol); scanVar(se->s, iss); // TODO } } else if (vd->init) { if (ExpInitializer *ie = vd->init->isExpInitializer()) { Expression *e = ie->exp->inlineScan(iss); if (vd->init != ie) // DeclareExp with vd appears in e return e; ie->exp = e; } } } else { s->inlineScan(); } return NULL; }
Expression *DeclarationExp::interpret(InterState *istate) { #if LOG printf("DeclarationExp::interpret() %s\n", toChars()); #endif Expression *e; VarDeclaration *v = declaration->isVarDeclaration(); if (v) { Dsymbol *s = v->toAlias(); if (s == v && !v->isStatic() && v->init) { ExpInitializer *ie = v->init->isExpInitializer(); if (ie) e = ie->exp->interpret(istate); else if (v->init->isVoidInitializer()) e = NULL; } #if V2 else if (s == v && (v->isConst() || v->isInvariant()) && v->init) #else else if (s == v && v->isConst() && v->init) #endif { e = v->init->toExpression(); if (!e) e = EXP_CANT_INTERPRET; else if (!e->type) e->type = v->type; } } else if (declaration->isAttribDeclaration() ||
void scanVar(Dsymbol *s, InlineScanState *iss) { VarDeclaration *vd = s->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { for (size_t i = 0; i < td->objects->dim; i++) { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; assert(se->op == TOKdsymbol); scanVar(se->s, iss); } } else { // Scan initializer (vd->init) if (vd->init) { ExpInitializer *ie = vd->init->isExpInitializer(); if (ie) { ie->exp = ie->exp->inlineScan(iss); } } } } }
int DeclarationExp::inlineCost3(InlineCostState *ics) { int cost = 0; VarDeclaration *vd; //printf("DeclarationExp::inlineCost3()\n"); vd = declaration->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { #if 1 return COST_MAX; // finish DeclarationExp::doInline #else for (size_t i = 0; i < td->objects->dim; i++) { Object *o = (*td->objects)[i]; if (o->dyncast() != DYNCAST_EXPRESSION) return COST_MAX; Expression *eo = (Expression *)o; if (eo->op != TOKdsymbol) return COST_MAX; } return td->objects->dim; #endif } if (!ics->hdrscan && vd->isDataseg()) return COST_MAX; cost += 1; #if DMDV2 if (vd->edtor) // if destructor required return COST_MAX; // needs work to make this work #endif // Scan initializer (vd->init) if (vd->init) { ExpInitializer *ie = vd->init->isExpInitializer(); if (ie) { cost += expressionInlineCost(ie->exp, ics); } } } // These can contain functions, which when copied, get output twice. if (declaration->isStructDeclaration() || declaration->isClassDeclaration() || declaration->isFuncDeclaration() || declaration->isTypedefDeclaration() || #if DMDV2 declaration->isAttribDeclaration() || #endif declaration->isTemplateMixin()) return COST_MAX; //printf("DeclarationExp::inlineCost3('%s')\n", toChars()); return cost; }
Expression *DeclarationExp::doInline(InlineDoState *ids) { DeclarationExp *de = (DeclarationExp *)copy(); VarDeclaration *vd; //printf("DeclarationExp::doInline(%s)\n", toChars()); vd = declaration->isVarDeclaration(); if (vd) { #if 0 // Need to figure this out before inlining can work for tuples TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { for (size_t i = 0; i < td->objects->dim; i++) { DsymbolExp *se = (DsymbolExp *)td->objects->data[i]; assert(se->op == TOKdsymbol); se->s; } return st->objects->dim; } #endif if (vd->isStatic() || vd->isConst()) ; else { VarDeclaration *vto; vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); *vto = *vd; vto->parent = ids->parent; #if IN_DMD vto->csym = NULL; vto->isym = NULL; #endif ids->from.push(vd); ids->to.push(vto); if (vd->init) { if (vd->init->isVoidInitializer()) { vto->init = new VoidInitializer(vd->init->loc); } else { ExpInitializer *ie = vd->init->isExpInitializer(); assert(ie); vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids)); } } de->declaration = (Dsymbol *) (void *)vto; } } /* This needs work, like DeclarationExp::toElem(), if we are * to handle TemplateMixin's. For now, we just don't inline them. */ return de; }
int DeclarationExp::inlineCost(InlineCostState *ics) { int cost = 0; VarDeclaration *vd; //printf("DeclarationExp::inlineCost()\n"); vd = declaration->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { #if 1 return COST_MAX; // finish DeclarationExp::doInline #else for (size_t i = 0; i < td->objects->dim; i++) { Object *o = (*td->objects)[i]; if (o->dyncast() != DYNCAST_EXPRESSION) return COST_MAX; Expression *eo = (Expression *)o; if (eo->op != TOKdsymbol) return COST_MAX; } return td->objects->dim; #endif } // This breaks on LDC too, since nested static variables have internal // linkage and thus can't be referenced from other objects. if (!ics->hdrscan && vd->isDataseg()) return COST_MAX; cost += 1; // Scan initializer (vd->init) if (vd->init) { ExpInitializer *ie = vd->init->isExpInitializer(); if (ie) { cost += ie->exp->inlineCost(ics); } } } // These can contain functions, which when copied, get output twice. // These break on LDC too, since nested static variables and functions have // internal linkage and thus can't be referenced from other objects. if (declaration->isStructDeclaration() || declaration->isClassDeclaration() || declaration->isFuncDeclaration() || declaration->isTypedefDeclaration() || declaration->isTemplateMixin()) return COST_MAX; //printf("DeclarationExp::inlineCost('%s')\n", toChars()); return cost; }
void scanVar(Dsymbol *s, InlineScanState *iss) { VarDeclaration *vd = s->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { for (size_t i = 0; i < td->objects->dim; i++) { DsymbolExp *se = (DsymbolExp *)td->objects->tdata()[i]; assert(se->op == TOKdsymbol); scanVar(se->s, iss); } } else { // Scan initializer (vd->init) if (vd->init) { ExpInitializer *ie = vd->init->isExpInitializer(); if (ie) { #if DMDV2 if (vd->type) { Type *tb = vd->type->toBasetype(); if (tb->ty == Tstruct) { StructDeclaration *sd = ((TypeStruct *)tb)->sym; if (sd->cpctor) { /* The problem here is that if the initializer is a * function call that returns a struct S with a cpctor: * S s = foo(); * the postblit is done by the return statement in foo() * in s2ir.c, the intermediate code generator. * But, if foo() is inlined and now the code looks like: * S s = x; * the postblit is not there, because such assignments * are rewritten as s.cpctor(&x) by the front end. * So, the inlining won't get the postblit called. * Work around by not inlining these cases. * A proper fix would be to move all the postblit * additions to the front end. */ return; } } } #endif ie->exp = ie->exp->inlineScan(iss); } } } } }
void visit(DeclarationExp *e) { //printf("DeclarationExp::inlineCost3()\n"); VarDeclaration *vd = e->declaration->isVarDeclaration(); if (vd) { TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { cost = COST_MAX; // finish DeclarationExp::doInline return; } if (!hdrscan && vd->isDataseg()) { cost = COST_MAX; return; } if (vd->edtor) { // if destructor required // needs work to make this work cost = COST_MAX; return; } // Scan initializer (vd->init) if (vd->_init) { ExpInitializer *ie = vd->_init->isExpInitializer(); if (ie) { expressionInlineCost(ie->exp); } } cost += 1; } // These can contain functions, which when copied, get output twice. if (e->declaration->isStructDeclaration() || e->declaration->isClassDeclaration() || e->declaration->isFuncDeclaration() || e->declaration->isAttribDeclaration() || e->declaration->isTemplateMixin()) { cost = COST_MAX; return; } //printf("DeclarationExp::inlineCost3('%s')\n", toChars()); }
Expression *DeclarationExp::doInline(InlineDoState *ids) { //printf("DeclarationExp::doInline(%s)\n", toChars()); VarDeclaration *vd = declaration->isVarDeclaration(); if (vd) { #if 0 // Need to figure this out before inlining can work for tuples TupleDeclaration *td = vd->toAlias()->isTupleDeclaration(); if (td) { for (size_t i = 0; i < td->objects->dim; i++) { DsymbolExp *se = (*td->objects)[i]; assert(se->op == TOKdsymbol); se->s; } return st->objects->dim; } #endif if (vd->isStatic()) ; else { VarDeclaration *vto; if (ids->fd && vd == ids->fd->nrvo_var) { for (size_t i = 0; i < ids->from.dim; i++) { if (vd == ids->from[i]) { vto = (VarDeclaration *)ids->to[i]; Expression *e; if (vd->init && !vd->init->isVoidInitializer()) { e = vd->init->toExpression(); assert(e); e = e->doInline(ids); } else e = new IntegerExp(vd->init->loc, 0, Type::tint32); return e; } } } vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init); memcpy((void *)vto, (void *)vd, sizeof(VarDeclaration)); vto->parent = ids->parent; vto->csym = NULL; vto->isym = NULL; ids->from.push(vd); ids->to.push(vto); L1: if (vd->init) { if (vd->init->isVoidInitializer()) { vto->init = new VoidInitializer(vd->init->loc); } else { Expression *e = vd->init->toExpression(); assert(e); vto->init = new ExpInitializer(e->loc, e->doInline(ids)); } } DeclarationExp *de = (DeclarationExp *)copy(); de->declaration = (Dsymbol *) (void *)vto; return de; } } /* This needs work, like DeclarationExp::toElem(), if we are * to handle TemplateMixin's. For now, we just don't inline them. */ return Expression::doInline(ids); }