Exemplo n.º 1
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(UnrolledLoopStatement *s)
    {
        Blockx *blx = irs->blx;

        IRState mystate(irs, s);
        mystate.breakBlock = block_calloc(blx);

        block *bpre = blx->curblock;
        block_next(blx, BCgoto, NULL);

        block *bdo = blx->curblock;
        bpre->appendSucc(bdo);

        block *bdox;

        size_t dim = s->statements->dim;
        for (size_t i = 0 ; i < dim ; i++)
        {
            Statement *s2 = (*s->statements)[i];
            if (s2 != NULL)
            {
                mystate.contBlock = block_calloc(blx);

                Statement_toIR(s2, &mystate);

                bdox = blx->curblock;
                block_next(blx, BCgoto, mystate.contBlock);
                bdox->appendSucc(mystate.contBlock);
            }
        }

        bdox = blx->curblock;
        block_next(blx, BCgoto, mystate.breakBlock);
        bdox->appendSucc(mystate.breakBlock);
    }
Exemplo n.º 2
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void DoStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    block *bpre = blx->curblock;
    block_next(blx, BCgoto, NULL);
    list_append(&bpre->Bsucc, blx->curblock);

    list_append(&mystate.contBlock->Bsucc, blx->curblock);
    list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);

    if (body)
        body->toIR(&mystate);
    list_append(&blx->curblock->Bsucc, mystate.contBlock);

    block_next(blx, BCgoto, mystate.contBlock);
    incUsage(irs, condition->loc);
    block_appendexp(mystate.contBlock, condition->toElemDtor(&mystate));
    block_next(blx, BCiftrue, mystate.breakBlock);

}
Exemplo n.º 3
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void WhileStatement::toIR(IRState *irs)
{
    assert(0); // was "lowered"
#if 0
    Blockx *blx = irs->blx;

    /* Create a new state, because we need a new continue and break target
     */
    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    list_append(&blx->curblock->Bsucc, mystate.contBlock);
    block_next(blx, BCgoto, mystate.contBlock);
    incUsage(irs, loc);
    block_appendexp(mystate.contBlock, condition->toElem(&mystate));

    block_next(blx, BCiftrue, NULL);

    /* curblock is the start of the while loop body
     */
    list_append(&mystate.contBlock->Bsucc, blx->curblock);
    if (body)
        body->toIR(&mystate);
    list_append(&blx->curblock->Bsucc, mystate.contBlock);
    block_next(blx, BCgoto, mystate.breakBlock);

    list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
#endif
}
Exemplo n.º 4
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(DoStatement *s)
    {
        Blockx *blx = irs->blx;

        IRState mystate(irs,s);
        mystate.breakBlock = block_calloc(blx);
        mystate.contBlock = block_calloc(blx);

        block *bpre = blx->curblock;
        block_next(blx, BCgoto, NULL);
        bpre->appendSucc(blx->curblock);

        mystate.contBlock->appendSucc(blx->curblock);
        mystate.contBlock->appendSucc(mystate.breakBlock);

        if (s->_body)
            Statement_toIR(s->_body, &mystate);
        blx->curblock->appendSucc(mystate.contBlock);

        block_next(blx, BCgoto, mystate.contBlock);
        incUsage(irs, s->condition->loc);
        block_appendexp(mystate.contBlock, toElemDtor(s->condition, &mystate));
        block_next(blx, BCiftrue, mystate.breakBlock);

    }
Exemplo n.º 5
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void UnrolledLoopStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;

    IRState mystate(irs, this);
    mystate.breakBlock = block_calloc(blx);

    block *bpre = blx->curblock;
    block_next(blx, BCgoto, NULL);

    block *bdo = blx->curblock;
    list_append(&bpre->Bsucc, bdo);

    block *bdox;

    size_t dim = statements->dim;
    for (size_t i = 0 ; i < dim ; i++)
    {
        Statement *s = statements->tdata()[i];
        if (s != NULL)
        {
            mystate.contBlock = block_calloc(blx);

            s->toIR(&mystate);

            bdox = blx->curblock;
            block_next(blx, BCgoto, mystate.contBlock);
            list_append(&bdox->Bsucc, mystate.contBlock);
        }
    }

    bdox = blx->curblock;
    block_next(blx, BCgoto, mystate.breakBlock);
    list_append(&bdox->Bsucc, mystate.breakBlock);
}
Exemplo n.º 6
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(ForStatement *s)
    {
        //printf("visit(ForStatement)) %u..%u\n", s->loc.linnum, s->endloc.linnum);
        Blockx *blx = irs->blx;

        IRState mystate(irs,s);
        mystate.breakBlock = block_calloc(blx);
        mystate.contBlock = block_calloc(blx);

        if (s->_init)
            Statement_toIR(s->_init, &mystate);
        block *bpre = blx->curblock;
        block_next(blx,BCgoto,NULL);
        block *bcond = blx->curblock;
        bpre->appendSucc(bcond);
        mystate.contBlock->appendSucc(bcond);
        if (s->condition)
        {
            incUsage(irs, s->condition->loc);
            block_appendexp(bcond, toElemDtor(s->condition, &mystate));
            block_next(blx,BCiftrue,NULL);
            bcond->appendSucc(blx->curblock);
            bcond->appendSucc(mystate.breakBlock);
        }
        else
        {   /* No conditional, it's a straight goto
             */
            block_next(blx,BCgoto,NULL);
            bcond->appendSucc(blx->curblock);
        }

        if (s->_body)
            Statement_toIR(s->_body, &mystate);
        /* End of the body goes to the continue block
         */
        blx->curblock->appendSucc(mystate.contBlock);
        block_setLoc(blx->curblock, s->endloc);
        block_next(blx, BCgoto, mystate.contBlock);

        if (s->increment)
        {
            incUsage(irs, s->increment->loc);
            block_appendexp(mystate.contBlock, toElemDtor(s->increment, &mystate));
        }

        /* The 'break' block follows the for statement.
         */
        block_next(blx,BCgoto, mystate.breakBlock);
    }
Exemplo n.º 7
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void IfStatement::toIR(IRState *irs)
{
    elem *e;
    Blockx *blx = irs->blx;

    //printf("IfStatement::toIR('%s')\n", condition->toChars());

    IRState mystate(irs, this);

    // bexit is the block that gets control after this IfStatement is done
    block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();

    incUsage(irs, loc);
#if 0
    if (match)
    {   /* Generate:
         *  if (match = RTLSYM_IFMATCH(string, pattern)) ...
         */
        assert(condition->op == TOKmatch);
        e = matchexp_toelem((MatchExp *)condition, &mystate, RTLSYM_IFMATCH);
        Symbol *s = match->toSymbol();
        symbol_add(s);
        e = el_bin(OPeq, TYnptr, el_var(s), e);
    }
    else
#endif
        e = condition->toElemDtor(&mystate);
    block_appendexp(blx->curblock, e);
    block *bcond = blx->curblock;
    block_next(blx, BCiftrue, NULL);

    list_append(&bcond->Bsucc, blx->curblock);
    if (ifbody)
        ifbody->toIR(&mystate);
    list_append(&blx->curblock->Bsucc, bexit);

    if (elsebody)
    {
        block_next(blx, BCgoto, NULL);
        list_append(&bcond->Bsucc, blx->curblock);
        elsebody->toIR(&mystate);
        list_append(&blx->curblock->Bsucc, bexit);
    }
    else
        list_append(&bcond->Bsucc, bexit);

    block_next(blx, BCgoto, bexit);

}
Exemplo n.º 8
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ScopeStatement::toIR(IRState *irs)
{
    if (statement)
    {
        Blockx *blx = irs->blx;
        IRState mystate(irs,this);

        if (mystate.prev->ident)
            mystate.ident = mystate.prev->ident;

        statement->toIR(&mystate);

        if (mystate.breakBlock)
            block_goto(blx,BCgoto,mystate.breakBlock);
    }
}
Exemplo n.º 9
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(ScopeStatement *s)
    {
        if (s->statement)
        {
            Blockx *blx = irs->blx;
            IRState mystate(irs,s);

            if (mystate.prev->ident)
                mystate.ident = mystate.prev->ident;

            Statement_toIR(s->statement, &mystate);

            if (mystate.breakBlock)
                block_goto(blx,BCgoto,mystate.breakBlock);
        }
    }
Exemplo n.º 10
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ForStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    if (init)
        init->toIR(&mystate);
    block *bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    block *bcond = blx->curblock;
    list_append(&bpre->Bsucc, bcond);
    list_append(&mystate.contBlock->Bsucc, bcond);
    if (condition)
    {
        incUsage(irs, condition->loc);
        block_appendexp(bcond, condition->toElemDtor(&mystate));
        block_next(blx,BCiftrue,NULL);
        list_append(&bcond->Bsucc, blx->curblock);
        list_append(&bcond->Bsucc, mystate.breakBlock);
    }
    else
    {   /* No conditional, it's a straight goto
         */
        block_next(blx,BCgoto,NULL);
        list_append(&bcond->Bsucc, blx->curblock);
    }

    if (body)
        body->toIR(&mystate);
    /* End of the body goes to the continue block
     */
    list_append(&blx->curblock->Bsucc, mystate.contBlock);
    block_next(blx, BCgoto, mystate.contBlock);

    if (increment)
    {
        incUsage(irs, increment->loc);
        block_appendexp(mystate.contBlock, increment->toElemDtor(&mystate));
    }

    /* The 'break' block follows the for statement.
     */
    block_next(blx,BCgoto, mystate.breakBlock);
}
Exemplo n.º 11
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void LabelStatement::toIR(IRState *irs)
{
    //printf("LabelStatement::toIR() %p, statement = %p\n", this, statement);
    Blockx *blx = irs->blx;
    block *bc = blx->curblock;
    IRState mystate(irs,this);
    mystate.ident = ident;

    if (lblock)
    {
        // At last, we know which try block this label is inside
        lblock->Btry = blx->tryblock;

        /* Go through the forward references and check.
         */
        if (fwdrefs)
        {
            for (size_t i = 0; i < fwdrefs->dim; i++)
            {   block *b = fwdrefs->tdata()[i];

                if (b->Btry != lblock->Btry)
                {
                    // Check that lblock is in an enclosing try block
                    for (block *bt = b->Btry; bt != lblock->Btry; bt = bt->Btry)
                    {
                        if (!bt)
                        {
                            //printf("b->Btry = %p, lblock->Btry = %p\n", b->Btry, lblock->Btry);
                            error("cannot goto into try block");
                            break;
                        }
                    }
                }

            }
            delete fwdrefs;
            fwdrefs = NULL;
        }
    }
    else
        lblock = block_calloc(blx);
    block_next(blx,BCgoto,lblock);
    list_append(&bc->Bsucc,blx->curblock);
    if (statement)
        statement->toIR(&mystate);
}
Exemplo n.º 12
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(LabelStatement *s)
    {
        //printf("LabelStatement::toIR() %p, statement = %p\n", this, statement);
        Blockx *blx = irs->blx;
        block *bc = blx->curblock;
        IRState mystate(irs,s);
        mystate.ident = s->ident;

        Label *label = getLabel(irs, blx, s);
        // At last, we know which try block this label is inside
        label->lblock->Btry = blx->tryblock;

        // Go through the forward references and check.
        if (label->fwdrefs)
        {
            block *b = label->fwdrefs;

            if (b->Btry != label->lblock->Btry)
            {
                // Check that lblock is in an enclosing try block
                for (block *bt = b->Btry; bt != label->lblock->Btry; bt = bt->Btry)
                {
                    if (!bt)
                    {
                        //printf("b->Btry = %p, label->lblock->Btry = %p\n", b->Btry, label->lblock->Btry);
                        s->error("cannot goto into try block");
                        break;
                    }

                }
            }
        }
        block_next(blx, BCgoto, label->lblock);
        bc->appendSucc(blx->curblock);
        if (s->statement)
            Statement_toIR(s->statement, &mystate);
    }
Exemplo n.º 13
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(IfStatement *s)
    {
        elem *e;
        Blockx *blx = irs->blx;

        //printf("IfStatement::toIR('%s')\n", s->condition->toChars());

        IRState mystate(irs, s);

        // bexit is the block that gets control after this IfStatement is done
        block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();

        incUsage(irs, s->loc);
        e = toElemDtor(s->condition, &mystate);
        block_appendexp(blx->curblock, e);
        block *bcond = blx->curblock;
        block_next(blx, BCiftrue, NULL);

        bcond->appendSucc(blx->curblock);
        if (s->ifbody)
            Statement_toIR(s->ifbody, &mystate);
        blx->curblock->appendSucc(bexit);

        if (s->elsebody)
        {
            block_next(blx, BCgoto, NULL);
            bcond->appendSucc(blx->curblock);
            Statement_toIR(s->elsebody, &mystate);
            blx->curblock->appendSucc(bexit);
        }
        else
            bcond->appendSucc(bexit);

        block_next(blx, BCgoto, bexit);

    }
Exemplo n.º 14
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(TryCatchStatement *s)
    {
        Blockx *blx = irs->blx;

#if SEH
        if (!global.params.is64bit)
            nteh_declarvars(blx);
#endif

        IRState mystate(irs, s);

        block *tryblock = block_goto(blx,BCgoto,NULL);

        int previndex = blx->scope_index;
        tryblock->Blast_index = previndex;
        blx->scope_index = tryblock->Bscope_index = blx->next_index++;

        // Set the current scope index
        setScopeIndex(blx,tryblock,tryblock->Bscope_index);

        // This is the catch variable
        tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));

        blx->tryblock = tryblock;
        block *breakblock = block_calloc(blx);
        block_goto(blx,BC_try,NULL);
        if (s->_body)
        {
            Statement_toIR(s->_body, &mystate);
        }
        blx->tryblock = tryblock->Btry;

        // break block goes here
        block_goto(blx, BCgoto, breakblock);

        setScopeIndex(blx,blx->curblock, previndex);
        blx->scope_index = previndex;

        // create new break block that follows all the catches
        breakblock = block_calloc(blx);

        blx->curblock->appendSucc(breakblock);
        block_next(blx,BCgoto,NULL);

        assert(s->catches);
        for (size_t i = 0 ; i < s->catches->dim; i++)
        {
            Catch *cs = (*s->catches)[i];
            if (cs->var)
                cs->var->csym = tryblock->jcatchvar;
            block *bcatch = blx->curblock;
            if (cs->type)
                bcatch->Bcatchtype = toSymbol(cs->type->toBasetype());
            tryblock->appendSucc(bcatch);
            block_goto(blx, BCjcatch, NULL);
            if (cs->handler != NULL)
            {
                IRState catchState(irs, s);

                /* Append to block:
                 *   *(sclosure + cs.offset) = cs;
                 */
                if (cs->var && cs->var->offset)
                {
                    tym_t tym = totym(cs->var->type);
                    elem *ex = el_var(irs->sclosure);
                    ex = el_bin(OPadd, TYnptr, ex, el_long(TYsize_t, cs->var->offset));
                    ex = el_una(OPind, tym, ex);
                    ex = el_bin(OPeq, tym, ex, el_var(toSymbol(cs->var)));
                    block_appendexp(catchState.blx->curblock, ex);
                }
                Statement_toIR(cs->handler, &catchState);
            }
            blx->curblock->appendSucc(breakblock);
            block_next(blx, BCgoto, NULL);
        }

        block_next(blx,(enum BC)blx->curblock->BC, breakblock);
    }
Exemplo n.º 15
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void TryCatchStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;

#if SEH
    nteh_declarvars(blx);
#endif

    IRState mystate(irs, this);

    block *tryblock = block_goto(blx,BCgoto,NULL);

    int previndex = blx->scope_index;
    tryblock->Blast_index = previndex;
    blx->scope_index = tryblock->Bscope_index = blx->next_index++;

    // Set the current scope index
    setScopeIndex(blx,tryblock,tryblock->Bscope_index);

    // This is the catch variable
    tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));

    blx->tryblock = tryblock;
    block *breakblock = block_calloc(blx);
    block_goto(blx,BC_try,NULL);
    if (body)
    {
        body->toIR(&mystate);
    }
    blx->tryblock = tryblock->Btry;

    // break block goes here
    block_goto(blx, BCgoto, breakblock);

    setScopeIndex(blx,blx->curblock, previndex);
    blx->scope_index = previndex;

    // create new break block that follows all the catches
    breakblock = block_calloc(blx);

    list_append(&blx->curblock->Bsucc, breakblock);
    block_next(blx,BCgoto,NULL);

    assert(catches);
    for (size_t i = 0 ; i < catches->dim; i++)
    {
        Catch *cs = catches->tdata()[i];
        if (cs->var)
            cs->var->csym = tryblock->jcatchvar;
        block *bcatch = blx->curblock;
        if (cs->type)
            bcatch->Bcatchtype = cs->type->toBasetype()->toSymbol();
        list_append(&tryblock->Bsucc,bcatch);
        block_goto(blx,BCjcatch,NULL);
        if (cs->handler != NULL)
        {
            IRState catchState(irs, this);
            cs->handler->toIR(&catchState);
        }
        list_append(&blx->curblock->Bsucc, breakblock);
        block_next(blx, BCgoto, NULL);
    }

    block_next(blx,(enum BC)blx->curblock->BC, breakblock);
}
Exemplo n.º 16
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ForeachStatement::toIR(IRState *irs)
{
    printf("ForeachStatement::toIR() %s\n", toChars());
    assert(0);  // done by "lowering" in the front end
#if 0
    Type *tab;
    elem *eaggr;
    elem *e;
    elem *elength;
    tym_t keytym;

    //printf("ForeachStatement::toIR()\n");
    block *bpre;
    block *bcond;
    block *bbody;
    block *bbodyx;
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    tab = aggr->type->toBasetype();
    assert(tab->ty == Tarray || tab->ty == Tsarray);

    incUsage(irs, aggr->loc);
    eaggr = aggr->toElem(irs);

    /* Create sp: pointer to start of array data
     */

    Symbol *sp = symbol_genauto(TYnptr);

    if (tab->ty == Tarray)
    {
        // stmp is copy of eaggr (the array), so eaggr is evaluated only once
        Symbol *stmp;

        // Initialize stmp
        stmp = symbol_genauto(eaggr);
        e = el_bin(OPeq, eaggr->Ety, el_var(stmp), eaggr);
        block_appendexp(blx->curblock, e);

        // Initialize sp
        e = el_una(OPmsw, TYnptr, el_var(stmp));
        e = el_bin(OPeq, TYnptr, el_var(sp), e);
        block_appendexp(blx->curblock, e);

        // Get array.length
        elength = el_var(stmp);
        elength->Ety = TYsize_t;
    }
    else // Tsarray
    {
        // Initialize sp
        e = el_una(OPaddr, TYnptr, eaggr);
        e = el_bin(OPeq, TYnptr, el_var(sp), e);
        block_appendexp(blx->curblock, e);

        // Get array.length
        elength = el_long(TYsize_t, ((TypeSArray *)tab)->dim->toInteger());
    }

    Symbol *spmax;
    Symbol *skey;

    if (key)
    {
        /* Create skey, the index to the array.
         * Initialize skey to 0 (foreach) or .length (foreach_reverse).
         */
        skey = key->toSymbol();
        symbol_add(skey);
        keytym = key->type->totym();
        elem *einit = (op == TOKforeach_reverse) ? elength : el_long(keytym, 0);
        e = el_bin(OPeq, keytym, el_var(skey), einit);
    }
    else
    {
        /* Create spmax, pointer past end of data.
         * Initialize spmax = sp + array.length * size
         */
        spmax = symbol_genauto(TYnptr);
        e = el_bin(OPmul, TYsize_t, elength, el_long(TYsize_t, tab->nextOf()->size()));
        e = el_bin(OPadd, TYnptr, el_var(sp), e);
        e = el_bin(OPeq, TYnptr, el_var(spmax), e);

        /* For foreach_reverse, swap sp and spmax
         */
        if (op == TOKforeach_reverse)
        {   Symbol *s = sp;
            sp = spmax;
            spmax = s;
        }
    }
    block_appendexp(blx->curblock, e);

    bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    bcond = blx->curblock;

    if (key)
    {
        if (op == TOKforeach_reverse)
        {
            // Construct (key != 0)
            e = el_bin(OPne, TYint, el_var(skey), el_long(keytym, 0));
        }
        else
        {
            // Construct (key < elength)
            e = el_bin(OPlt, TYint, el_var(skey), elength);
        }
    }
    else
    {
        if (op == TOKforeach_reverse)
        {
            // Construct (sp > spmax)
            e = el_bin(OPgt, TYint, el_var(sp), el_var(spmax));
        }
        else
        {
            // Construct (sp < spmax)
            e = el_bin(OPlt, TYint, el_var(sp), el_var(spmax));
        }
    }
    bcond->Belem = e;
    block_next(blx, BCiftrue, NULL);

    if (op == TOKforeach_reverse)
    {
        if (key)
        {   // Construct (skey -= 1)
            e = el_bin(OPminass, keytym, el_var(skey), el_long(keytym, 1));
        }
        else
        {   // Construct (sp--)
            e = el_bin(OPminass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
        }
        block_appendexp(blx->curblock, e);
    }

    Symbol *s;
    FuncDeclaration *fd = NULL;
    if (value->toParent2())
        fd = value->toParent2()->isFuncDeclaration();
    int nrvo = 0;
    if (fd && fd->nrvo_can && fd->nrvo_var == value)
    {
        s = fd->shidden;
        nrvo = 1;
    }
    else
    {   s = value->toSymbol();
        symbol_add(s);
    }

    // Construct (value = *sp) or (value = sp[skey * elemsize])
    tym_t tym = value->type->totym();
    if (key)
    {   // sp + skey * elemsize
        e = el_bin(OPmul, keytym, el_var(skey), el_long(keytym, tab->nextOf()->size()));
        e = el_bin(OPadd, TYnptr, el_var(sp), e);
    }
    else
        e = el_var(sp);

    elem *evalue;
#if DMDV2
    if (value->offset)  // if value is a member of a closure
    {
        assert(irs->sclosure);
        evalue = el_var(irs->sclosure);
        evalue = el_bin(OPadd, TYnptr, evalue, el_long(TYint, value->offset));
        evalue = el_una(OPind, value->type->totym(), evalue);
    }
    else
#endif
        evalue = el_var(s);

    if (value->isOut() || value->isRef())
    {
        assert(value->storage_class & (STCout | STCref));
        e = el_bin(OPeq, TYnptr, evalue, e);
    }
    else
    {
        if (nrvo)
            evalue = el_una(OPind, tym, evalue);
        StructDeclaration *sd = needsPostblit(value->type);
        if (tybasic(tym) == TYstruct)
        {
            e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
            e->Eoper = OPstreq;
            e->ET = value->type->toCtype();
#if DMDV2
            // Call postblit on e
            if (sd)
            {   FuncDeclaration *fd = sd->postblit;
                elem *ec = el_copytree(evalue);
                ec = el_una(OPaddr, TYnptr, ec);
                ec = callfunc(loc, irs, 1, Type::tvoid, ec, sd->type->pointerTo(), fd, fd->type, NULL, NULL);
                e = el_combine(e, ec);
            }
#endif
        }
        else if (tybasic(tym) == TYarray)
        {
            if (sd)
            {
                /* Generate:
                 *      _d_arrayctor(ti, efrom, eto)
                 */
                Expression *ti = value->type->toBasetype()->nextOf()->toBasetype()->getTypeInfo(NULL);
                elem *esize = el_long(TYsize_t, ((TypeSArray *)value->type->toBasetype())->dim->toInteger());
                elem *eto = el_pair(TYdarray, esize, el_una(OPaddr, TYnptr, evalue));
                elem *efrom = el_pair(TYdarray, el_copytree(esize), e);
                elem *ep = el_params(eto, efrom, ti->toElem(irs), NULL);
                int rtl = RTLSYM_ARRAYCTOR;
                e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), ep);
            }
            else
            {
                e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
                e->Eoper = OPstreq;
                e->Ejty = e->Ety = TYstruct;
                e->ET = value->type->toCtype();
            }
        }
        else
            e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
    }
    incUsage(irs, loc);
    block_appendexp(blx->curblock, e);

    bbody = blx->curblock;
    if (body)
        body->toIR(&mystate);
    bbodyx = blx->curblock;
    block_next(blx,BCgoto,mystate.contBlock);

    if (op == TOKforeach)
    {
        if (key)
        {   // Construct (skey += 1)
            e = el_bin(OPaddass, keytym, el_var(skey), el_long(keytym, 1));
        }
        else
        {   // Construct (sp++)
            e = el_bin(OPaddass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
        }
        mystate.contBlock->Belem = e;
    }
    block_next(blx,BCgoto,mystate.breakBlock);

    list_append(&bpre->Bsucc,bcond);
    list_append(&bcond->Bsucc,bbody);
    list_append(&bcond->Bsucc,mystate.breakBlock);
    list_append(&bbodyx->Bsucc,mystate.contBlock);
    list_append(&mystate.contBlock->Bsucc,bcond);
#endif
}
Exemplo n.º 17
0
Arquivo: s2ir.c Projeto: Faianca/dmd
    void visit(SwitchStatement *s)
    {
        int string;
        Blockx *blx = irs->blx;

        //printf("SwitchStatement::toIR()\n");
        IRState mystate(irs,s);

        mystate.switchBlock = blx->curblock;

        /* Block for where "break" goes to
         */
        mystate.breakBlock = block_calloc(blx);

        /* Block for where "default" goes to.
         * If there is a default statement, then that is where default goes.
         * If not, then do:
         *   default: break;
         * by making the default block the same as the break block.
         */
        mystate.defaultBlock = s->sdefault ? block_calloc(blx) : mystate.breakBlock;

        size_t numcases = 0;
        if (s->cases)
            numcases = s->cases->dim;

        incUsage(irs, s->loc);
        elem *econd = toElemDtor(s->condition, &mystate);
        if (s->hasVars)
        {   /* Generate a sequence of if-then-else blocks for the cases.
             */
            if (econd->Eoper != OPvar)
            {
                elem *e = exp2_copytotemp(econd);
                block_appendexp(mystate.switchBlock, e);
                econd = e->E2;
            }

            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];

                elem *ecase = toElemDtor(cs->exp, &mystate);
                elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase);
                block *b = blx->curblock;
                block_appendexp(b, e);
                Label *clabel = getLabel(irs, blx, cs);
                block_next(blx, BCiftrue, NULL);
                b->appendSucc(clabel->lblock);
                b->appendSucc(blx->curblock);
            }

            /* The final 'else' clause goes to the default
             */
            block *b = blx->curblock;
            block_next(blx, BCgoto, NULL);
            b->appendSucc(mystate.defaultBlock);

            Statement_toIR(s->_body, &mystate);

            /* Have the end of the switch body fall through to the block
             * following the switch statement.
             */
            block_goto(blx, BCgoto, mystate.breakBlock);
            return;
        }

        if (s->condition->type->isString())
        {
            // Number the cases so we can unscramble things after the sort()
            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];
                cs->index = i;
            }

            s->cases->sort();

            /* Create a sorted array of the case strings, and si
             * will be the symbol for it.
             */
            dt_t *dt = NULL;
            Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray));
            dtsize_t(&dt, numcases);
            dtxoff(&dt, si, Target::ptrsize * 2, TYnptr);

            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];

                if (cs->exp->op != TOKstring)
                {   s->error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert
                }
                else
                {
                    StringExp *se = (StringExp *)(cs->exp);
                    Symbol *si = toStringSymbol((char *)se->string, se->len, se->sz);
                    dtsize_t(&dt, se->len);
                    dtxoff(&dt, si, 0);
                }
            }

            si->Sdt = dt;
            si->Sfl = FLdata;
            outdata(si);

            /* Call:
             *      _d_switch_string(string[] si, string econd)
             */
            if (config.exe == EX_WIN64)
                econd = addressElem(econd, s->condition->type, true);
            elem *eparam = el_param(econd, (config.exe == EX_WIN64) ? el_ptr(si) : el_var(si));
            switch (s->condition->type->nextOf()->ty)
            {
                case Tchar:
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_STRING)), eparam);
                    break;
                case Twchar:
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_USTRING)), eparam);
                    break;
                case Tdchar:        // BUG: implement
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_DSTRING)), eparam);
                    break;
                default:
                    assert(0);
            }
            elem_setLoc(econd, s->loc);
            string = 1;
        }
        else
            string = 0;
        block_appendexp(mystate.switchBlock, econd);
        block_next(blx,BCswitch,NULL);

        // Corresponding free is in block_free
        targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1));
        mystate.switchBlock->BS.Bswitch = pu;
        /* First pair is the number of cases, and the default block
         */
        *pu++ = numcases;
        mystate.switchBlock->appendSucc(mystate.defaultBlock);

        /* Fill in the first entry in each pair, which is the case value.
         * CaseStatement::toIR() will fill in
         * the second entry for each pair with the block.
         */
        for (size_t i = 0; i < numcases; i++)
        {
            CaseStatement *cs = (*s->cases)[i];
            if (string)
            {
                pu[cs->index] = i;
            }
            else
            {
                pu[i] = cs->exp->toInteger();
            }
        }

        Statement_toIR(s->_body, &mystate);

        /* Have the end of the switch body fall through to the block
         * following the switch statement.
         */
        block_goto(blx, BCgoto, mystate.breakBlock);
    }
Exemplo n.º 18
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ForeachRangeStatement::toIR(IRState *irs)
{
    assert(0);
#if 0
    Type *tab;
    elem *eaggr;
    elem *elwr;
    elem *eupr;
    elem *e;
    elem *elength;
    tym_t keytym;

    //printf("ForeachStatement::toIR()\n");
    block *bpre;
    block *bcond;
    block *bbody;
    block *bbodyx;
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    incUsage(irs, lwr->loc);
    elwr = lwr->toElem(irs);

    incUsage(irs, upr->loc);
    eupr = upr->toElem(irs);

    /* Create skey, the index to the array.
     * Initialize skey to elwr (foreach) or eupr (foreach_reverse).
     */
    Symbol *skey = key->toSymbol();
    symbol_add(skey);
    keytym = key->type->totym();

    elem *ekey;
    if (key->offset)            // if key is member of a closure
    {
        assert(irs->sclosure);
        ekey = el_var(irs->sclosure);
        ekey = el_bin(OPadd, TYnptr, ekey, el_long(TYint, key->offset));
        ekey = el_una(OPind, keytym, ekey);
    }
    else
        ekey = el_var(skey);

    elem *einit = (op == TOKforeach_reverse) ? eupr : elwr;
    e = el_bin(OPeq, keytym, ekey, einit);   // skey = einit;
    block_appendexp(blx->curblock, e);

    /* Make a copy of the end condition, so it only
     * gets evaluated once.
     */
    elem *eend = (op == TOKforeach_reverse) ? elwr : eupr;
    Symbol *send = symbol_genauto(eend);
    e = el_bin(OPeq, eend->Ety, el_var(send), eend);
    assert(tybasic(e->Ety) != TYstruct);
    block_appendexp(blx->curblock, e);

    bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    bcond = blx->curblock;

    if (op == TOKforeach_reverse)
    {
        // Construct (key > elwr)
        e = el_bin(OPgt, TYint, el_copytree(ekey), el_var(send));
    }
    else
    {
        // Construct (key < eupr)
        e = el_bin(OPlt, TYint, el_copytree(ekey), el_var(send));
    }

    // The size of the increment
    size_t sz = 1;
    Type *tkeyb = key->type->toBasetype();
    if (tkeyb->ty == Tpointer)
        sz = tkeyb->nextOf()->size();

    bcond->Belem = e;
    block_next(blx, BCiftrue, NULL);

    if (op == TOKforeach_reverse)
    {
        // Construct (skey -= 1)
        e = el_bin(OPminass, keytym, el_copytree(ekey), el_long(keytym, sz));
        block_appendexp(blx->curblock, e);
    }

    bbody = blx->curblock;
    if (body)
        body->toIR(&mystate);
    bbodyx = blx->curblock;
    block_next(blx,BCgoto,mystate.contBlock);

    if (op == TOKforeach)
    {
        // Construct (skey += 1)
        e = el_bin(OPaddass, keytym, el_copytree(ekey), el_long(keytym, sz));
        mystate.contBlock->Belem = e;
    }
    block_next(blx,BCgoto,mystate.breakBlock);

    list_append(&bpre->Bsucc,bcond);
    list_append(&bcond->Bsucc,bbody);
    list_append(&bcond->Bsucc,mystate.breakBlock);
    list_append(&bbodyx->Bsucc,mystate.contBlock);
    list_append(&mystate.contBlock->Bsucc,bcond);
#endif
}
Exemplo n.º 19
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void SwitchStatement::toIR(IRState *irs)
{
    int string;
    Blockx *blx = irs->blx;

    //printf("SwitchStatement::toIR()\n");
    IRState mystate(irs,this);

    mystate.switchBlock = blx->curblock;

    /* Block for where "break" goes to
     */
    mystate.breakBlock = block_calloc(blx);

    /* Block for where "default" goes to.
     * If there is a default statement, then that is where default goes.
     * If not, then do:
     *   default: break;
     * by making the default block the same as the break block.
     */
    mystate.defaultBlock = sdefault ? block_calloc(blx) : mystate.breakBlock;

    int numcases = 0;
    if (cases)
        numcases = cases->dim;

    incUsage(irs, loc);
    elem *econd = condition->toElemDtor(&mystate);
#if DMDV2
    if (hasVars)
    {   /* Generate a sequence of if-then-else blocks for the cases.
         */
        if (econd->Eoper != OPvar)
        {
            elem *e = exp2_copytotemp(econd);
            block_appendexp(mystate.switchBlock, e);
            econd = e->E2;
        }

        for (int i = 0; i < numcases; i++)
        {   CaseStatement *cs = cases->tdata()[i];

            elem *ecase = cs->exp->toElemDtor(&mystate);
            elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase);
            block *b = blx->curblock;
            block_appendexp(b, e);
            block *bcase = block_calloc(blx);
            cs->cblock = bcase;
            block_next(blx, BCiftrue, NULL);
            list_append(&b->Bsucc, bcase);
            list_append(&b->Bsucc, blx->curblock);
        }

        /* The final 'else' clause goes to the default
         */
        block *b = blx->curblock;
        block_next(blx, BCgoto, NULL);
        list_append(&b->Bsucc, mystate.defaultBlock);

        body->toIR(&mystate);

        /* Have the end of the switch body fall through to the block
         * following the switch statement.
         */
        block_goto(blx, BCgoto, mystate.breakBlock);
        return;
    }
#endif

    if (condition->type->isString())
    {
        // Number the cases so we can unscramble things after the sort()
        for (int i = 0; i < numcases; i++)
        {   CaseStatement *cs = cases->tdata()[i];
            cs->index = i;
        }

        cases->sort();

        /* Create a sorted array of the case strings, and si
         * will be the symbol for it.
         */
        dt_t *dt = NULL;
        Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray));
#if MACHOBJ
        si->Sseg = DATA;
#endif
        dtsize_t(&dt, numcases);
        dtxoff(&dt, si, PTRSIZE * 2, TYnptr);

        for (int i = 0; i < numcases; i++)
        {   CaseStatement *cs = cases->tdata()[i];

            if (cs->exp->op != TOKstring)
            {   error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert
            }
            else
            {
                StringExp *se = (StringExp *)(cs->exp);
                unsigned len = se->len;
                dtsize_t(&dt, len);
                dtabytes(&dt, TYnptr, 0, se->len * se->sz, (char *)se->string);
            }
        }

        si->Sdt = dt;
        si->Sfl = FLdata;
        outdata(si);

        /* Call:
         *      _d_switch_string(string[] si, string econd)
         */
        elem *eparam = el_param(econd, el_var(si));
        switch (condition->type->nextOf()->ty)
        {
        case Tchar:
            econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_STRING]), eparam);
            break;
        case Twchar:
            econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_USTRING]), eparam);
            break;
        case Tdchar:        // BUG: implement
            econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_DSTRING]), eparam);
            break;
        default:
            assert(0);
        }
        elem_setLoc(econd, loc);
        string = 1;
    }
    else
        string = 0;
    block_appendexp(mystate.switchBlock, econd);
    block_next(blx,BCswitch,NULL);

    // Corresponding free is in block_free
    targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1));
    mystate.switchBlock->BS.Bswitch = pu;
    /* First pair is the number of cases, and the default block
     */
    *pu++ = numcases;
    list_append(&mystate.switchBlock->Bsucc, mystate.defaultBlock);

    /* Fill in the first entry in each pair, which is the case value.
     * CaseStatement::toIR() will fill in
     * the second entry for each pair with the block.
     */
    for (int i = 0; i < numcases; i++)
    {
        CaseStatement *cs = cases->tdata()[i];
        if (string)
        {
            pu[cs->index] = i;
        }
        else
        {
            pu[i] = cs->exp->toInteger();
        }
    }

    body->toIR(&mystate);

    /* Have the end of the switch body fall through to the block
     * following the switch statement.
     */
    block_goto(blx, BCgoto, mystate.breakBlock);
}