Mercurial > projects > ldc
view dmd2/optimize.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | e4f7b5d9c68a |
children |
line wrap: on
line source
// Compiler implementation of the D programming language // Copyright (c) 1999-2009 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. #include <stdio.h> #include <ctype.h> #include <assert.h> #include <math.h> #if __DMC__ #include <complex.h> #endif #include "lexer.h" #include "mtype.h" #include "expression.h" #include "declaration.h" #include "aggregate.h" #include "init.h" #ifdef IN_GCC #include "d-gcc-real.h" /* %% fix? */ extern "C" bool real_isnan (const real_t *); #endif static real_t zero; // work around DMC bug for now /************************************* * If variable has a const initializer, * return that initializer. */ Expression *expandVar(int result, VarDeclaration *v) { //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null"); Expression *e = NULL; if (!v) return e; if (v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) { if (!v->type) { //error("ICE"); return e; } Type *tb = v->type->toBasetype(); if (result & WANTinterpret || v->storage_class & STCmanifest || (tb->ty != Tsarray && tb->ty != Tstruct) ) { if (v->init) { if (v->inuse) { if (v->storage_class & STCmanifest) v->error("recursive initialization of constant"); goto L1; } Expression *ei = v->init->toExpression(); if (!ei) goto L1; if (ei->op == TOKconstruct || ei->op == TOKblit) { AssignExp *ae = (AssignExp *)ei; ei = ae->e2; if (ei->isConst() != 1 && ei->op != TOKstring) goto L1; if (ei->type != v->type) goto L1; } if (v->scope) { v->inuse++; e = ei->syntaxCopy(); e = e->semantic(v->scope); e = e->implicitCastTo(v->scope, v->type); // enabling this line causes test22 in test suite to fail //ei->type = e->type; v->scope = NULL; v->inuse--; } else if (!ei->type) { goto L1; } else // Should remove the copy() operation by // making all mods to expressions copy-on-write e = ei->copy(); } else { #if 1 goto L1; #else // BUG: what if const is initialized in constructor? e = v->type->defaultInit(); e->loc = e1->loc; #endif } if (e->type != v->type) { e = e->castTo(NULL, v->type); } v->inuse++; e = e->optimize(result); v->inuse--; } } L1: //if (e) printf("\te = %s, e->type = %s\n", e->toChars(), e->type->toChars()); return e; } Expression *fromConstInitializer(int result, Expression *e1) { //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars()); //static int xx; if (xx++ == 10) assert(0); Expression *e = e1; if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); e = expandVar(result, v); if (e) { if (e->type != e1->type) { // Type 'paint' operation e = e->copy(); e->type = e1->type; } } else e = e1; } return e; } Expression *Expression::optimize(int result) { //printf("Expression::optimize(result = x%x) %s\n", result, toChars()); return this; } Expression *VarExp::optimize(int result) { return fromConstInitializer(result, this); } Expression *TupleExp::optimize(int result) { for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); exps->data[i] = (void *)e; } return this; } Expression *ArrayLiteralExp::optimize(int result) { if (elements) { for (size_t i = 0; i < elements->dim; i++) { Expression *e = (Expression *)elements->data[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); elements->data[i] = (void *)e; } } return this; } Expression *AssocArrayLiteralExp::optimize(int result) { assert(keys->dim == values->dim); for (size_t i = 0; i < keys->dim; i++) { Expression *e = (Expression *)keys->data[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); keys->data[i] = (void *)e; e = (Expression *)values->data[i]; e = e->optimize(WANTvalue | (result & WANTinterpret)); values->data[i] = (void *)e; } return this; } Expression *StructLiteralExp::optimize(int result) { if (elements) { for (size_t i = 0; i < elements->dim; i++) { Expression *e = (Expression *)elements->data[i]; if (!e) continue; e = e->optimize(WANTvalue | (result & WANTinterpret)); elements->data[i] = (void *)e; } } return this; } Expression *TypeExp::optimize(int result) { return this; } Expression *UnaExp::optimize(int result) { e1 = e1->optimize(result); return this; } Expression *NegExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); if (e1->isConst() == 1) { e = Neg(type, e1); } else e = this; return e; } Expression *ComExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); if (e1->isConst() == 1) { e = Com(type, e1); } else e = this; return e; } Expression *NotExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); if (e1->isConst() == 1) { e = Not(type, e1); } else e = this; return e; } Expression *BoolExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); if (e1->isConst() == 1) { e = Bool(type, e1); } else e = this; return e; } Expression *AddrExp::optimize(int result) { Expression *e; //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); /* Rewrite &(a,b) as (a,&b) */ if (e1->op == TOKcomma) { CommaExp *ce = (CommaExp *)e1; AddrExp *ae = new AddrExp(loc, ce->e2); ae->type = type; e = new CommaExp(ce->loc, ce->e1, ae); e->type = type; return e->optimize(result); } if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; if (ve->var->storage_class & STCmanifest) e1 = e1->optimize(result); } else e1 = e1->optimize(result); // Convert &*ex to ex if (e1->op == TOKstar) { Expression *ex; ex = ((PtrExp *)e1)->e1; if (type->equals(ex->type)) e = ex; else { e = ex->copy(); e->type = type; } return e; } #if !IN_LLVM if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; if (!ve->var->isOut() && !ve->var->isRef() && !ve->var->isImportedSymbol()) { SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads); se->type = type; return se; } } if (e1->op == TOKindex) { // Convert &array[n] to &array+n IndexExp *ae = (IndexExp *)e1; if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) { dinteger_t index = ae->e2->toInteger(); VarExp *ve = (VarExp *)ae->e1; if (ve->type->ty == Tsarray && !ve->var->isImportedSymbol()) { TypeSArray *ts = (TypeSArray *)ve->type; dinteger_t dim = ts->dim->toInteger(); if (index < 0 || index >= dim) error("array index %jd is out of bounds [0..%jd]", index, dim); e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size()); e->type = type; return e; } } } #endif return this; } Expression *PtrExp::optimize(int result) { //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); e1 = e1->optimize(result); // Convert *&ex to ex if (e1->op == TOKaddress) { Expression *e; Expression *ex; ex = ((AddrExp *)e1)->e1; if (type->equals(ex->type)) e = ex; else { e = ex->copy(); e->type = type; } return e; } // Constant fold *(&structliteral + offset) if (e1->op == TOKadd) { Expression *e; e = Ptr(type, e1); if (e != EXP_CANT_INTERPRET) return e; } if (e1->op == TOKsymoff) { SymOffExp *se = (SymOffExp *)e1; VarDeclaration *v = se->var->isVarDeclaration(); Expression *e = expandVar(result, v); if (e && e->op == TOKstructliteral) { StructLiteralExp *sle = (StructLiteralExp *)e; e = sle->getField(type, se->offset); if (e && e != EXP_CANT_INTERPRET) return e; } } return this; } Expression *DotVarExp::optimize(int result) { //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); e1 = e1->optimize(result); if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; VarDeclaration *v = ve->var->isVarDeclaration(); Expression *e = expandVar(result, v); if (e && e->op == TOKstructliteral) { StructLiteralExp *sle = (StructLiteralExp *)e; VarDeclaration *vf = var->isVarDeclaration(); if (vf) { e = sle->getField(type, vf->offset); if (e && e != EXP_CANT_INTERPRET) return e; } } } else if (e1->op == TOKstructliteral) { StructLiteralExp *sle = (StructLiteralExp *)e1; VarDeclaration *vf = var->isVarDeclaration(); if (vf) { Expression *e = sle->getField(type, vf->offset); if (e && e != EXP_CANT_INTERPRET) return e; } } return this; } Expression *NewExp::optimize(int result) { if (thisexp) thisexp = thisexp->optimize(WANTvalue); // Optimize parameters if (newargs) { for (size_t i = 0; i < newargs->dim; i++) { Expression *e = (Expression *)newargs->data[i]; e = e->optimize(WANTvalue); newargs->data[i] = (void *)e; } } if (arguments) { for (size_t i = 0; i < arguments->dim; i++) { Expression *e = (Expression *)arguments->data[i]; e = e->optimize(WANTvalue); arguments->data[i] = (void *)e; } } return this; } Expression *CallExp::optimize(int result) { //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); Expression *e = this; // Optimize parameters if (arguments) { for (size_t i = 0; i < arguments->dim; i++) { Expression *e = (Expression *)arguments->data[i]; e = e->optimize(WANTvalue); arguments->data[i] = (void *)e; } } e1 = e1->optimize(result); if (e1->op == TOKvar) { FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); if (fd) { enum BUILTIN b = fd->isBuiltin(); if (b) { e = eval_builtin(b, arguments); if (!e) // failed e = this; // evaluate at runtime } else if (result & WANTinterpret) { Expression *eresult = fd->interpret(NULL, arguments); if (eresult && eresult != EXP_VOID_INTERPRET) e = eresult; else error("cannot evaluate %s at compile time", toChars()); } } } 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 Expression *e1old = e1; e1 = e1->optimize(result); e1 = fromConstInitializer(result, e1); if (e1 == e1old && e1->op == TOKarrayliteral && type->toBasetype()->ty == Tpointer && e1->type->toBasetype()->ty != Tsarray) { // Casting this will result in the same expression, and // infinite loop because of Expression::implicitCastTo() return this; // no change } if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && (type->ty == Tpointer || type->ty == Tarray) && e1->type->nextOf()->size() == type->nextOf()->size() ) { Expression *e = e1->castTo(NULL, type); if (X) printf(" returning1 %s\n", e->toChars()); return e; } 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 *BinExp::optimize(int result) { //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); if (op != TOKconstruct && op != TOKblit) // don't replace const variable with its initializer e1 = e1->optimize(result); e2 = e2->optimize(result); if (op == TOKshlass || op == TOKshrass || op == TOKushrass) { if (e2->isConst() == 1) { dinteger_t i2 = e2->toInteger(); d_uns64 sz = e1->type->size() * 8; if (i2 < 0 || i2 > sz) { error("shift assign by %jd is outside the range 0..%zu", i2, sz); e2 = new IntegerExp(0); } } } return this; } Expression *AddExp::optimize(int result) { Expression *e; //printf("AddExp::optimize(%s)\n", toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() && e2->isConst()) { if (e1->op == TOKsymoff && e2->op == TOKsymoff) return this; e = Add(type, e1, e2); } else e = this; return e; } Expression *MinExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() && e2->isConst()) { if (e2->op == TOKsymoff) return this; e = Min(type, e1, e2); } else e = this; return e; } Expression *MulExp::optimize(int result) { Expression *e; //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) { e = Mul(type, e1, e2); } else e = this; return e; } Expression *DivExp::optimize(int result) { Expression *e; //printf("DivExp::optimize(%s)\n", toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) { e = Div(type, e1, e2); } else e = this; return e; } Expression *ModExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) { e = Mod(type, e1, e2); } else e = this; return e; } Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) { Expression *ex = e; e->e1 = e->e1->optimize(result); e->e2 = e->e2->optimize(result); if (e->e2->isConst() == 1) { dinteger_t i2 = e->e2->toInteger(); d_uns64 sz = e->e1->type->size() * 8; if (i2 < 0 || i2 > sz) { e->error("shift by %jd is outside the range 0..%zu", i2, sz); e->e2 = new IntegerExp(0); } if (e->e1->isConst() == 1) ex = (*shift)(e->type, e->e1, e->e2); } return ex; } Expression *ShlExp::optimize(int result) { //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); return shift_optimize(result, this, Shl); } Expression *ShrExp::optimize(int result) { //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); return shift_optimize(result, this, Shr); } Expression *UshrExp::optimize(int result) { //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); return shift_optimize(result, this, Ushr); } Expression *AndExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) e = And(type, e1, e2); else e = this; return e; } Expression *OrExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) e = Or(type, e1, e2); else e = this; return e; } Expression *XorExp::optimize(int result) { Expression *e; e1 = e1->optimize(result); e2 = e2->optimize(result); if (e1->isConst() == 1 && e2->isConst() == 1) e = Xor(type, e1, e2); else e = this; return e; } Expression *CommaExp::optimize(int result) { Expression *e; //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(result & WANTinterpret); e2 = e2->optimize(result); if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) { e = e2; if (e) e->type = type; } else e = this; //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); return e; } Expression *ArrayLengthExp::optimize(int result) { Expression *e; //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e = this; if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) { e = ArrayLength(type, e1); } return e; } Expression *EqualExp::optimize(int result) { Expression *e; //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; Expression *e1 = fromConstInitializer(result, this->e1); Expression *e2 = fromConstInitializer(result, this->e2); e = Equal(op, type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; } Expression *IdentityExp::optimize(int result) { Expression *e; //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = this; if ((this->e1->isConst() && this->e2->isConst()) || (this->e1->op == TOKnull && this->e2->op == TOKnull)) { e = Identity(op, type, this->e1, this->e2); } 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)); 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; } } e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); e = Index(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)); 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); 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 *AndAndExp::optimize(int result) { Expression *e; //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); e1 = e1->optimize(WANTflags | (result & WANTinterpret)); e = this; if (e1->isBool(FALSE)) { e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); e->type = type; e = e->optimize(result); } else { e2 = e2->optimize(WANTflags | (result & WANTinterpret)); if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) error("void has no value"); if (e1->isConst()) { if (e2->isConst()) { int n1 = e1->isBool(1); int n2 = e2->isBool(1); e = new IntegerExp(loc, n1 && n2, type); } else if (e1->isBool(TRUE)) e = new BoolExp(loc, e2, type); } } return e; } Expression *OrOrExp::optimize(int result) { Expression *e; e1 = e1->optimize(WANTflags | (result & WANTinterpret)); e = this; if (e1->isBool(TRUE)) { // Replace with (e1, 1) e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); e->type = type; e = e->optimize(result); } else { e2 = e2->optimize(WANTflags | (result & WANTinterpret)); if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) error("void has no value"); if (e1->isConst()) { if (e2->isConst()) { int n1 = e1->isBool(1); int n2 = e2->isBool(1); e = new IntegerExp(loc, n1 || n2, type); } else if (e1->isBool(FALSE)) e = new BoolExp(loc, e2, type); } } 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 *CatExp::optimize(int result) { Expression *e; //printf("CatExp::optimize(%d) %s\n", result, toChars()); e1 = e1->optimize(result); e2 = e2->optimize(result); e = Cat(type, e1, e2); if (e == EXP_CANT_INTERPRET) e = this; return e; } Expression *CondExp::optimize(int result) { Expression *e; econd = econd->optimize(WANTflags | (result & WANTinterpret)); if (econd->isBool(TRUE)) e = e1->optimize(result); else if (econd->isBool(FALSE)) e = e2->optimize(result); else { e1 = e1->optimize(result); e2 = e2->optimize(result); e = this; } return e; }