Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
Archivo: s2ir.c Proyecto: Faianca/dmd
    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);
            }
        }
    }