1: 
   2: // Compiler implementation of the D programming language
   3: // Copyright (c) 2000-2011 by Digital Mars
   4: // All Rights Reserved
   5: // Written by Walter Bright
   6: // http://www.digitalmars.com
   7: 
   8: #include        <stdio.h>
   9: #include        <string.h>
  10: #include        <time.h>
  11: 
  12: #include        "mars.h"
  13: #include        "lexer.h"
  14: #include        "statement.h"
  15: #include        "expression.h"
  16: #include        "mtype.h"
  17: #include        "dsymbol.h"
  18: #include        "declaration.h"
  19: #include        "irstate.h"
  20: #include        "init.h"
  21: #include        "module.h"
  22: #include        "enum.h"
  23: #include        "aggregate.h"
  24: #include        "template.h"
  25: #include        "id.h"
  26: 
  27: // Back end
  28: #include        "cc.h"
  29: #include        "type.h"
  30: #include        "code.h"
  31: #include        "oper.h"
  32: #include        "global.h"
  33: #include        "dt.h"
  34: 
  35: #include        "rmem.h"
  36: 
  37: static char __file__[] = __FILE__;      // for tassert.h
  38: #include        "tassert.h"
  39: 
  40: elem *callfunc(Loc loc,
  41:         IRState *irs,
  42:         int directcall,         // 1: don't do virtual call
  43:         Type *tret,             // return type
  44:         elem *ec,               // evaluates to function address
  45:         Type *ectype,           // original type of ec
  46:         FuncDeclaration *fd,    // if !=NULL, this is the function being called
  47:         Type *t,                // TypeDelegate or TypeFunction for this function
  48:         elem *ehidden,          // if !=NULL, this is the 'hidden' argument
  49:         Expressions *arguments);
  50: 
  51: elem *exp2_copytotemp(elem *e);
  52: elem *incUsageElem(IRState *irs, Loc loc);
  53: StructDeclaration *needsPostblit(Type *t);
  54: 
  55: #define elem_setLoc(e,loc)      ((e)->Esrcpos.Sfilename = (char *)(loc).filename, \
  56:                                  (e)->Esrcpos.Slinnum = (loc).linnum)
  57: 
  58: #define SEH     (TARGET_WINDOS)
  59: 
  60: /***********************************************
  61:  * Generate code to set index into scope table.
  62:  */
  63: 
  64: #if SEH
  65: void setScopeIndex(Blockx *blx, block *b, int scope_index)
  66: {
  67:     block_appendexp(b, nteh_setScopeTableIndex(blx, scope_index));
  68: }
  69: #else
  70: #define setScopeIndex(blx, b, scope_index) ;
  71: #endif
  72: 
  73: /****************************************
  74:  * Allocate a new block, and set the tryblock.
  75:  */
  76: 
  77: block *block_calloc(Blockx *blx)
  78: {
  79:     block *b = block_calloc();
  80:     b->Btry = blx->tryblock;
  81:     return b;
  82: }
  83: 
  84: /**************************************
  85:  * Convert label to block.
  86:  */
  87: 
  88: block *labelToBlock(Loc loc, Blockx *blx, LabelDsymbol *label, int flag = 0)
  89: {
  90:     if (!label->statement)
  91:     {
  92:         error(loc, "undefined label %s", label->toChars());
  93:         return NULL;
  94:     }
  95:     LabelStatement *s = label->statement;
  96:     if (!s->lblock)
  97:     {   s->lblock = block_calloc(blx);
  98:         s->lblock->Btry = NULL;         // fill this in later
  99: 
 100:         if (flag)
 101:         {
 102:             // Keep track of the forward reference to this block, so we can check it later
 103:             if (!s->fwdrefs)
 104:                 s->fwdrefs = new Blocks();
 105:             s->fwdrefs->push(blx->curblock);
 106:         }
 107:     }
 108:     return s->lblock;
 109: }
 110: 
 111: /**************************************
 112:  * Add in code to increment usage count for linnum.
 113:  */
 114: 
 115: void incUsage(IRState *irs, Loc loc)
 116: {
 117: 
 118:     if (global.params.cov && loc.linnum)
 119:     {
 120:         block_appendexp(irs->blx->curblock, incUsageElem(irs, loc));
 121:     }
 122: }
 123: 
 124: /****************************************
 125:  * This should be overridden by each statement class.
 126:  */
 127: 
 128: void Statement::toIR(IRState *irs)
 129: {
 130:     print();
 131:     assert(0);
 132: }
 133: 
 134: /*************************************
 135:  */
 136: 
 137: void OnScopeStatement::toIR(IRState *irs)
 138: {
 139: }
 140: 
 141: /****************************************
 142:  */
 143: 
 144: void IfStatement::toIR(IRState *irs)
 145: {
 146:     elem *e;
 147:     Blockx *blx = irs->blx;
 148: 
 149:     //printf("IfStatement::toIR('%s')\n", condition->toChars());
 150: 
 151:     IRState mystate(irs, this);
 152: 
 153:     // bexit is the block that gets control after this IfStatement is done
 154:     block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();
 155: 
 156:     incUsage(irs, loc);
 157: #if 0
 158:     if (match)
 159:     {   /* Generate:
 160:          *  if (match = RTLSYM_IFMATCH(string, pattern)) ...
 161:          */
 162:         assert(condition->op == TOKmatch);
 163:         e = matchexp_toelem((MatchExp *)condition, &mystate, RTLSYM_IFMATCH);
 164:         Symbol *s = match->toSymbol();
 165:         symbol_add(s);
 166:         e = el_bin(OPeq, TYnptr, el_var(s), e);
 167:     }
 168:     else
 169: #endif
 170:         e = condition->toElemDtor(&mystate);
 171:     block_appendexp(blx->curblock, e);
 172:     block *bcond = blx->curblock;
 173:     block_next(blx, BCiftrue, NULL);
 174: 
 175:     list_append(&bcond->Bsucc, blx->curblock);
 176:     if (ifbody)
 177:         ifbody->toIR(&mystate);
 178:     list_append(&blx->curblock->Bsucc, bexit);
 179: 
 180:     if (elsebody)
 181:     {
 182:         block_next(blx, BCgoto, NULL);
 183:         list_append(&bcond->Bsucc, blx->curblock);
 184:         elsebody->toIR(&mystate);
 185:         list_append(&blx->curblock->Bsucc, bexit);
 186:     }
 187:     else
 188:         list_append(&bcond->Bsucc, bexit);
 189: 
 190:     block_next(blx, BCgoto, bexit);
 191: 
 192: }
 193: 
 194: /**************************************
 195:  */
 196: 
 197: #if DMDV2
 198: void PragmaStatement::toIR(IRState *irs)
 199: {
 200:     //printf("PragmaStatement::toIR()\n");
 201:     if (ident == Id::startaddress)
 202:     {
 203:         assert(args && args->dim == 1);
 204:         Expression *e = args->tdata()[0];
 205:         Dsymbol *sa = getDsymbol(e);
 206:         FuncDeclaration *f = sa->isFuncDeclaration();
 207:         assert(f);
 208:         Symbol *s = f->toSymbol();
 209:         while (irs->prev)
 210:             irs = irs->prev;
 211:         irs->startaddress = s;
 212:     }
 213: }
 214: #endif
 215: 
 216: /***********************
 217:  */
 218: 
 219: void WhileStatement::toIR(IRState *irs)
 220: {
 221:     assert(0); // was "lowered"
 222: #if 0
 223:     Blockx *blx = irs->blx;
 224: 
 225:     /* Create a new state, because we need a new continue and break target
 226:      */
 227:     IRState mystate(irs,this);
 228:     mystate.breakBlock = block_calloc(blx);
 229:     mystate.contBlock = block_calloc(blx);
 230: 
 231:     list_append(&blx->curblock->Bsucc, mystate.contBlock);
 232:     block_next(blx, BCgoto, mystate.contBlock);
 233:     incUsage(irs, loc);
 234:     block_appendexp(mystate.contBlock, condition->toElem(&mystate));
 235: 
 236:     block_next(blx, BCiftrue, NULL);
 237: 
 238:     /* curblock is the start of the while loop body
 239:      */
 240:     list_append(&mystate.contBlock->Bsucc, blx->curblock);
 241:     if (body)
 242:         body->toIR(&mystate);
 243:     list_append(&blx->curblock->Bsucc, mystate.contBlock);
 244:     block_next(blx, BCgoto, mystate.breakBlock);
 245: 
 246:     list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
 247: #endif
 248: }
 249: 
 250: /******************************************
 251:  */
 252: 
 253: void DoStatement::toIR(IRState *irs)
 254: {
 255:     Blockx *blx = irs->blx;
 256: 
 257:     IRState mystate(irs,this);
 258:     mystate.breakBlock = block_calloc(blx);
 259:     mystate.contBlock = block_calloc(blx);
 260: 
 261:     block *bpre = blx->curblock;
 262:     block_next(blx, BCgoto, NULL);
 263:     list_append(&bpre->Bsucc, blx->curblock);
 264: 
 265:     list_append(&mystate.contBlock->Bsucc, blx->curblock);
 266:     list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
 267: 
 268:     if (body)
 269:         body->toIR(&mystate);
 270:     list_append(&blx->curblock->Bsucc, mystate.contBlock);
 271: 
 272:     block_next(blx, BCgoto, mystate.contBlock);
 273:     incUsage(irs, condition->loc);
 274:     block_appendexp(mystate.contBlock, condition->toElemDtor(&mystate));
 275:     block_next(blx, BCiftrue, mystate.breakBlock);
 276: 
 277: }
 278: 
 279: /*****************************************
 280:  */
 281: 
 282: void ForStatement::toIR(IRState *irs)
 283: {
 284:     Blockx *blx = irs->blx;
 285: 
 286:     IRState mystate(irs,this);
 287:     mystate.breakBlock = block_calloc(blx);
 288:     mystate.contBlock = block_calloc(blx);
 289: 
 290:     if (init)
 291:         init->toIR(&mystate);
 292:     block *bpre = blx->curblock;
 293:     block_next(blx,BCgoto,NULL);
 294:     block *bcond = blx->curblock;
 295:     list_append(&bpre->Bsucc, bcond);
 296:     list_append(&mystate.contBlock->Bsucc, bcond);
 297:     if (condition)
 298:     {
 299:         incUsage(irs, condition->loc);
 300:         block_appendexp(bcond, condition->toElemDtor(&mystate));
 301:         block_next(blx,BCiftrue,NULL);
 302:         list_append(&bcond->Bsucc, blx->curblock);
 303:         list_append(&bcond->Bsucc, mystate.breakBlock);
 304:     }
 305:     else
 306:     {   /* No conditional, it's a straight goto
 307:          */
 308:         block_next(blx,BCgoto,NULL);
 309:         list_append(&bcond->Bsucc, blx->curblock);
 310:     }
 311: 
 312:     if (body)
 313:         body->toIR(&mystate);
 314:     /* End of the body goes to the continue block
 315:      */
 316:     list_append(&blx->curblock->Bsucc, mystate.contBlock);
 317:     block_next(blx, BCgoto, mystate.contBlock);
 318: 
 319:     if (increment)
 320:     {
 321:         incUsage(irs, increment->loc);
 322:         block_appendexp(mystate.contBlock, increment->toElemDtor(&mystate));
 323:     }
 324: 
 325:     /* The 'break' block follows the for statement.
 326:      */
 327:     block_next(blx,BCgoto, mystate.breakBlock);
 328: }
 329: 
 330: 
 331: /**************************************
 332:  */
 333: 
 334: void ForeachStatement::toIR(IRState *irs)
 335: {
 336:     printf("ForeachStatement::toIR() %s\n", toChars());
 337:     assert(0);  // done by "lowering" in the front end
 338: #if 0
 339:     Type *tab;
 340:     elem *eaggr;
 341:     elem *e;
 342:     elem *elength;
 343:     tym_t keytym;
 344: 
 345:     //printf("ForeachStatement::toIR()\n");
 346:     block *bpre;
 347:     block *bcond;
 348:     block *bbody;
 349:     block *bbodyx;
 350:     Blockx *blx = irs->blx;
 351: 
 352:     IRState mystate(irs,this);
 353:     mystate.breakBlock = block_calloc(blx);
 354:     mystate.contBlock = block_calloc(blx);
 355: 
 356:     tab = aggr->type->toBasetype();
 357:     assert(tab->ty == Tarray || tab->ty == Tsarray);
 358: 
 359:     incUsage(irs, aggr->loc);
 360:     eaggr = aggr->toElem(irs);
 361: 
 362:     /* Create sp: pointer to start of array data
 363:      */
 364: 
 365:     Symbol *sp = symbol_genauto(TYnptr);
 366: 
 367:     if (tab->ty == Tarray)
 368:     {
 369:         // stmp is copy of eaggr (the array), so eaggr is evaluated only once
 370:         Symbol *stmp;
 371: 
 372:         // Initialize stmp
 373:         stmp = symbol_genauto(eaggr);
 374:         e = el_bin(OPeq, eaggr->Ety, el_var(stmp), eaggr);
 375:         block_appendexp(blx->curblock, e);
 376: 
 377:         // Initialize sp
 378:         e = el_una(OPmsw, TYnptr, el_var(stmp));
 379:         e = el_bin(OPeq, TYnptr, el_var(sp), e);
 380:         block_appendexp(blx->curblock, e);
 381: 
 382:         // Get array.length
 383:         elength = el_var(stmp);
 384:         elength->Ety = TYsize_t;
 385:     }
 386:     else // Tsarray
 387:     {
 388:         // Initialize sp
 389:         e = el_una(OPaddr, TYnptr, eaggr);
 390:         e = el_bin(OPeq, TYnptr, el_var(sp), e);
 391:         block_appendexp(blx->curblock, e);
 392: 
 393:         // Get array.length
 394:         elength = el_long(TYsize_t, ((TypeSArray *)tab)->dim->toInteger());
 395:     }
 396: 
 397:     Symbol *spmax;
 398:     Symbol *skey;
 399: 
 400:     if (key)
 401:     {
 402:         /* Create skey, the index to the array.
 403:          * Initialize skey to 0 (foreach) or .length (foreach_reverse).
 404:          */
 405:         skey = key->toSymbol();
 406:         symbol_add(skey);
 407:         keytym = key->type->totym();
 408:         elem *einit = (op == TOKforeach_reverse) ? elength : el_long(keytym, 0);
 409:         e = el_bin(OPeq, keytym, el_var(skey), einit);
 410:     }
 411:     else
 412:     {
 413:         /* Create spmax, pointer past end of data.
 414:          * Initialize spmax = sp + array.length * size
 415:          */
 416:         spmax = symbol_genauto(TYnptr);
 417:         e = el_bin(OPmul, TYsize_t, elength, el_long(TYsize_t, tab->nextOf()->size()));
 418:         e = el_bin(OPadd, TYnptr, el_var(sp), e);
 419:         e = el_bin(OPeq, TYnptr, el_var(spmax), e);
 420: 
 421:         /* For foreach_reverse, swap sp and spmax
 422:          */
 423:         if (op == TOKforeach_reverse)
 424:         {   Symbol *s = sp;
 425:             sp = spmax;
 426:             spmax = s;
 427:         }
 428:     }
 429:     block_appendexp(blx->curblock, e);
 430: 
 431:     bpre = blx->curblock;
 432:     block_next(blx,BCgoto,NULL);
 433:     bcond = blx->curblock;
 434: 
 435:     if (key)
 436:     {
 437:         if (op == TOKforeach_reverse)
 438:         {
 439:             // Construct (key != 0)
 440:             e = el_bin(OPne, TYint, el_var(skey), el_long(keytym, 0));
 441:         }
 442:         else
 443:         {
 444:             // Construct (key < elength)
 445:             e = el_bin(OPlt, TYint, el_var(skey), elength);
 446:         }
 447:     }
 448:     else
 449:     {
 450:         if (op == TOKforeach_reverse)
 451:         {
 452:             // Construct (sp > spmax)
 453:             e = el_bin(OPgt, TYint, el_var(sp), el_var(spmax));
 454:         }
 455:         else
 456:         {
 457:             // Construct (sp < spmax)
 458:             e = el_bin(OPlt, TYint, el_var(sp), el_var(spmax));
 459:         }
 460:     }
 461:     bcond->Belem = e;
 462:     block_next(blx, BCiftrue, NULL);
 463: 
 464:     if (op == TOKforeach_reverse)
 465:     {
 466:         if (key)
 467:         {   // Construct (skey -= 1)
 468:             e = el_bin(OPminass, keytym, el_var(skey), el_long(keytym, 1));
 469:         }
 470:         else
 471:         {   // Construct (sp--)
 472:             e = el_bin(OPminass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
 473:         }
 474:         block_appendexp(blx->curblock, e);
 475:     }
 476: 
 477:     Symbol *s;
 478:     FuncDeclaration *fd = NULL;
 479:     if (value->toParent2())
 480:         fd = value->toParent2()->isFuncDeclaration();
 481:     int nrvo = 0;
 482:     if (fd && fd->nrvo_can && fd->nrvo_var == value)
 483:     {
 484:         s = fd->shidden;
 485:         nrvo = 1;
 486:     }
 487:     else
 488:     {   s = value->toSymbol();
 489:         symbol_add(s);
 490:     }
 491: 
 492:     // Construct (value = *sp) or (value = sp[skey * elemsize])
 493:     tym_t tym = value->type->totym();
 494:     if (key)
 495:     {   // sp + skey * elemsize
 496:         e = el_bin(OPmul, keytym, el_var(skey), el_long(keytym, tab->nextOf()->size()));
 497:         e = el_bin(OPadd, TYnptr, el_var(sp), e);
 498:     }
 499:     else
 500:         e = el_var(sp);
 501: 
 502:     elem *evalue;
 503: #if DMDV2
 504:     if (value->offset)  // if value is a member of a closure
 505:     {
 506:         assert(irs->sclosure);
 507:         evalue = el_var(irs->sclosure);
 508:         evalue = el_bin(OPadd, TYnptr, evalue, el_long(TYint, value->offset));
 509:         evalue = el_una(OPind, value->type->totym(), evalue);
 510:     }
 511:     else
 512: #endif
 513:         evalue = el_var(s);
 514: 
 515:     if (value->isOut() || value->isRef())
 516:     {
 517:         assert(value->storage_class & (STCout | STCref));
 518:         e = el_bin(OPeq, TYnptr, evalue, e);
 519:     }
 520:     else
 521:     {
 522:         if (nrvo)
 523:             evalue = el_una(OPind, tym, evalue);
 524:         StructDeclaration *sd = needsPostblit(value->type);
 525:         if (tybasic(tym) == TYstruct)
 526:         {
 527:             e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
 528:             e->Eoper = OPstreq;
 529:             e->ET = value->type->toCtype();
 530: #if DMDV2
 531:             // Call postblit on e
 532:             if (sd)
 533:             {   FuncDeclaration *fd = sd->postblit;
 534:                 elem *ec = el_copytree(evalue);
 535:                 ec = el_una(OPaddr, TYnptr, ec);
 536:                 ec = callfunc(loc, irs, 1, Type::tvoid, ec, sd->type->pointerTo(), fd, fd->type, NULL, NULL);
 537:                 e = el_combine(e, ec);
 538:             }
 539: #endif
 540:         }
 541:         else if (tybasic(tym) == TYarray)
 542:         {
 543:             if (sd)
 544:             {
 545:                 /* Generate:
 546:                  *      _d_arrayctor(ti, efrom, eto)
 547:                  */
 548:                 Expression *ti = value->type->toBasetype()->nextOf()->toBasetype()->getTypeInfo(NULL);
 549:                 elem *esize = el_long(TYsize_t, ((TypeSArray *)value->type->toBasetype())->dim->toInteger());
 550:                 elem *eto = el_pair(TYdarray, esize, el_una(OPaddr, TYnptr, evalue));
 551:                 elem *efrom = el_pair(TYdarray, el_copytree(esize), e);
 552:                 elem *ep = el_params(eto, efrom, ti->toElem(irs), NULL);
 553:                 int rtl = RTLSYM_ARRAYCTOR;
 554:                 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), ep);
 555:             }
 556:             else
 557:             {
 558:                 e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
 559:                 e->Eoper = OPstreq;
 560:                 e->Ejty = e->Ety = TYstruct;
 561:                 e->ET = value->type->toCtype();
 562:             }
 563:         }
 564:         else
 565:             e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
 566:     }
 567:     incUsage(irs, loc);
 568:     block_appendexp(blx->curblock, e);
 569: 
 570:     bbody = blx->curblock;
 571:     if (body)
 572:         body->toIR(&mystate);
 573:     bbodyx = blx->curblock;
 574:     block_next(blx,BCgoto,mystate.contBlock);
 575: 
 576:     if (op == TOKforeach)
 577:     {
 578:         if (key)
 579:         {   // Construct (skey += 1)
 580:             e = el_bin(OPaddass, keytym, el_var(skey), el_long(keytym, 1));
 581:         }
 582:         else
 583:         {   // Construct (sp++)
 584:             e = el_bin(OPaddass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
 585:         }
 586:         mystate.contBlock->Belem = e;
 587:     }
 588:     block_next(blx,BCgoto,mystate.breakBlock);
 589: 
 590:     list_append(&bpre->Bsucc,bcond);
 591:     list_append(&bcond->Bsucc,bbody);
 592:     list_append(&bcond->Bsucc,mystate.breakBlock);
 593:     list_append(&bbodyx->Bsucc,mystate.contBlock);
 594:     list_append(&mystate.contBlock->Bsucc,bcond);
 595: #endif
 596: }
 597: 
 598: 
 599: /**************************************
 600:  */
 601: 
 602: #if DMDV2
 603: void ForeachRangeStatement::toIR(IRState *irs)
 604: {
 605:     assert(0);
 606: #if 0
 607:     Type *tab;
 608:     elem *eaggr;
 609:     elem *elwr;
 610:     elem *eupr;
 611:     elem *e;
 612:     elem *elength;
 613:     tym_t keytym;
 614: 
 615:     //printf("ForeachStatement::toIR()\n");
 616:     block *bpre;
 617:     block *bcond;
 618:     block *bbody;
 619:     block *bbodyx;
 620:     Blockx *blx = irs->blx;
 621: 
 622:     IRState mystate(irs,this);
 623:     mystate.breakBlock = block_calloc(blx);
 624:     mystate.contBlock = block_calloc(blx);
 625: 
 626:     incUsage(irs, lwr->loc);
 627:     elwr = lwr->toElem(irs);
 628: 
 629:     incUsage(irs, upr->loc);
 630:     eupr = upr->toElem(irs);
 631: 
 632:     /* Create skey, the index to the array.
 633:      * Initialize skey to elwr (foreach) or eupr (foreach_reverse).
 634:      */
 635:     Symbol *skey = key->toSymbol();
 636:     symbol_add(skey);
 637:     keytym = key->type->totym();
 638: 
 639:     elem *ekey;
 640:     if (key->offset)            // if key is member of a closure
 641:     {
 642:         assert(irs->sclosure);
 643:         ekey = el_var(irs->sclosure);
 644:         ekey = el_bin(OPadd, TYnptr, ekey, el_long(TYint, key->offset));
 645:         ekey = el_una(OPind, keytym, ekey);
 646:     }
 647:     else
 648:         ekey = el_var(skey);
 649: 
 650:     elem *einit = (op == TOKforeach_reverse) ? eupr : elwr;
 651:     e = el_bin(OPeq, keytym, ekey, einit);   // skey = einit;
 652:     block_appendexp(blx->curblock, e);
 653: 
 654:     /* Make a copy of the end condition, so it only
 655:      * gets evaluated once.
 656:      */
 657:     elem *eend = (op == TOKforeach_reverse) ? elwr : eupr;
 658:     Symbol *send = symbol_genauto(eend);
 659:     e = el_bin(OPeq, eend->Ety, el_var(send), eend);
 660:     assert(tybasic(e->Ety) != TYstruct);
 661:     block_appendexp(blx->curblock, e);
 662: 
 663:     bpre = blx->curblock;
 664:     block_next(blx,BCgoto,NULL);
 665:     bcond = blx->curblock;
 666: 
 667:     if (op == TOKforeach_reverse)
 668:     {
 669:         // Construct (key > elwr)
 670:         e = el_bin(OPgt, TYint, el_copytree(ekey), el_var(send));
 671:     }
 672:     else
 673:     {
 674:         // Construct (key < eupr)
 675:         e = el_bin(OPlt, TYint, el_copytree(ekey), el_var(send));
 676:     }
 677: 
 678:     // The size of the increment
 679:     size_t sz = 1;
 680:     Type *tkeyb = key->type->toBasetype();
 681:     if (tkeyb->ty == Tpointer)
 682:         sz = tkeyb->nextOf()->size();
 683: 
 684:     bcond->Belem = e;
 685:     block_next(blx, BCiftrue, NULL);
 686: 
 687:     if (op == TOKforeach_reverse)
 688:     {
 689:         // Construct (skey -= 1)
 690:         e = el_bin(OPminass, keytym, el_copytree(ekey), el_long(keytym, sz));
 691:         block_appendexp(blx->curblock, e);
 692:     }
 693: 
 694:     bbody = blx->curblock;
 695:     if (body)
 696:         body->toIR(&mystate);
 697:     bbodyx = blx->curblock;
 698:     block_next(blx,BCgoto,mystate.contBlock);
 699: 
 700:     if (op == TOKforeach)
 701:     {
 702:         // Construct (skey += 1)
 703:         e = el_bin(OPaddass, keytym, el_copytree(ekey), el_long(keytym, sz));
 704:         mystate.contBlock->Belem = e;
 705:     }
 706:     block_next(blx,BCgoto,mystate.breakBlock);
 707: 
 708:     list_append(&bpre->Bsucc,bcond);
 709:     list_append(&bcond->Bsucc,bbody);
 710:     list_append(&bcond->Bsucc,mystate.breakBlock);
 711:     list_append(&bbodyx->Bsucc,mystate.contBlock);
 712:     list_append(&mystate.contBlock->Bsucc,bcond);
 713: #endif
 714: }
 715: #endif
 716: 
 717: 
 718: /****************************************
 719:  */
 720: 
 721: void BreakStatement::toIR(IRState *irs)
 722: {
 723:     block *bbreak;
 724:     block *b;
 725:     Blockx *blx = irs->blx;
 726: 
 727:     bbreak = irs->getBreakBlock(ident);
 728:     assert(bbreak);
 729:     b = blx->curblock;
 730:     incUsage(irs, loc);
 731: 
 732:     // Adjust exception handler scope index if in different try blocks
 733:     if (b->Btry != bbreak->Btry)
 734:     {
 735:         //setScopeIndex(blx, b, bbreak->Btry ? bbreak->Btry->Bscope_index : -1);
 736:     }
 737: 
 738:     /* Nothing more than a 'goto' to the current break destination
 739:      */
 740:     list_append(&b->Bsucc, bbreak);
 741:     block_next(blx, BCgoto, NULL);
 742: }
 743: 
 744: /************************************
 745:  */
 746: 
 747: void ContinueStatement::toIR(IRState *irs)
 748: {
 749:     block *bcont;
 750:     block *b;
 751:     Blockx *blx = irs->blx;
 752: 
 753:     //printf("ContinueStatement::toIR() %p\n", this);
 754:     bcont = irs->getContBlock(ident);
 755:     assert(bcont);
 756:     b = blx->curblock;
 757:     incUsage(irs, loc);
 758: 
 759:     // Adjust exception handler scope index if in different try blocks
 760:     if (b->Btry != bcont->Btry)
 761:     {
 762:         //setScopeIndex(blx, b, bcont->Btry ? bcont->Btry->Bscope_index : -1);
 763:     }
 764: 
 765:     /* Nothing more than a 'goto' to the current continue destination
 766:      */
 767:     list_append(&b->Bsucc, bcont);
 768:     block_next(blx, BCgoto, NULL);
 769: }
 770: 
 771: /**************************************
 772:  */
 773: 
 774: void el_setVolatile(elem *e)
 775: {
 776:     elem_debug(e);
 777:     while (1)
 778:     {
 779:         e->Ety |= mTYvolatile;
 780:         if (OTunary(e->Eoper))
 781:             e = e->E1;
 782:         else if (OTbinary(e->Eoper))
 783:         {   el_setVolatile(e->E2);
 784:             e = e->E1;
 785:         }
 786:         else
 787:             break;
 788:     }
 789: }
 790: 
 791: void VolatileStatement::toIR(IRState *irs)
 792: {
 793:     block *b;
 794: 
 795:     if (statement)
 796:     {
 797:         Blockx *blx = irs->blx;
 798: 
 799:         block_goto(blx, BCgoto, NULL);
 800:         b = blx->curblock;
 801: 
 802:         statement->toIR(irs);
 803: 
 804:         block_goto(blx, BCgoto, NULL);
 805: 
 806:         // Mark the blocks generated as volatile
 807:         for (; b != blx->curblock; b = b->Bnext)
 808:         {   b->Bflags |= BFLvolatile;
 809:             if (b->Belem)
 810:                 el_setVolatile(b->Belem);
 811:         }
 812:     }
 813: }
 814: 
 815: /**************************************
 816:  */
 817: 
 818: void GotoStatement::toIR(IRState *irs)
 819: {
 820:     Blockx *blx = irs->blx;
 821: 
 822:     if (!label->statement)
 823:     {   error("label %s is undefined", label->toChars());
 824:         return;
 825:     }
 826:     if (tf != label->statement->tf)
 827:         error("cannot goto forward out of or into finally block");
 828: 
 829:     block *bdest = labelToBlock(loc, blx, label, 1);
 830:     if (!bdest)
 831:         return;
 832:     block *b = blx->curblock;
 833:     incUsage(irs, loc);
 834: 
 835:     if (b->Btry != bdest->Btry)
 836:     {
 837:         // Check that bdest is in an enclosing try block
 838:         for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry)
 839:         {
 840:             if (!bt)
 841:             {
 842:                 //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry);
 843:                 error("cannot goto into try block");
 844:                 break;
 845:             }
 846:         }
 847:     }
 848: 
 849:     list_append(&b->Bsucc,bdest);
 850:     block_next(blx,BCgoto,NULL);
 851: }
 852: 
 853: void LabelStatement::toIR(IRState *irs)
 854: {
 855:     //printf("LabelStatement::toIR() %p, statement = %p\n", this, statement);
 856:     Blockx *blx = irs->blx;
 857:     block *bc = blx->curblock;
 858:     IRState mystate(irs,this);
 859:     mystate.ident = ident;
 860: 
 861:     if (lblock)
 862:     {
 863:         // At last, we know which try block this label is inside
 864:         lblock->Btry = blx->tryblock;
 865: 
 866:         /* Go through the forward references and check.
 867:          */
 868:         if (fwdrefs)
 869:         {
 870:             for (int i = 0; i < fwdrefs->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
871: { block *b = fwdrefs->tdata()[i]; 872: 873: if (b->Btry != lblock->Btry) 874: { 875: // Check that lblock is in an enclosing try block 876: for (block *bt = b->Btry; bt != lblock->Btry; bt = bt->Btry) 877: { 878: if (!bt) 879: { 880: //printf("b->Btry = %p, lblock->Btry = %p\n", b->Btry, lblock->Btry); 881: error("cannot goto into try block"); 882: break; 883: } 884: } 885: } 886: 887: } 888: delete fwdrefs; 889: fwdrefs = NULL; 890: } 891: } 892: else 893: lblock = block_calloc(blx); 894: block_next(blx,BCgoto,lblock); 895: list_append(&bc->Bsucc,blx->curblock); 896: if (statement) 897: statement->toIR(&mystate); 898: } 899: 900: /************************************** 901: */ 902: 903: void SwitchStatement::toIR(IRState *irs) 904: { 905: int string; 906: Blockx *blx = irs->blx; 907: 908: //printf("SwitchStatement::toIR()\n"); 909: IRState mystate(irs,this); 910: 911: mystate.switchBlock = blx->curblock; 912: 913: /* Block for where "break" goes to 914: */ 915: mystate.breakBlock = block_calloc(blx); 916: 917: /* Block for where "default" goes to. 918: * If there is a default statement, then that is where default goes. 919: * If not, then do: 920: * default: break; 921: * by making the default block the same as the break block. 922: */ 923: mystate.defaultBlock = sdefault ? block_calloc(blx) : mystate.breakBlock; 924: 925: int numcases = 0; 926: if (cases) 927: numcases = cases->dim; 928: 929: incUsage(irs, loc); 930: elem *econd = condition->toElemDtor(&mystate); 931: #if DMDV2 932: if (hasVars) 933: { /* Generate a sequence of if-then-else blocks for the cases. 934: */ 935: if (econd->Eoper != OPvar) 936: { 937: elem *e = exp2_copytotemp(econd); 938: block_appendexp(mystate.switchBlock, e); 939: econd = e->E2; 940: } 941: 942: for (int i = 0; i < numcases; i++) 943: { CaseStatement *cs = cases->tdata()[i]; 944: 945: elem *ecase = cs->exp->toElemDtor(&mystate); 946: elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase); 947: block *b = blx->curblock; 948: block_appendexp(b, e); 949: block *bcase = block_calloc(blx); 950: cs->cblock = bcase; 951: block_next(blx, BCiftrue, NULL); 952: list_append(&b->Bsucc, bcase); 953: list_append(&b->Bsucc, blx->curblock); 954: } 955: 956: /* The final 'else' clause goes to the default 957: */ 958: block *b = blx->curblock; 959: block_next(blx, BCgoto, NULL); 960: list_append(&b->Bsucc, mystate.defaultBlock); 961: 962: body->toIR(&mystate); 963: 964: /* Have the end of the switch body fall through to the block 965: * following the switch statement. 966: */ 967: block_goto(blx, BCgoto, mystate.breakBlock); 968: return; 969: } 970: #endif 971: 972: if (condition->type->isString()) 973: { 974: // Number the cases so we can unscramble things after the sort() 975: for (int i = 0; i < numcases; i++) 976: { CaseStatement *cs = cases->tdata()[i]; 977: cs->index = i; 978: } 979: 980: cases->sort();
warning C6011: Dereferencing NULL pointer 'cases': Lines: 905, 906, 909, 911, 915, 923, 925, 926, 929, 930, 932, 972, 975, 980
981: 982: /* Create a sorted array of the case strings, and si 983: * will be the symbol for it. 984: */ 985: dt_t *dt = NULL; 986: Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray)); 987: #if MACHOBJ 988: si->Sseg = DATA; 989: #endif 990: dtsize_t(&dt, numcases); 991: dtxoff(&dt, si, PTRSIZE * 2, TYnptr); 992: 993: for (int i = 0; i < numcases; i++) 994: { CaseStatement *cs = cases->tdata()[i]; 995: 996: if (cs->exp->op != TOKstring) 997: { error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert 998: } 999: else 1000: { 1001: StringExp *se = (StringExp *)(cs->exp); 1002: unsigned len = se->len; 1003: dtsize_t(&dt, len); 1004: dtabytes(&dt, TYnptr, 0, se->len * se->sz, (char *)se->string); 1005: } 1006: } 1007: 1008: si->Sdt = dt; 1009: si->Sfl = FLdata; 1010: outdata(si); 1011: 1012: /* Call: 1013: * _d_switch_string(string[] si, string econd) 1014: */ 1015: elem *eparam = el_param(econd, el_var(si)); 1016: switch (condition->type->nextOf()->ty) 1017: { 1018: case Tchar: 1019: econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_STRING]), eparam); 1020: break; 1021: case Twchar: 1022: econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_USTRING]), eparam); 1023: break; 1024: case Tdchar: // BUG: implement 1025: econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_DSTRING]), eparam); 1026: break; 1027: default: 1028: assert(0); 1029: } 1030: elem_setLoc(econd, loc); 1031: string = 1; 1032: } 1033: else 1034: string = 0; 1035: block_appendexp(mystate.switchBlock, econd); 1036: block_next(blx,BCswitch,NULL); 1037: 1038: // Corresponding free is in block_free 1039: targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1)); 1040: mystate.switchBlock->BS.Bswitch = pu; 1041: /* First pair is the number of cases, and the default block 1042: */ 1043: *pu++ = numcases;
warning C6011: Dereferencing NULL pointer 'pu++': Lines: 905, 906, 909, 911, 915, 923, 925, 926, 927, 929, 930, 932, 972, 975, 980, 985, 986, 990, 991, 993, 1008, 1009, 1010, 1015, 1016, 1018, 1019, 1030, 1031, 1035, 1036, 1039, 1040, 1043
1044: list_append(&mystate.switchBlock->Bsucc, mystate.defaultBlock); 1045: 1046: /* Fill in the first entry in each pair, which is the case value. 1047: * CaseStatement::toIR() will fill in 1048: * the second entry for each pair with the block. 1049: */ 1050: for (int i = 0; i < numcases; i++) 1051: { 1052: CaseStatement *cs = cases->tdata()[i]; 1053: if (string) 1054: { 1055: pu[cs->index] = i; 1056: } 1057: else 1058: { 1059: pu[i] = cs->exp->toInteger(); 1060: } 1061: } 1062: 1063: body->toIR(&mystate); 1064: 1065: /* Have the end of the switch body fall through to the block 1066: * following the switch statement. 1067: */ 1068: block_goto(blx, BCgoto, mystate.breakBlock); 1069: } 1070: 1071: void CaseStatement::toIR(IRState *irs) 1072: { 1073: Blockx *blx = irs->blx; 1074: block *bcase = blx->curblock; 1075: if (!cblock) 1076: cblock = block_calloc(blx); 1077: block_next(blx,BCgoto,cblock); 1078: block *bsw = irs->getSwitchBlock(); 1079: if (bsw->BC == BCswitch) 1080: list_append(&bsw->Bsucc,cblock); // second entry in pair 1081: list_append(&bcase->Bsucc,cblock); 1082: if (blx->tryblock != bsw->Btry) 1083: error("case cannot be in different try block level from switch"); 1084: incUsage(irs, loc); 1085: if (statement) 1086: statement->toIR(irs); 1087: } 1088: 1089: void DefaultStatement::toIR(IRState *irs) 1090: { 1091: Blockx *blx = irs->blx; 1092: block *bcase = blx->curblock; 1093: block *bdefault = irs->getDefaultBlock(); 1094: block_next(blx,BCgoto,bdefault); 1095: list_append(&bcase->Bsucc,blx->curblock); 1096: if (blx->tryblock != irs->getSwitchBlock()->Btry) 1097: error("default cannot be in different try block level from switch"); 1098: incUsage(irs, loc); 1099: if (statement) 1100: statement->toIR(irs); 1101: } 1102: 1103: void GotoDefaultStatement::toIR(IRState *irs) 1104: { 1105: block *b; 1106: Blockx *blx = irs->blx; 1107: block *bdest = irs->getDefaultBlock(); 1108: 1109: b = blx->curblock; 1110: 1111: // The rest is equivalent to GotoStatement 1112: 1113: // Adjust exception handler scope index if in different try blocks 1114: if (b->Btry != bdest->Btry) 1115: { 1116: // Check that bdest is in an enclosing try block 1117: for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) 1118: { 1119: if (!bt) 1120: { 1121: //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); 1122: error("cannot goto into try block"); 1123: break; 1124: } 1125: } 1126: 1127: //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1); 1128: } 1129: 1130: list_append(&b->Bsucc,bdest); 1131: incUsage(irs, loc); 1132: block_next(blx,BCgoto,NULL); 1133: } 1134: 1135: void GotoCaseStatement::toIR(IRState *irs) 1136: { 1137: block *b; 1138: Blockx *blx = irs->blx; 1139: block *bdest = cs->cblock; 1140: 1141: if (!bdest) 1142: { 1143: bdest = block_calloc(blx); 1144: cs->cblock = bdest; 1145: } 1146: 1147: b = blx->curblock; 1148: 1149: // The rest is equivalent to GotoStatement 1150: 1151: // Adjust exception handler scope index if in different try blocks 1152: if (b->Btry != bdest->Btry) 1153: { 1154: // Check that bdest is in an enclosing try block 1155: for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry) 1156: { 1157: if (!bt) 1158: { 1159: //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry); 1160: error("cannot goto into try block"); 1161: break; 1162: } 1163: } 1164: 1165: //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1); 1166: } 1167: 1168: list_append(&b->Bsucc,bdest); 1169: incUsage(irs, loc); 1170: block_next(blx,BCgoto,NULL); 1171: } 1172: 1173: void SwitchErrorStatement::toIR(IRState *irs) 1174: { 1175: Blockx *blx = irs->blx; 1176: 1177: //printf("SwitchErrorStatement::toIR()\n"); 1178: 1179: elem *efilename = el_ptr(blx->module->toSymbol()); 1180: elem *elinnum = el_long(TYint, loc.linnum); 1181: elem *e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DSWITCHERR]), el_param(elinnum, efilename)); 1182: block_appendexp(blx->curblock, e); 1183: } 1184: 1185: /************************************** 1186: */ 1187: 1188: void ReturnStatement::toIR(IRState *irs) 1189: { 1190: Blockx *blx = irs->blx; 1191: 1192: incUsage(irs, loc); 1193: if (exp) 1194: { elem *e; 1195: 1196: FuncDeclaration *func = irs->getFunc(); 1197: assert(func); 1198: assert(func->type->ty == Tfunction); 1199: TypeFunction *tf = (TypeFunction *)(func->type); 1200: 1201: enum RET retmethod = tf->retStyle(); 1202: if (retmethod == RETstack) 1203: { 1204: elem *es; 1205: 1206: /* If returning struct literal, write result 1207: * directly into return value 1208: */ 1209: if (exp->op == TOKstructliteral) 1210: { StructLiteralExp *se = (StructLiteralExp *)exp; 1211: char save[sizeof(StructLiteralExp)]; 1212: memcpy(save, se, sizeof(StructLiteralExp)); 1213: se->sym = irs->shidden; 1214: se->soffset = 0; 1215: se->fillHoles = 1; 1216: e = exp->toElemDtor(irs); 1217: memcpy(se, save, sizeof(StructLiteralExp)); 1218: 1219: } 1220: else 1221: e = exp->toElemDtor(irs); 1222: assert(e); 1223: 1224: if (exp->op == TOKstructliteral || 1225: (func->nrvo_can && func->nrvo_var)) 1226: { 1227: // Return value via hidden pointer passed as parameter 1228: // Write exp; return shidden; 1229: es = e; 1230: } 1231: else 1232: { 1233: // Return value via hidden pointer passed as parameter 1234: // Write *shidden=exp; return shidden; 1235: int op; 1236: tym_t ety; 1237: 1238: ety = e->Ety; 1239: es = el_una(OPind,ety,el_var(irs->shidden)); 1240: op = (tybasic(ety) == TYstruct) ? OPstreq : OPeq; 1241: es = el_bin(op, ety, es, e); 1242: if (op == OPstreq) 1243: es->ET = exp->type->toCtype(); 1244: #if DMDV2 1245: /* Call postBlit() on *shidden 1246: */ 1247: Type *tb = exp->type->toBasetype(); 1248: //if (tb->ty == Tstruct) exp->dump(0); 1249: if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis) && 1250: tb->ty == Tstruct) 1251: { StructDeclaration *sd = ((TypeStruct *)tb)->sym; 1252: if (sd->postblit) 1253: { FuncDeclaration *fd = sd->postblit; 1254: if (fd->storage_class & STCdisable) 1255: { 1256: fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); 1257: } 1258: elem *ec = el_var(irs->shidden); 1259: ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL); 1260: es = el_bin(OPcomma, ec->Ety, es, ec); 1261: } 1262: 1263: #if 0 1264: /* It has been moved, so disable destructor 1265: */ 1266: if (exp->op == TOKvar) 1267: { VarExp *ve = (VarExp *)exp; 1268: VarDeclaration *v = ve->var->isVarDeclaration(); 1269: if (v && v->rundtor) 1270: { 1271: elem *er = el_var(v->rundtor->toSymbol()); 1272: er = el_bin(OPeq, TYint, er, el_long(TYint, 0)); 1273: es = el_bin(OPcomma, TYint, es, er); 1274: } 1275: } 1276: #endif 1277: } 1278: #endif 1279: } 1280: e = el_var(irs->shidden); 1281: e = el_bin(OPcomma, e->Ety, es, e); 1282: } 1283: #if DMDV2 1284: else if (tf->isref) 1285: { // Reference return, so convert to a pointer 1286: Expression *ae = exp->addressOf(NULL); 1287: e = ae->toElemDtor(irs); 1288: } 1289: #endif 1290: else 1291: { 1292: e = exp->toElemDtor(irs); 1293: assert(e); 1294: } 1295: 1296: elem_setLoc(e, loc); 1297: block_appendexp(blx->curblock, e); 1298: block_next(blx, BCretexp, NULL); 1299: } 1300: else 1301: block_next(blx, BCret, NULL); 1302: } 1303: 1304: /************************************** 1305: */ 1306: 1307: void ExpStatement::toIR(IRState *irs) 1308: { 1309: Blockx *blx = irs->blx; 1310: 1311: //printf("ExpStatement::toIR(), exp = %s\n", exp ? exp->toChars() : ""); 1312: incUsage(irs, loc); 1313: if (exp) 1314: block_appendexp(blx->curblock,exp->toElemDtor(irs)); 1315: } 1316: 1317: /************************************** 1318: */ 1319: 1320: void DtorExpStatement::toIR(IRState *irs) 1321: { 1322: //printf("DtorExpStatement::toIR(), exp = %s\n", exp ? exp->toChars() : ""); 1323: 1324: FuncDeclaration *fd = irs->getFunc(); 1325: assert(fd); 1326: if (fd->nrvo_can && fd->nrvo_var == var) 1327: /* Do not call destructor, because var is returned as the nrvo variable. 1328: * This is done at this stage because nrvo can be turned off at a 1329: * very late stage in semantic analysis. 1330: */ 1331: ; 1332: else 1333: { 1334: ExpStatement::toIR(irs); 1335: } 1336: } 1337: 1338: /************************************** 1339: */ 1340: 1341: void CompoundStatement::toIR(IRState *irs) 1342: { 1343: if (statements) 1344: { 1345: size_t dim = statements->dim; 1346: for (size_t i = 0 ; i < dim ; i++) 1347: { 1348: Statement *s = statements->tdata()[i]; 1349: if (s != NULL) 1350: { 1351: s->toIR(irs); 1352: } 1353: } 1354: } 1355: } 1356: 1357: 1358: /************************************** 1359: */ 1360: 1361: void UnrolledLoopStatement::toIR(IRState *irs) 1362: { 1363: Blockx *blx = irs->blx; 1364: 1365: IRState mystate(irs, this); 1366: mystate.breakBlock = block_calloc(blx); 1367: 1368: block *bpre = blx->curblock; 1369: block_next(blx, BCgoto, NULL); 1370: 1371: block *bdo = blx->curblock; 1372: list_append(&bpre->Bsucc, bdo); 1373: 1374: block *bdox; 1375: 1376: size_t dim = statements->dim; 1377: for (size_t i = 0 ; i < dim ; i++) 1378: { 1379: Statement *s = statements->tdata()[i]; 1380: if (s != NULL) 1381: { 1382: mystate.contBlock = block_calloc(blx); 1383: 1384: s->toIR(&mystate); 1385: 1386: bdox = blx->curblock; 1387: block_next(blx, BCgoto, mystate.contBlock); 1388: list_append(&bdox->Bsucc, mystate.contBlock); 1389: } 1390: } 1391: 1392: bdox = blx->curblock; 1393: block_next(blx, BCgoto, mystate.breakBlock); 1394: list_append(&bdox->Bsucc, mystate.breakBlock); 1395: } 1396: 1397: 1398: /************************************** 1399: */ 1400: 1401: void ScopeStatement::toIR(IRState *irs) 1402: { 1403: if (statement) 1404: { 1405: Blockx *blx = irs->blx; 1406: IRState mystate(irs,this); 1407: 1408: if (mystate.prev->ident) 1409: mystate.ident = mystate.prev->ident; 1410: 1411: statement->toIR(&mystate); 1412: 1413: if (mystate.breakBlock) 1414: block_goto(blx,BCgoto,mystate.breakBlock); 1415: } 1416: } 1417: 1418: /*************************************** 1419: */ 1420: 1421: void WithStatement::toIR(IRState *irs) 1422: { 1423: Symbol *sp; 1424: elem *e; 1425: elem *ei; 1426: ExpInitializer *ie; 1427: Blockx *blx = irs->blx; 1428: 1429: //printf("WithStatement::toIR()\n"); 1430: if (exp->op == TOKimport || exp->op == TOKtype) 1431: { 1432: } 1433: else 1434: { 1435: // Declare with handle 1436: sp = wthis->toSymbol(); 1437: symbol_add(sp); 1438: 1439: // Perform initialization of with handle 1440: ie = wthis->init->isExpInitializer(); 1441: assert(ie); 1442: ei = ie->exp->toElemDtor(irs); 1443: e = el_var(sp); 1444: e = el_bin(OPeq,e->Ety, e, ei); 1445: elem_setLoc(e, loc); 1446: incUsage(irs, loc); 1447: block_appendexp(blx->curblock,e); 1448: } 1449: // Execute with block 1450: if (body) 1451: body->toIR(irs); 1452: } 1453: 1454: 1455: /*************************************** 1456: */ 1457: 1458: void ThrowStatement::toIR(IRState *irs) 1459: { 1460: // throw(exp) 1461: 1462: Blockx *blx = irs->blx; 1463: 1464: incUsage(irs, loc); 1465: elem *e = exp->toElemDtor(irs); 1466: e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_THROWC]),e); 1467: block_appendexp(blx->curblock, e); 1468: } 1469: 1470: /*************************************** 1471: * Builds the following: 1472: * _try 1473: * block 1474: * jcatch 1475: * handler 1476: * A try-catch statement. 1477: */ 1478: 1479: void TryCatchStatement::toIR(IRState *irs) 1480: { 1481: Blockx *blx = irs->blx; 1482: 1483: #if SEH 1484: nteh_declarvars(blx); 1485: #endif 1486: 1487: IRState mystate(irs, this); 1488: 1489: block *tryblock = block_goto(blx,BCgoto,NULL); 1490: 1491: int previndex = blx->scope_index; 1492: tryblock->Blast_index = previndex; 1493: blx->scope_index = tryblock->Bscope_index = blx->next_index++; 1494: 1495: // Set the current scope index 1496: setScopeIndex(blx,tryblock,tryblock->Bscope_index); 1497: 1498: // This is the catch variable 1499: tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr)); 1500: 1501: blx->tryblock = tryblock; 1502: block *breakblock = block_calloc(blx); 1503: block_goto(blx,BC_try,NULL); 1504: if (body) 1505: { 1506: body->toIR(&mystate); 1507: } 1508: blx->tryblock = tryblock->Btry; 1509: 1510: // break block goes here 1511: block_goto(blx, BCgoto, breakblock); 1512: 1513: setScopeIndex(blx,blx->curblock, previndex); 1514: blx->scope_index = previndex; 1515: 1516: // create new break block that follows all the catches 1517: breakblock = block_calloc(blx); 1518: 1519: list_append(&blx->curblock->Bsucc, breakblock); 1520: block_next(blx,BCgoto,NULL); 1521: 1522: assert(catches); 1523: for (int i = 0 ; i < catches->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1524: { 1525: Catch *cs = catches->tdata()[i]; 1526: if (cs->var) 1527: cs->var->csym = tryblock->jcatchvar; 1528: block *bcatch = blx->curblock; 1529: if (cs->type) 1530: bcatch->Bcatchtype = cs->type->toBasetype()->toSymbol(); 1531: list_append(&tryblock->Bsucc,bcatch); 1532: block_goto(blx,BCjcatch,NULL); 1533: if (cs->handler != NULL) 1534: { 1535: IRState catchState(irs, this); 1536: cs->handler->toIR(&catchState); 1537: } 1538: list_append(&blx->curblock->Bsucc, breakblock); 1539: block_next(blx, BCgoto, NULL); 1540: } 1541: 1542: block_next(blx,(enum BC)blx->curblock->BC, breakblock); 1543: } 1544: 1545: /**************************************** 1546: * A try-finally statement. 1547: * Builds the following: 1548: * _try 1549: * block 1550: * _finally 1551: * finalbody 1552: * _ret 1553: */ 1554: 1555: void TryFinallyStatement::toIR(IRState *irs) 1556: { 1557: //printf("TryFinallyStatement::toIR()\n"); 1558: 1559: Blockx *blx = irs->blx; 1560: 1561: #if SEH 1562: nteh_declarvars(blx); 1563: #endif 1564: 1565: block *tryblock = block_goto(blx, BCgoto, NULL); 1566: 1567: int previndex = blx->scope_index; 1568: tryblock->Blast_index = previndex; 1569: tryblock->Bscope_index = blx->next_index++; 1570: blx->scope_index = tryblock->Bscope_index; 1571: 1572: // Current scope index 1573: setScopeIndex(blx,tryblock,tryblock->Bscope_index); 1574: 1575: blx->tryblock = tryblock; 1576: block_goto(blx,BC_try,NULL); 1577: 1578: IRState bodyirs(irs, this); 1579: block *breakblock = block_calloc(blx); 1580: block *contblock = block_calloc(blx); 1581: 1582: if (body) 1583: body->toIR(&bodyirs); 1584: blx->tryblock = tryblock->Btry; // back to previous tryblock 1585: 1586: setScopeIndex(blx,blx->curblock,previndex); 1587: blx->scope_index = previndex; 1588: 1589: block_goto(blx,BCgoto, breakblock); 1590: block *finallyblock = block_goto(blx,BCgoto,contblock); 1591: 1592: list_append(&tryblock->Bsucc,finallyblock); 1593: 1594: block_goto(blx,BC_finally,NULL); 1595: 1596: IRState finallyState(irs, this); 1597: breakblock = block_calloc(blx); 1598: contblock = block_calloc(blx); 1599: 1600: setScopeIndex(blx, blx->curblock, previndex); 1601: if (finalbody) 1602: finalbody->toIR(&finallyState); 1603: block_goto(blx, BCgoto, contblock); 1604: block_goto(blx, BCgoto, breakblock); 1605: 1606: block *retblock = blx->curblock; 1607: block_next(blx,BC_ret,NULL); 1608: 1609: list_append(&finallyblock->Bsucc, blx->curblock); 1610: list_append(&retblock->Bsucc, blx->curblock); 1611: } 1612: 1613: /**************************************** 1614: */ 1615: 1616: void SynchronizedStatement::toIR(IRState *irs) 1617: { 1618: assert(0); 1619: } 1620: 1621: 1622: /**************************************** 1623: */ 1624: 1625: void AsmStatement::toIR(IRState *irs) 1626: { 1627: block *bpre; 1628: block *basm; 1629: Declaration *d; 1630: Symbol *s; 1631: Blockx *blx = irs->blx; 1632: 1633: //printf("AsmStatement::toIR(asmcode = %x)\n", asmcode); 1634: bpre = blx->curblock; 1635: block_next(blx,BCgoto,NULL); 1636: basm = blx->curblock; 1637: list_append(&bpre->Bsucc, basm); 1638: basm->Bcode = asmcode; 1639: basm->Balign = asmalign; 1640: #if 0 1641: if (label) 1642: { block *b; 1643: 1644: b = labelToBlock(loc, blx, label); 1645: printf("AsmStatement::toIR() %p\n", b); 1646: if (b) 1647: list_append(&basm->Bsucc, b); 1648: } 1649: #endif 1650: // Loop through each instruction, fixing Dsymbols into Symbol's 1651: for (code *c = asmcode; c; c = c->next) 1652: { LabelDsymbol *label; 1653: block *b; 1654: 1655: switch (c->IFL1) 1656: { 1657: case FLblockoff: 1658: case FLblock: 1659: // FLblock and FLblockoff have LabelDsymbol's - convert to blocks 1660: label = c->IEVlsym1; 1661: b = labelToBlock(loc, blx, label); 1662: list_append(&basm->Bsucc, b); 1663: c->IEV1.Vblock = b; 1664: break; 1665: 1666: case FLdsymbol: 1667: case FLfunc: 1668: s = c->IEVdsym1->toSymbol(); 1669: if (s->Sclass == SCauto && s->Ssymnum == -1) 1670: symbol_add(s); 1671: c->IEVsym1 = s; 1672: c->IFL1 = s->Sfl ? s->Sfl : FLauto; 1673: break; 1674: } 1675: 1676: // Repeat for second operand 1677: switch (c->IFL2) 1678: { 1679: case FLblockoff: 1680: case FLblock: 1681: label = c->IEVlsym2; 1682: b = labelToBlock(loc, blx, label); 1683: list_append(&basm->Bsucc, b); 1684: c->IEV2.Vblock = b; 1685: break; 1686: 1687: case FLdsymbol: 1688: case FLfunc: 1689: d = c->IEVdsym2; 1690: s = d->toSymbol(); 1691: if (s->Sclass == SCauto && s->Ssymnum == -1) 1692: symbol_add(s); 1693: c->IEVsym2 = s; 1694: c->IFL2 = s->Sfl ? s->Sfl : FLauto; 1695: if (d->isDataseg()) 1696: s->Sflags |= SFLlivexit; 1697: break; 1698: } 1699: //c->print(); 1700: } 1701: 1702: basm->bIasmrefparam = refparam; // are parameters reference? 1703: basm->usIasmregs = regs; // registers modified 1704: 1705: block_next(blx,BCasm, NULL); 1706: list_prepend(&basm->Bsucc, blx->curblock); 1707: 1708: if (naked) 1709: { 1710: blx->funcsym->Stype->Tty |= mTYnaked; 1711: } 1712: } 1713: 1714: /**************************************** 1715: */ 1716: 1717: void ImportStatement::toIR(IRState *irs) 1718: { 1719: } 1720: 1721: 1722: 1723: