Expression *EqualExp::optimize(int result, bool keepLvalue) { //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); Expression *e1 = fromConstInitializer(result, this->e1); Expression *e2 = fromConstInitializer(result, this->e2); Expression *e = Equal(op, type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; }
Expression *CmpExp::optimize(int result) { Expression *e; //printf("CmpExp::optimize() %s\n", toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); Expression *e1 = fromConstInitializer(result, this->e1); Expression *e2 = fromConstInitializer(result, this->e2); e = Cmp(op, type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; }
Expression *SliceExp::optimize(int result) { Expression *e; //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); e = this; e1 = e1->optimize(WANTvalue | (result & (WANTinterpret|WANTexpand))); if (!lwr) { if (e1->op == TOKstring) { // Convert slice of string literal into dynamic array Type *t = e1->type->toBasetype(); if (t->nextOf()) e = e1->castTo(NULL, t->nextOf()->arrayOf()); } return e; } e1 = fromConstInitializer(result, e1); // We might know $ now setLengthVarIfKnown(lengthVar, e1); lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); upr = upr->optimize(WANTvalue | (result & WANTinterpret)); e = Slice(type, e1, lwr, upr); if (e == EXP_CANT_INTERPRET) e = this; //printf("-SliceExp::optimize() %s\n", e->toChars()); return e; }
Expression *IndexExp::optimize(int result) { Expression *e; //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); Expression *e1 = this->e1->optimize( WANTvalue | (result & (WANTinterpret| WANTexpand))); e1 = fromConstInitializer(result, e1); if (this->e1->op == TOKvar) { VarExp *ve = (VarExp *)this->e1; if (ve->var->storage_class & STCmanifest) { /* We generally don't want to have more than one copy of an * array literal, but if it's an enum we have to because the * enum isn't stored elsewhere. See Bugzilla 2559 */ this->e1 = e1; } } // We might know $ now setLengthVarIfKnown(lengthVar, e1); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = Index(type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; }
Expression *VarExp::optimize(int result) { if (result & WANTinterpret) { return fromConstInitializer(this); } return this; }
Expression *IndexExp::optimize(int result) { Expression *e; //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); Expression *e1 = this->e1->optimize(WANTvalue | (result & WANTinterpret)); e1 = fromConstInitializer(result, e1); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = Index(type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; }
Expression *CastExp::optimize(int result) { //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); //printf("from %s to %s\n", type->toChars(), to->toChars()); //printf("from %s\n", type->toChars()); //printf("e1->type %s\n", e1->type->toChars()); //printf("type = %p\n", type); assert(type); enum TOK op1 = e1->op; #define X 0 e1 = e1->optimize(result); e1 = fromConstInitializer(result, e1); if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && e1->type->nextOf()->size() == type->nextOf()->size() ) { e1 = e1->castTo(NULL, type); if (X) printf(" returning1 %s\n", e1->toChars()); return e1; } if (e1->op == TOKstructliteral && e1->type->implicitConvTo(type) >= MATCHconst) { e1->type = type; if (X) printf(" returning2 %s\n", e1->toChars()); return e1; } /* The first test here is to prevent infinite loops */ if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) return e1->castTo(NULL, to); if (e1->op == TOKnull && (type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray)) { e1->type = type; if (X) printf(" returning3 %s\n", e1->toChars()); return e1; } if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) { // See if we can remove an unnecessary cast ClassDeclaration *cdfrom; ClassDeclaration *cdto; int offset; cdfrom = e1->type->isClassHandle(); cdto = type->isClassHandle(); if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) { e1->type = type; if (X) printf(" returning4 %s\n", e1->toChars()); return e1; } } // We can convert 'head const' to mutable if (to->constOf()->equals(e1->type->constOf())) // if (to->constConv(e1->type) >= MATCHconst) { e1->type = type; if (X) printf(" returning5 %s\n", e1->toChars()); return e1; } Expression *e; if (e1->isConst()) { if (e1->op == TOKsymoff) { if (type->size() == e1->type->size() && type->toBasetype()->ty != Tsarray) { e1->type = type; return e1; } return this; } if (to->toBasetype()->ty == Tvoid) e = this; else e = Cast(type, to, e1); } else e = this; if (X) printf(" returning6 %s\n", e->toChars()); return e; #undef X }
Expression *VarExp::optimize(int result) { return fromConstInitializer(result, this); }
Dsymbol *ArrayScopeSymbol::search(Loc loc, Identifier *ident, int flags) { //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident->toChars(), flags); if (ident == Id::length || ident == Id::dollar) { VarDeclaration **pvar; Expression *ce; L1: if (td) { VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(0, td->objects->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCstatic | STCconst; v->semantic(sc); return v; } if (type) { VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); Expression *e = new IntegerExp(0, type->arguments->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCstatic | STCconst; v->semantic(sc); return v; } if (exp->op == TOKindex) { IndexExp *ie = (IndexExp *)exp; pvar = &ie->lengthVar; ce = ie->e1; } else if (exp->op == TOKslice) { SliceExp *se = (SliceExp *)exp; pvar = &se->lengthVar; ce = se->e1; } else return NULL; if (ce->op == TOKtype) { Type *t = ((TypeExp *)ce)->type; if (t->ty == Ttuple) { type = (TypeTuple *)t; goto L1; } } if (!*pvar) { VarDeclaration *v = new VarDeclaration(loc, Type::tsize_t, Id::dollar, NULL); if (ce->op == TOKvar) { // if ce is const, get its initializer ce = fromConstInitializer(WANTvalue | WANTinterpret, ce); } if (ce->op == TOKstring) { /* It is for a string literal, so the * length will be a const. */ Expression *e = new IntegerExp(0, ((StringExp *)ce)->len, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCstatic | STCconst; } else if (ce->op == TOKarrayliteral) { /* It is for an array literal, so the * length will be a const. */ Expression *e = new IntegerExp(0, ((ArrayLiteralExp *)ce)->elements->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCstatic | STCconst; } else if (ce->op == TOKtuple) { /* It is for an expression tuple, so the * length will be a const. */ Expression *e = new IntegerExp(0, ((TupleExp *)ce)->exps->dim, Type::tsize_t); v->init = new ExpInitializer(0, e); v->storage_class |= STCstatic | STCconst; } *pvar = v; } (*pvar)->semantic(sc); return (*pvar); } return NULL; }
Expression *CastExp::optimize(int result) { //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); //printf("from %s to %s\n", type->toChars(), to->toChars()); //printf("from %s\n", type->toChars()); //printf("e1->type %s\n", e1->type->toChars()); //printf("type = %p\n", type); assert(type); enum TOK op1 = e1->op; e1 = e1->optimize(result); if (result & WANTinterpret) e1 = fromConstInitializer(e1); if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && type->next->equals(e1->type->next) ) { // make a copy before adjusting type to avoid // messing up the type of an existing initializer e1 = e1->syntaxCopy(); e1->type = type; return e1; } /* The first test here is to prevent infinite loops */ if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) return e1->castTo(NULL, to); if (e1->op == TOKnull && (type->ty == Tpointer || type->ty == Tclass)) { e1->type = type; return e1; } if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) { // See if we can remove an unnecessary cast ClassDeclaration *cdfrom; ClassDeclaration *cdto; int offset; cdfrom = e1->type->isClassHandle(); cdto = type->isClassHandle(); if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) { e1->type = type; return e1; } } Expression *e; if (e1->isConst()) { if (e1->op == TOKsymoff) { if (type->size() == e1->type->size() && type->toBasetype()->ty != Tsarray) { e1->type = type; return e1; } return this; } if (to->toBasetype()->ty == Tvoid) e = this; else e = Cast(type, to, e1); } else e = this; return e; }
Expression *VarExp::optimize(int result, bool keepLvalue) { return keepLvalue ? this : fromConstInitializer(result, this); }