void TryFinallyStatement::toIR(IRState *irs) { //printf("TryFinallyStatement::toIR()\n"); Blockx *blx = irs->blx; #if SEH if (!global.params.is64bit) nteh_declarvars(blx); #endif block *tryblock = block_goto(blx, BCgoto, NULL); int previndex = blx->scope_index; tryblock->Blast_index = previndex; tryblock->Bscope_index = blx->next_index++; blx->scope_index = tryblock->Bscope_index; // Current scope index setScopeIndex(blx,tryblock,tryblock->Bscope_index); blx->tryblock = tryblock; block_goto(blx,BC_try,NULL); IRState bodyirs(irs, this); block *breakblock = block_calloc(blx); block *contblock = block_calloc(blx); tryblock->appendSucc(contblock); contblock->BC = BC_finally; if (body) body->toIR(&bodyirs); blx->tryblock = tryblock->Btry; // back to previous tryblock setScopeIndex(blx,blx->curblock,previndex); blx->scope_index = previndex; block_goto(blx,BCgoto, breakblock); block *finallyblock = block_goto(blx,BCgoto,contblock); assert(finallyblock == contblock); block_goto(blx,BC_finally,NULL); IRState finallyState(irs, this); breakblock = block_calloc(blx); contblock = block_calloc(blx); setScopeIndex(blx, blx->curblock, previndex); if (finalbody) finalbody->toIR(&finallyState); block_goto(blx, BCgoto, contblock); block_goto(blx, BCgoto, breakblock); block *retblock = blx->curblock; block_next(blx,BC_ret,NULL); finallyblock->appendSucc(blx->curblock); retblock->appendSucc(blx->curblock); }
void visit(TryFinallyStatement *s) { //printf("TryFinallyStatement::toIR()\n"); Blockx *blx = irs->blx; #if SEH if (!global.params.is64bit) nteh_declarvars(blx); #endif block *tryblock = block_goto(blx, BCgoto, NULL); int previndex = blx->scope_index; tryblock->Blast_index = previndex; tryblock->Bscope_index = blx->next_index++; blx->scope_index = tryblock->Bscope_index; // Current scope index setScopeIndex(blx,tryblock,tryblock->Bscope_index); blx->tryblock = tryblock; block_goto(blx,BC_try,NULL); IRState bodyirs(irs, s); block *breakblock = block_calloc(blx); block *contblock = block_calloc(blx); tryblock->appendSucc(contblock); contblock->BC = BC_finally; bodyirs.finallyBlock = contblock; if (s->_body) Statement_toIR(s->_body, &bodyirs); blx->tryblock = tryblock->Btry; // back to previous tryblock setScopeIndex(blx,blx->curblock,previndex); blx->scope_index = previndex; block_goto(blx,BCgoto, breakblock); block *finallyblock = block_goto(blx,BCgoto,contblock); assert(finallyblock == contblock); block_goto(blx,BC_finally,NULL); IRState finallyState(irs, s); breakblock = block_calloc(blx); contblock = block_calloc(blx); setScopeIndex(blx, blx->curblock, previndex); if (s->finalbody) Statement_toIR(s->finalbody, &finallyState); block_goto(blx, BCgoto, contblock); block_goto(blx, BCgoto, breakblock); block *retblock = blx->curblock; block_next(blx,BC_ret,NULL); finallyblock->appendSucc(blx->curblock); retblock->appendSucc(blx->curblock); /* The BCfinally..BC_ret blocks form a function that gets called from stack unwinding. * The successors to BC_ret blocks are both the next outer BCfinally and the destination * after the unwinding is complete. */ for (block *b = tryblock; b != finallyblock; b = b->Bnext) { block *btry = b->Btry; if (b->BC == BCgoto && b->numSucc() == 1) { block *bdest = b->nthSucc(0); if (btry && bdest->Btry != btry) { //printf("test1 b %p b->Btry %p bdest %p bdest->Btry %p\n", b, btry, bdest, bdest->Btry); block *bfinally = btry->nthSucc(1); if (bfinally == finallyblock) b->appendSucc(finallyblock); } } // If the goto exits a try block, then the finally block is also a successor if (b->BC == BCgoto && b->numSucc() == 2) // if goto exited a tryblock { block *bdest = b->nthSucc(0); // If the last finally block executed by the goto if (bdest->Btry == tryblock->Btry) // The finally block will exit and return to the destination block retblock->appendSucc(bdest); } if (b->BC == BC_ret && b->Btry == tryblock) { // b is nested inside this TryFinally, and so this finally will be called next b->appendSucc(finallyblock); } } }