1: 
   2: // Compiler implementation of the D programming language
   3: // Copyright (c) 1999-2011 by Digital Mars
   4: // All Rights Reserved
   5: // written by Walter Bright
   6: // http://www.digitalmars.com
   7: // License for redistribution is by either the Artistic License
   8: // in artistic.txt, or the GNU General Public License in gnu.txt.
   9: // See the included readme.txt for details.
  10: 
  11: #include <stdio.h>
  12: #include <ctype.h>
  13: static char __file__[] = __FILE__;      /* for tassert.h                */
  14: #include        "tassert.h"
  15: #include <math.h>
  16: 
  17: #if __DMC__
  18: #include <complex.h>
  19: #endif
  20: 
  21: #include "cdef.h"
  22: #include "lexer.h"
  23: #include "mtype.h"
  24: #include "expression.h"
  25: #include "declaration.h"
  26: #include "aggregate.h"
  27: #include "init.h"
  28: 
  29: 
  30: #ifdef IN_GCC
  31: #include "d-gcc-real.h"
  32: 
  33: /* %% fix? */
  34: extern "C" bool real_isnan (const real_t *);
  35: #endif
  36: 
  37: static real_t zero;     // work around DMC bug for now
  38: 
  39: 
  40: /*************************************
  41:  * If variable has a const initializer,
  42:  * return that initializer.
  43:  */
  44: 
  45: Expression *expandVar(int result, VarDeclaration *v)
  46: {
  47:     //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null");
  48: 
  49:     Expression *e = NULL;
  50:     if (!v)
  51:         return e;
  52:     if (!v->originalType && v->scope)   // semantic() not yet run
  53:         v->semantic (v->scope);
  54: 
  55:     if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
  56:     {
  57:         if (!v->type)
  58:         {
  59:             //error("ICE");
  60:             return e;
  61:         }
  62:         Type *tb = v->type->toBasetype();
  63:         if (result & WANTinterpret ||
  64:             v->storage_class & STCmanifest ||
  65:             v->type->toBasetype()->isscalar() ||
  66:             ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct))
  67:            )
  68:         {
  69:             if (v->init)
  70:             {
  71:                 if (v->inuse)
  72:                 {   if (v->storage_class & STCmanifest)
  73:                         v->error("recursive initialization of constant");
  74:                     goto L1;
  75:                 }
  76:                 Expression *ei = v->init->toExpression();
  77:                 if (!ei)
  78:                 {   if (v->storage_class & STCmanifest)
  79:                         v->error("enum cannot be initialized with %s", v->init->toChars());
  80:                     goto L1;
  81:                 }
  82:                 if (ei->op == TOKconstruct || ei->op == TOKblit)
  83:                 {   AssignExp *ae = (AssignExp *)ei;
  84:                     ei = ae->e2;
  85:                     if (result & WANTinterpret)
  86:                     {
  87:                         v->inuse++;
  88:                         ei = ei->optimize(result);
  89:                         v->inuse--;
  90:                     }
  91:                     else if (ei->isConst() != 1 && ei->op != TOKstring)
  92:                         goto L1;
  93: 
  94:                     if (ei->type == v->type)
  95:                     {   // const variable initialized with const expression
  96:                     }
  97:                     else if (ei->implicitConvTo(v->type) >= MATCHconst)
  98:                     {   // const var initialized with non-const expression
  99:                         ei = ei->implicitCastTo(0, v->type);
 100:                         ei = ei->semantic(0);
 101:                     }
 102:                     else
 103:                         goto L1;
 104:                 }
 105:                 if (v->scope)
 106:                 {
 107:                     v->inuse++;
 108:                     e = ei->syntaxCopy();
 109:                     e = e->semantic(v->scope);
 110:                     e = e->implicitCastTo(v->scope, v->type);
 111:                     // enabling this line causes test22 in test suite to fail
 112:                     //ei->type = e->type;
 113:                     v->scope = NULL;
 114:                     v->inuse--;
 115:                 }
 116:                 else if (!ei->type)
 117:                 {
 118:                     goto L1;
 119:                 }
 120:                 else
 121:                     // Should remove the copy() operation by
 122:                     // making all mods to expressions copy-on-write
 123:                     e = ei->copy();
 124:             }
 125:             else
 126:             {
 127: #if 1
 128:                 goto L1;
 129: #else
 130:                 // BUG: what if const is initialized in constructor?
 131:                 e = v->type->defaultInit();
 132:                 e->loc = e1->loc;
 133: #endif
 134:             }
 135:             if (e->type != v->type)
 136:             {
 137:                 e = e->castTo(NULL, v->type);
 138:             }
 139:             v->inuse++;
 140:             e = e->optimize(result);
 141:             v->inuse--;
 142:         }
 143:     }
 144: L1:
 145:     //if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars());
 146:     return e;
 147: }
 148: 
 149: 
 150: Expression *fromConstInitializer(int result, Expression *e1)
 151: {
 152:     //printf("fromConstInitializer(result = %x, %s)\n", result, e1->toChars());
 153:     //static int xx; if (xx++ == 10) assert(0);
 154:     Expression *e = e1;
 155:     if (e1->op == TOKvar)
 156:     {   VarExp *ve = (VarExp *)e1;
 157:         VarDeclaration *v = ve->var->isVarDeclaration();
 158:         int fwdref = (v && !v->originalType && v->scope);
 159:         e = expandVar(result, v);
 160:         if (e)
 161:         {
 162:             // If it is a comma expression involving a declaration, we mustn't
 163:             // perform a copy -- we'd get two declarations of the same variable.
 164:             // See bugzilla 4465.
 165:             if (e->op == TOKcomma && ((CommaExp *)e)->e1->op == TOKdeclaration)
 166:                  e = e1;
 167:             else
 168: 
 169:             if (e->type != e1->type && e1->type && e1->type->ty != Tident)
 170:             {   // Type 'paint' operation
 171:                 e = e->copy();
 172:                 e->type = e1->type;
 173:             }
 174:             e->loc = e1->loc;
 175:         }
 176:         else
 177:         {
 178:             e = e1;
 179:             /* If we needed to interpret, generate an error.
 180:              * Don't give an error if it's a template parameter
 181:              */
 182:             if (v && (result & WANTinterpret) &&
 183:                 !(v->storage_class & STCtemplateparameter))
 184:             {
 185:                 e1->error("variable %s cannot be read at compile time", v->toChars());
 186:             }
 187:         }
 188:     }
 189:     return e;
 190: }
 191: 
 192: 
 193: Expression *Expression::optimize(int result)
 194: {
 195:     //printf("Expression::optimize(result = x%x) %s\n", result, toChars());
 196:     return this;
 197: }
 198: 
 199: Expression *VarExp::optimize(int result)
 200: {
 201:     return fromConstInitializer(result, this);
 202: }
 203: 
 204: Expression *TupleExp::optimize(int result)
 205: {
 206:     for (size_t i = 0; i < exps->dim; i++)
 207:     {   Expression *e = exps->tdata()[i];
 208: 
 209:         e = e->optimize(WANTvalue | (result & WANTinterpret));
 210:         exps->tdata()[i] = e;
 211:     }
 212:     return this;
 213: }
 214: 
 215: Expression *ArrayLiteralExp::optimize(int result)
 216: {
 217:     if (elements)
 218:     {
 219:         for (size_t i = 0; i < elements->dim; i++)
 220:         {   Expression *e = elements->tdata()[i];
 221: 
 222:             e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
 223:             elements->tdata()[i] = e;
 224:         }
 225:     }
 226:     return this;
 227: }
 228: 
 229: Expression *AssocArrayLiteralExp::optimize(int result)
 230: {
 231:     assert(keys->dim == values->dim);
 232:     for (size_t i = 0; i < keys->dim; i++)
 233:     {   Expression *e = keys->tdata()[i];
 234: 
 235:         e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
 236:         keys->tdata()[i] = e;
 237: 
 238:         e = values->tdata()[i];
 239:         e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
 240:         values->tdata()[i] = e;
 241:     }
 242:     return this;
 243: }
 244: 
 245: Expression *StructLiteralExp::optimize(int result)
 246: {
 247:     if (elements)
 248:     {
 249:         for (size_t i = 0; i < elements->dim; i++)
 250:         {   Expression *e = elements->tdata()[i];
 251:             if (!e)
 252:                 continue;
 253:             e = e->optimize(WANTvalue | (result & (WANTinterpret | WANTexpand)));
 254:             elements->tdata()[i] = e;
 255:         }
 256:     }
 257:     return this;
 258: }
 259: 
 260: Expression *TypeExp::optimize(int result)
 261: {
 262:     return this;
 263: }
 264: 
 265: Expression *UnaExp::optimize(int result)
 266: {
 267:     e1 = e1->optimize(result);
 268:     return this;
 269: }
 270: 
 271: Expression *NegExp::optimize(int result)
 272: {   Expression *e;
 273: 
 274:     e1 = e1->optimize(result);
 275:     if (e1->isConst() == 1)
 276:     {
 277:         e = Neg(type, e1);
 278:     }
 279:     else
 280:         e = this;
 281:     return e;
 282: }
 283: 
 284: Expression *ComExp::optimize(int result)
 285: {   Expression *e;
 286: 
 287:     e1 = e1->optimize(result);
 288:     if (e1->isConst() == 1)
 289:     {
 290:         e = Com(type, e1);
 291:     }
 292:     else
 293:         e = this;
 294:     return e;
 295: }
 296: 
 297: Expression *NotExp::optimize(int result)
 298: {   Expression *e;
 299: 
 300:     e1 = e1->optimize(result);
 301:     if (e1->isConst() == 1)
 302:     {
 303:         e = Not(type, e1);
 304:     }
 305:     else
 306:         e = this;
 307:     return e;
 308: }
 309: 
 310: Expression *BoolExp::optimize(int result)
 311: {   Expression *e;
 312: 
 313:     e1 = e1->optimize(result);
 314:     if (e1->isConst() == 1)
 315:     {
 316:         e = Bool(type, e1);
 317:     }
 318:     else
 319:         e = this;
 320:     return e;
 321: }
 322: 
 323: Expression *AddrExp::optimize(int result)
 324: {   Expression *e;
 325: 
 326:     //printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
 327: 
 328:     /* Rewrite &(a,b) as (a,&b)
 329:      */
 330:     if (e1->op == TOKcomma)
 331:     {   CommaExp *ce = (CommaExp *)e1;
 332:         AddrExp *ae = new AddrExp(loc, ce->e2);
 333:         ae->type = type;
 334:         e = new CommaExp(ce->loc, ce->e1, ae);
 335:         e->type = type;
 336:         return e->optimize(result);
 337:     }
 338: 
 339:     if (e1->op == TOKvar)
 340:     {   VarExp *ve = (VarExp *)e1;
 341:         if (ve->var->storage_class & STCmanifest)
 342:             e1 = e1->optimize(result);
 343:     }
 344:     else
 345:         e1 = e1->optimize(result);
 346: 
 347:     // Convert &*ex to ex
 348:     if (e1->op == TOKstar)
 349:     {   Expression *ex;
 350: 
 351:         ex = ((PtrExp *)e1)->e1;
 352:         if (type->equals(ex->type))
 353:             e = ex;
 354:         else
 355:         {
 356:             e = ex->copy();
 357:             e->type = type;
 358:         }
 359:         return e;
 360:     }
 361:     if (e1->op == TOKvar)
 362:     {   VarExp *ve = (VarExp *)e1;
 363:         if (!ve->var->isOut() && !ve->var->isRef() &&
 364:             !ve->var->isImportedSymbol())
 365:         {
 366:             SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads);
 367:             se->type = type;
 368:             return se;
 369:         }
 370:     }
 371:     if (e1->op == TOKindex)
 372:     {   // Convert &array[n] to &array+n
 373:         IndexExp *ae = (IndexExp *)e1;
 374: 
 375:         if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar)
 376:         {
 377:             dinteger_t index = ae->e2->toInteger();
 378:             VarExp *ve = (VarExp *)ae->e1;
 379:             if (ve->type->ty == Tsarray
 380:                 && !ve->var->isImportedSymbol())
 381:             {
 382:                 TypeSArray *ts = (TypeSArray *)ve->type;
 383:                 dinteger_t dim = ts->dim->toInteger();
 384:                 if (index < 0 || index >= dim)
 385:                     error("array index %jd is out of bounds [0..%jd]", index, dim);
 386:                 e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
387: e->type = type; 388: return e; 389: } 390: } 391: } 392: return this; 393: } 394: 395: Expression *PtrExp::optimize(int result) 396: { 397: //printf("PtrExp::optimize(result = x%x) %s\n", result, toChars()); 398: e1 = e1->optimize(result); 399: // Convert *&ex to ex 400: if (e1->op == TOKaddress) 401: { Expression *e; 402: Expression *ex; 403: 404: ex = ((AddrExp *)e1)->e1; 405: if (type->equals(ex->type)) 406: e = ex; 407: else 408: { 409: e = ex->copy(); 410: e->type = type; 411: } 412: return e; 413: } 414: // Constant fold *(&structliteral + offset) 415: if (e1->op == TOKadd) 416: { 417: Expression *e; 418: e = Ptr(type, e1); 419: if (e != EXP_CANT_INTERPRET) 420: return e; 421: } 422: 423: if (e1->op == TOKsymoff) 424: { SymOffExp *se = (SymOffExp *)e1; 425: VarDeclaration *v = se->var->isVarDeclaration(); 426: Expression *e = expandVar(result, v); 427: if (e && e->op == TOKstructliteral) 428: { StructLiteralExp *sle = (StructLiteralExp *)e; 429: e = sle->getField(type, se->offset); 430: if (e && e != EXP_CANT_INTERPRET) 431: return e; 432: } 433: } 434: return this; 435: } 436: 437: Expression *DotVarExp::optimize(int result) 438: { 439: //printf("DotVarExp::optimize(result = x%x) %s\n", result, toChars()); 440: e1 = e1->optimize(result); 441: 442: Expression *e = e1; 443: 444: if (e1->op == TOKvar) 445: { VarExp *ve = (VarExp *)e1; 446: VarDeclaration *v = ve->var->isVarDeclaration(); 447: e = expandVar(result, v); 448: } 449: 450: if (e && e->op == TOKstructliteral) 451: { StructLiteralExp *sle = (StructLiteralExp *)e; 452: VarDeclaration *vf = var->isVarDeclaration(); 453: if (vf) 454: { 455: Expression *e = sle->getField(type, vf->offset);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '442' of 'c:\projects\extern\d\dmd\src\optimize.c': Lines: 442
456: if (e && e != EXP_CANT_INTERPRET) 457: return e; 458: } 459: } 460: 461: return this; 462: } 463: 464: Expression *NewExp::optimize(int result) 465: { 466: if (thisexp) 467: thisexp = thisexp->optimize(WANTvalue); 468: 469: // Optimize parameters 470: if (newargs) 471: { 472: for (size_t i = 0; i < newargs->dim; i++) 473: { Expression *e = newargs->tdata()[i]; 474: 475: e = e->optimize(WANTvalue); 476: newargs->tdata()[i] = e; 477: } 478: } 479: 480: if (arguments) 481: { 482: for (size_t i = 0; i < arguments->dim; i++) 483: { Expression *e = arguments->tdata()[i]; 484: 485: e = e->optimize(WANTvalue); 486: arguments->tdata()[i] = e; 487: } 488: } 489: if (result & WANTinterpret) 490: { 491: error("cannot evaluate %s at compile time", toChars()); 492: } 493: return this; 494: } 495: 496: Expression *CallExp::optimize(int result) 497: { 498: //printf("CallExp::optimize(result = %d) %s\n", result, toChars()); 499: Expression *e = this; 500: 501: // Optimize parameters 502: if (arguments) 503: { 504: for (size_t i = 0; i < arguments->dim; i++) 505: { Expression *e = arguments->tdata()[i];
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '499' of 'c:\projects\extern\d\dmd\src\optimize.c': Lines: 499
506: 507: e = e->optimize(WANTvalue); 508: arguments->tdata()[i] = e; 509: } 510: } 511: 512: e1 = e1->optimize(result); 513: #if 1 514: if (result & WANTinterpret) 515: { 516: Expression *eresult = interpret(NULL); 517: if (eresult == EXP_CANT_INTERPRET) 518: return e; 519: if (eresult && eresult != EXP_VOID_INTERPRET) 520: e = eresult; 521: else 522: error("cannot evaluate %s at compile time", toChars()); 523: } 524: #else 525: if (e1->op == TOKvar) 526: { 527: FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration(); 528: if (fd) 529: { 530: enum BUILTIN b = fd->isBuiltin(); 531: if (b) 532: { 533: e = eval_builtin(b, arguments); 534: if (!e) // failed 535: e = this; // evaluate at runtime 536: } 537: else if (result & WANTinterpret) 538: { 539: Expression *eresult = fd->interpret(NULL, arguments); 540: if (eresult && eresult != EXP_VOID_INTERPRET) 541: e = eresult; 542: else 543: error("cannot evaluate %s at compile time", toChars()); 544: } 545: } 546: } 547: else if (e1->op == TOKdotvar && result & WANTinterpret) 548: { DotVarExp *dve = (DotVarExp *)e1; 549: FuncDeclaration *fd = dve->var->isFuncDeclaration(); 550: if (fd) 551: { 552: Expression *eresult = fd->interpret(NULL, arguments, dve->e1); 553: if (eresult && eresult != EXP_VOID_INTERPRET) 554: e = eresult; 555: else 556: error("cannot evaluate %s at compile time", toChars()); 557: } 558: } 559: #endif 560: return e; 561: } 562: 563: 564: Expression *CastExp::optimize(int result) 565: { 566: //printf("CastExp::optimize(result = %d) %s\n", result, toChars()); 567: //printf("from %s to %s\n", type->toChars(), to->toChars()); 568: //printf("from %s\n", type->toChars()); 569: //printf("e1->type %s\n", e1->type->toChars()); 570: //printf("type = %p\n", type); 571: assert(type); 572: enum TOK op1 = e1->op; 573: #define X 0 574: 575: Expression *e1old = e1; 576: e1 = e1->optimize(result); 577: e1 = fromConstInitializer(result, e1); 578: 579: if (e1 == e1old && 580: e1->op == TOKarrayliteral && 581: type->toBasetype()->ty == Tpointer && 582: e1->type->toBasetype()->ty != Tsarray) 583: { 584: // Casting this will result in the same expression, and 585: // infinite loop because of Expression::implicitCastTo() 586: return this; // no change 587: } 588: 589: if ((e1->op == TOKstring || e1->op == TOKarrayliteral) && 590: (type->ty == Tpointer || type->ty == Tarray) && 591: e1->type->nextOf()->size() == type->nextOf()->size() 592: ) 593: { 594: Expression *e = e1->castTo(NULL, type); 595: if (X) printf(" returning1 %s\n", e->toChars()); 596: return e; 597: } 598: 599: if (e1->op == TOKstructliteral && 600: e1->type->implicitConvTo(type) >= MATCHconst) 601: { 602: e1->type = type; 603: if (X) printf(" returning2 %s\n", e1->toChars()); 604: return e1; 605: } 606: 607: /* The first test here is to prevent infinite loops 608: */ 609: if (op1 != TOKarrayliteral && e1->op == TOKarrayliteral) 610: return e1->castTo(NULL, to); 611: if (e1->op == TOKnull && 612: (type->ty == Tpointer || type->ty == Tclass || type->ty == Tarray)) 613: { 614: e1->type = type; 615: if (X) printf(" returning3 %s\n", e1->toChars()); 616: return e1; 617: } 618: 619: if (result & WANTflags && type->ty == Tclass && e1->type->ty == Tclass) 620: { 621: // See if we can remove an unnecessary cast 622: ClassDeclaration *cdfrom; 623: ClassDeclaration *cdto; 624: int offset; 625: 626: cdfrom = e1->type->isClassHandle(); 627: cdto = type->isClassHandle(); 628: if (cdto->isBaseOf(cdfrom, &offset) && offset == 0) 629: { 630: e1->type = type; 631: if (X) printf(" returning4 %s\n", e1->toChars()); 632: return e1; 633: } 634: } 635: 636: // We can convert 'head const' to mutable 637: if (to->constOf()->equals(e1->type->constOf())) 638: // if (to->constConv(e1->type) >= MATCHconst) 639: { 640: e1->type = type; 641: if (X) printf(" returning5 %s\n", e1->toChars()); 642: return e1; 643: } 644: 645: Expression *e; 646: 647: if (e1->isConst()) 648: { 649: if (e1->op == TOKsymoff) 650: { 651: if (type->size() == e1->type->size() && 652: type->toBasetype()->ty != Tsarray) 653: { 654: e1->type = type; 655: return e1; 656: } 657: return this; 658: } 659: if (to->toBasetype()->ty == Tvoid) 660: e = this; 661: else 662: e = Cast(type, to, e1); 663: } 664: else 665: e = this; 666: if (X) printf(" returning6 %s\n", e->toChars()); 667: return e; 668: #undef X 669: } 670: 671: Expression *BinExp::optimize(int result) 672: { 673: //printf("BinExp::optimize(result = %d) %s\n", result, toChars()); 674: if (op != TOKconstruct && op != TOKblit) // don't replace const variable with its initializer 675: e1 = e1->optimize(result); 676: e2 = e2->optimize(result); 677: if (op == TOKshlass || op == TOKshrass || op == TOKushrass) 678: { 679: if (e2->isConst() == 1) 680: { 681: dinteger_t i2 = e2->toInteger(); 682: d_uns64 sz = e1->type->size() * 8; 683: if (i2 < 0 || i2 > sz) 684: { error("shift assign by %jd is outside the range 0..%"SIZE_T_FORMAT"u", i2, sz); 685: e2 = new IntegerExp(0); 686: } 687: } 688: } 689: return this; 690: } 691: 692: Expression *AddExp::optimize(int result) 693: { Expression *e; 694: 695: //printf("AddExp::optimize(%s)\n", toChars()); 696: e1 = e1->optimize(result); 697: e2 = e2->optimize(result); 698: if (e1->isConst() && e2->isConst()) 699: { 700: if (e1->op == TOKsymoff && e2->op == TOKsymoff) 701: return this; 702: e = Add(type, e1, e2); 703: } 704: else 705: e = this; 706: return e; 707: } 708: 709: Expression *MinExp::optimize(int result) 710: { Expression *e; 711: 712: e1 = e1->optimize(result); 713: e2 = e2->optimize(result); 714: if (e1->isConst() && e2->isConst()) 715: { 716: if (e2->op == TOKsymoff) 717: return this; 718: e = Min(type, e1, e2); 719: } 720: else 721: e = this; 722: return e; 723: } 724: 725: Expression *MulExp::optimize(int result) 726: { Expression *e; 727: 728: //printf("MulExp::optimize(result = %d) %s\n", result, toChars()); 729: e1 = e1->optimize(result); 730: e2 = e2->optimize(result); 731: if (e1->isConst() == 1 && e2->isConst() == 1) 732: { 733: e = Mul(type, e1, e2); 734: } 735: else 736: e = this; 737: return e; 738: } 739: 740: Expression *DivExp::optimize(int result) 741: { Expression *e; 742: 743: //printf("DivExp::optimize(%s)\n", toChars()); 744: e1 = e1->optimize(result); 745: e2 = e2->optimize(result); 746: if (e1->isConst() == 1 && e2->isConst() == 1) 747: { 748: e = Div(type, e1, e2); 749: } 750: else 751: e = this; 752: return e; 753: } 754: 755: Expression *ModExp::optimize(int result) 756: { Expression *e; 757: 758: e1 = e1->optimize(result); 759: e2 = e2->optimize(result); 760: if (e1->isConst() == 1 && e2->isConst() == 1) 761: { 762: e = Mod(type, e1, e2); 763: } 764: else 765: e = this; 766: return e; 767: } 768: 769: Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, Expression *, Expression *)) 770: { Expression *ex = e; 771: 772: e->e1 = e->e1->optimize(result); 773: e->e2 = e->e2->optimize(result); 774: if (e->e2->isConst() == 1) 775: { 776: dinteger_t i2 = e->e2->toInteger(); 777: d_uns64 sz = e->e1->type->size() * 8; 778: if (i2 < 0 || i2 > sz) 779: { e->error("shift by %jd is outside the range 0..%"SIZE_T_FORMAT"u", i2, sz); 780: e->e2 = new IntegerExp(0); 781: } 782: if (e->e1->isConst() == 1) 783: ex = (*shift)(e->type, e->e1, e->e2); 784: } 785: return ex; 786: } 787: 788: Expression *ShlExp::optimize(int result) 789: { 790: //printf("ShlExp::optimize(result = %d) %s\n", result, toChars()); 791: return shift_optimize(result, this, Shl); 792: } 793: 794: Expression *ShrExp::optimize(int result) 795: { 796: //printf("ShrExp::optimize(result = %d) %s\n", result, toChars()); 797: return shift_optimize(result, this, Shr); 798: } 799: 800: Expression *UshrExp::optimize(int result) 801: { 802: //printf("UshrExp::optimize(result = %d) %s\n", result, toChars()); 803: return shift_optimize(result, this, Ushr); 804: } 805: 806: Expression *AndExp::optimize(int result) 807: { Expression *e; 808: 809: e1 = e1->optimize(result); 810: e2 = e2->optimize(result); 811: if (e1->isConst() == 1 && e2->isConst() == 1) 812: e = And(type, e1, e2); 813: else 814: e = this; 815: return e; 816: } 817: 818: Expression *OrExp::optimize(int result) 819: { Expression *e; 820: 821: e1 = e1->optimize(result); 822: e2 = e2->optimize(result); 823: if (e1->isConst() == 1 && e2->isConst() == 1) 824: e = Or(type, e1, e2); 825: else 826: e = this; 827: return e; 828: } 829: 830: Expression *XorExp::optimize(int result) 831: { Expression *e; 832: 833: e1 = e1->optimize(result); 834: e2 = e2->optimize(result); 835: if (e1->isConst() == 1 && e2->isConst() == 1) 836: e = Xor(type, e1, e2); 837: else 838: e = this; 839: return e; 840: } 841: 842: Expression *CommaExp::optimize(int result) 843: { Expression *e; 844: 845: //printf("CommaExp::optimize(result = %d) %s\n", result, toChars()); 846: // Comma needs special treatment, because it may 847: // contain compiler-generated declarations. We can interpret them, but 848: // otherwise we must NOT attempt to constant-fold them. 849: // In particular, if the comma returns a temporary variable, it needs 850: // to be an lvalue (this is particularly important for struct constructors) 851: 852: if (result & WANTinterpret) 853: { // Interpreting comma needs special treatment, because it may 854: // contain compiler-generated declarations. 855: e = interpret(NULL); 856: return (e == EXP_CANT_INTERPRET) ? this : e; 857: } 858: // Don't constant fold if it is a compiler-generated temporary. 859: if (e1->op == TOKdeclaration) 860: return this; 861: 862: e1 = e1->optimize(result & WANTinterpret); 863: e2 = e2->optimize(result); 864: if (!e1 || e1->op == TOKint64 || e1->op == TOKfloat64 || !e1->checkSideEffect(2)) 865: { 866: e = e2; 867: if (e) 868: e->type = type; 869: } 870: else 871: e = this; 872: //printf("-CommaExp::optimize(result = %d) %s\n", result, e->toChars()); 873: return e; 874: } 875: 876: Expression *ArrayLengthExp::optimize(int result) 877: { Expression *e; 878: 879: //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); 880: e1 = e1->optimize(WANTvalue | WANTexpand | (result & WANTinterpret)); 881: e = this; 882: if (e1->op == TOKstring || e1->op == TOKarrayliteral || e1->op == TOKassocarrayliteral) 883: { 884: e = ArrayLength(type, e1); 885: } 886: return e; 887: } 888: 889: Expression *EqualExp::optimize(int result) 890: { Expression *e; 891: 892: //printf("EqualExp::optimize(result = %x) %s\n", result, toChars()); 893: e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); 894: e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); 895: e = this; 896: 897: Expression *e1 = fromConstInitializer(result, this->e1); 898: Expression *e2 = fromConstInitializer(result, this->e2); 899: 900: e = Equal(op, type, e1, e2); 901: if (e == EXP_CANT_INTERPRET) 902: e = this; 903: return e; 904: } 905: 906: Expression *IdentityExp::optimize(int result) 907: { 908: //printf("IdentityExp::optimize(result = %d) %s\n", result, toChars()); 909: e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); 910: e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); 911: Expression *e = this; 912: 913: if ((this->e1->isConst() && this->e2->isConst()) || 914: (this->e1->op == TOKnull && this->e2->op == TOKnull)) 915: { 916: e = Identity(op, type, this->e1, this->e2); 917: if (e == EXP_CANT_INTERPRET) 918: e = this; 919: } 920: return e; 921: } 922: 923: /* It is possible for constant folding to change an array expression of 924: * unknown length, into one where the length is known. 925: * If the expression 'arr' is a literal, set lengthVar to be its length. 926: */ 927: void setLengthVarIfKnown(VarDeclaration *lengthVar, Expression *arr) 928: { 929: if (!lengthVar) 930: return; 931: if (lengthVar->init && !lengthVar->init->isVoidInitializer()) 932: return; // we have previously calculated the length 933: size_t len; 934: if (arr->op == TOKstring) 935: len = ((StringExp *)arr)->len; 936: else if (arr->op == TOKarrayliteral) 937: len = ((ArrayLiteralExp *)arr)->elements->dim; 938: else 939: return; // we don't know the length yet 940: 941: Expression *dollar = new IntegerExp(0, len, Type::tsize_t); 942: lengthVar->init = new ExpInitializer(0, dollar); 943: lengthVar->storage_class |= STCstatic | STCconst; 944: } 945: 946: 947: Expression *IndexExp::optimize(int result) 948: { Expression *e; 949: 950: //printf("IndexExp::optimize(result = %d) %s\n", result, toChars()); 951: Expression *e1 = this->e1->optimize( 952: WANTvalue | (result & (WANTinterpret| WANTexpand))); 953: e1 = fromConstInitializer(result, e1); 954: if (this->e1->op == TOKvar) 955: { VarExp *ve = (VarExp *)this->e1; 956: if (ve->var->storage_class & STCmanifest) 957: { /* We generally don't want to have more than one copy of an 958: * array literal, but if it's an enum we have to because the 959: * enum isn't stored elsewhere. See Bugzilla 2559 960: */ 961: this->e1 = e1; 962: } 963: } 964: // We might know $ now 965: setLengthVarIfKnown(lengthVar, e1); 966: e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); 967: e = Index(type, e1, e2); 968: if (e == EXP_CANT_INTERPRET) 969: e = this; 970: return e; 971: } 972: 973: 974: Expression *SliceExp::optimize(int result) 975: { Expression *e; 976: 977: //printf("SliceExp::optimize(result = %d) %s\n", result, toChars()); 978: e = this; 979: e1 = e1->optimize(WANTvalue | (result & (WANTinterpret|WANTexpand))); 980: if (!lwr) 981: { if (e1->op == TOKstring) 982: { // Convert slice of string literal into dynamic array 983: Type *t = e1->type->toBasetype(); 984: if (t->nextOf()) 985: e = e1->castTo(NULL, t->nextOf()->arrayOf()); 986: } 987: return e; 988: } 989: e1 = fromConstInitializer(result, e1); 990: // We might know $ now 991: setLengthVarIfKnown(lengthVar, e1); 992: lwr = lwr->optimize(WANTvalue | (result & WANTinterpret)); 993: upr = upr->optimize(WANTvalue | (result & WANTinterpret)); 994: e = Slice(type, e1, lwr, upr); 995: if (e == EXP_CANT_INTERPRET) 996: e = this; 997: //printf("-SliceExp::optimize() %s\n", e->toChars()); 998: return e; 999: } 1000: 1001: Expression *AndAndExp::optimize(int result) 1002: { Expression *e; 1003: 1004: //printf("AndAndExp::optimize(%d) %s\n", result, toChars()); 1005: e1 = e1->optimize(WANTflags | (result & WANTinterpret)); 1006: e = this; 1007: if (e1->isBool(FALSE)) 1008: { 1009: e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type)); 1010: e->type = type; 1011: e = e->optimize(result); 1012: } 1013: else 1014: { 1015: e2 = e2->optimize(WANTflags | (result & WANTinterpret)); 1016: if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) 1017: error("void has no value"); 1018: if (e1->isConst()) 1019: { 1020: if (e2->isConst()) 1021: { int n1 = e1->isBool(1); 1022: int n2 = e2->isBool(1); 1023: 1024: e = new IntegerExp(loc, n1 && n2, type); 1025: } 1026: else if (e1->isBool(TRUE)) 1027: e = new BoolExp(loc, e2, type); 1028: } 1029: } 1030: return e; 1031: } 1032: 1033: Expression *OrOrExp::optimize(int result) 1034: { Expression *e; 1035: 1036: e1 = e1->optimize(WANTflags | (result & WANTinterpret)); 1037: e = this; 1038: if (e1->isBool(TRUE)) 1039: { // Replace with (e1, 1) 1040: e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type)); 1041: e->type = type; 1042: e = e->optimize(result); 1043: } 1044: else 1045: { 1046: e2 = e2->optimize(WANTflags | (result & WANTinterpret)); 1047: if (result && e2->type->toBasetype()->ty == Tvoid && !global.errors) 1048: error("void has no value"); 1049: if (e1->isConst()) 1050: { 1051: if (e2->isConst()) 1052: { int n1 = e1->isBool(1); 1053: int n2 = e2->isBool(1); 1054: 1055: e = new IntegerExp(loc, n1 || n2, type); 1056: } 1057: else if (e1->isBool(FALSE)) 1058: e = new BoolExp(loc, e2, type); 1059: } 1060: } 1061: return e; 1062: } 1063: 1064: Expression *CmpExp::optimize(int result) 1065: { Expression *e; 1066: 1067: //printf("CmpExp::optimize() %s\n", toChars()); 1068: e1 = e1->optimize(WANTvalue | (result & WANTinterpret)); 1069: e2 = e2->optimize(WANTvalue | (result & WANTinterpret)); 1070: 1071: Expression *e1 = fromConstInitializer(result, this->e1); 1072: Expression *e2 = fromConstInitializer(result, this->e2); 1073: 1074: e = Cmp(op, type, e1, e2); 1075: if (e == EXP_CANT_INTERPRET) 1076: e = this; 1077: return e; 1078: } 1079: 1080: Expression *CatExp::optimize(int result) 1081: { Expression *e; 1082: 1083: //printf("CatExp::optimize(%d) %s\n", result, toChars()); 1084: e1 = e1->optimize(result); 1085: e2 = e2->optimize(result); 1086: e = Cat(type, e1, e2); 1087: if (e == EXP_CANT_INTERPRET) 1088: e = this; 1089: return e; 1090: } 1091: 1092: 1093: Expression *CondExp::optimize(int result) 1094: { Expression *e; 1095: 1096: econd = econd->optimize(WANTflags | (result & WANTinterpret)); 1097: if (econd->isBool(TRUE)) 1098: e = e1->optimize(result); 1099: else if (econd->isBool(FALSE)) 1100: e = e2->optimize(result); 1101: else 1102: { e1 = e1->optimize(result); 1103: e2 = e2->optimize(result); 1104: e = this; 1105: } 1106: return e; 1107: } 1108: 1109: 1110: