Esempio n. 1
0
EXPRESSION *doinline(FUNCTIONCALL *params, SYMBOL *funcsp)
{
    static SYMBOL *curfunc;
    STATEMENT *stmt = NULL, **stp = &stmt;
    EXPRESSION *newExpression;
    BOOL allocated = FALSE;
    if (funcsp)
        curfunc = funcsp;
    if (!isfunction(params->functp))
        return NULL;
    if (params->sp->linkage != lk_inline)
        return NULL;
    if (!params->sp->inlineFunc.syms)
        return NULL;

    if (!localNameSpace->syms)
    {
        allocated = TRUE;
        AllocateLocalContext(NULL, NULL);
    }
    stmt = SetupArguments(params);
    SetupVariables(params->sp);

    while (*stp)
        stp = &(*stp)->next;
    *stp = inlinestmt(params->sp->inlineFunc.stmt);
    newExpression = exprNode(en_stmt, NULL, NULL);
    newExpression->v.stmt = stmt;
    
    if (params->sp->retcount == 1)
    {
        /* optimization for simple inline functions that only have
         * one return statement, don't save to an intermediate variable
         */
        newExpression->left = scanReturn(stmt, basetype(params->sp->tp)->btp);
    }
    else
    {
        newExpression->left = newReturn(basetype(params->sp->tp)->btp);
        reduceReturns(stmt, params->sp->tp->btp, newExpression->left);
    }

    if (params->sp->storage_class == sc_virtual || params->sp->storage_class == sc_member)
        thisptrs = thisptrs->next;
        
    if (allocated)
    {
        FreeLocalContext(NULL, NULL);
    }
    if (funcsp)
        curfunc = NULL;
    return newExpression;
}
Esempio n. 2
0
IMODE *imake_label(int label)
/*
 *      make a node to reference an immediate value i.
 */

{
    IMODE *ap = (IMODE *)Alloc(sizeof(IMODE));
    ap->mode = i_immed;
    ap->offset = exprNode(en_labcon, NULL, NULL);
    ap->offset->v.i = label;
    ap->size = ISZ_ADDR;
        return ap;
}
Esempio n. 3
0
static void inlineResetReturn(STATEMENT *block, TYPE *rettp, EXPRESSION *retnode)
{
    EXPRESSION *exp;
    if (isstructured(rettp))
    {
        diag("structure in inlineResetReturn");
    }
    else
    {
        exp = block->select;
        cast(rettp, &exp);
        exp = exprNode(en_assign, retnode, exp);
    }
    block->type = st_expr;
    block->select = exp;
}
Esempio n. 4
0
static STATEMENT *SetupArguments(FUNCTIONCALL *params)
{
    STATEMENT *st = NULL, **stp = &st;
    ARGLIST *al = params->arguments;
    HASHREC *hr = params->sp->inlineFunc.syms->table[0];
    while (al && hr)
    {
        SYMBOL *sx;
        if (al == params->arguments && (params->sp->storage_class == sc_member || params->sp->storage_class == sc_virtual))
        {
            LIST *l = Alloc(sizeof(LIST));
            l->next = thisptrs;
            thisptrs = l;
            l->data = (void *)(sx = makeID(sc_auto, &stdpointer, NULL, "__$this$__"));
        }
        else
        {
            sx = (SYMBOL *)hr->p;
        }
        if (!sx->altered && !sx->addressTaken && !sideEffects(al->exp))
        {
            // well if the expression is too complicated it gets evaluated over and over
            // but maybe the backend can clean it up again...
            sx->inlineFunc.stmt = (STATEMENT *)al->exp;
        }
        else
        {
            EXPRESSION *tnode = varNode(en_auto, anonymousVar(sc_auto, sx->tp));
            deref(sx->tp, &tnode);
            sx->inlineFunc.stmt = (STATEMENT *)tnode;
            tnode = exprNode(en_assign, tnode, al->exp);
            *stp = Alloc(sizeof(STATEMENT));
            memset(*stp, 0 , sizeof(STATEMENT));
            (*stp)->type = st_expr;
            (*stp)->select = tnode;
            stp = &(*stp)->next;
        }
        al = al->next;
        if (hr)
            hr = hr->next;
    }
    return st;
}
Esempio n. 5
0
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP)
/*
 *      generate a return statement.
 */
{
    IMODE *ap,  *ap1, *ap3;
    EXPRESSION ep;
    /* returns a value? */
    if (stmt != 0 && stmt->select != 0)
    {
        if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) ||
                                          basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr))
        {
            SYMBOL *sp = anonymousVar(sc_parameter, &stdpointer);
            EXPRESSION *en = varNode(en_auto, sp);
            IMODE *ap3 = gen_expr(funcsp, stmt->select, 0, ISZ_ADDR), *ap2, *ap1;
            DumpIncDec(funcsp);
            if (!ap3->retval)
            {
                ap1 = LookupLoadTemp(NULL, ap3);
                if (ap1 != ap3)
                {
                    IMODE *barrier;
                    if (stmt->select->isatomic)
                    {
                        barrier = doatomicFence(funcsp, stmt->select, NULL);
                    }
                    gen_icode(i_assn, ap1, ap3, NULL);
                    if (stmt->select->isatomic)
                    {
                        doatomicFence(funcsp, stmt->select, barrier);
                    }
                }
            }
            else
            {
                ap1 = ap3;
            }
            if ((funcsp->linkage == lk_pascal) &&
                basetype(funcsp->tp)->syms->table[0] && 
                ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void)
            {
                sp->offset = funcsp->paramsize;
            }
            else
            {
                sp->offset = chosenAssembler->arch->retblocksize+(funcsp->farproc
                    *getSize(bt_pointer));
                if (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual)
                    sp->offset += getSize(bt_pointer);
            }
                
            en = exprNode(en_l_p, en, NULL);
            ap3 = gen_expr(funcsp, en, 0, ISZ_ADDR);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (en->isatomic)
                {
                    barrier = doatomicFence(funcsp, en, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (en->isatomic)
                {
                    doatomicFence(funcsp, en, barrier);
                }
            }
            gen_icode(i_assnblock, make_immed(ISZ_NONE, basetype(funcsp->tp)->btp->size),
                      ap, ap1);
            ap1 = tempreg(ISZ_ADDR, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, NULL);
        }
        else if (basetype(funcsp->tp)->btp && basetype(funcsp->tp)->btp->type ==
            bt_memberptr)
        {
            ap3 = gen_expr(funcsp, stmt->select, F_VOL, ISZ_ADDR);
            DumpIncDec(funcsp);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (stmt->select->isatomic)
                {
                    barrier = doatomicFence(funcsp, stmt->select, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (stmt->select->isatomic)
                {
                    doatomicFence(funcsp, stmt->select, barrier);
                }
            }
            ap1 = tempreg(ISZ_ADDR, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, 0);
        }
        else
        {
            int size = natural_size(stmt->select);
            ap3 = gen_expr(funcsp, stmt->select, 0, size);
            DumpIncDec(funcsp);
            ap = LookupLoadTemp(NULL, ap3);
            if (ap != ap3)
            {
                IMODE *barrier;
                if (stmt->select->isatomic)
                {
                    barrier = doatomicFence(funcsp, stmt->select, NULL);
                }
                gen_icode(i_assn, ap, ap3, NULL);
                if (stmt->select->isatomic)
                {
                    doatomicFence(funcsp, stmt->select, barrier);
                }
            }
            if (abs(size) < ISZ_UINT)
                size = -ISZ_UINT;
            ap1 = tempreg(size, 0);
            ap1->retval = TRUE;
            gen_icode(i_assn, ap1, ap, 0);
        }
    }
    else
    {
        DumpIncDec(funcsp);
    }
    /* create the return or a branch to the return
     * return is put at end of function...
     */
    if (flag)
    {
        int retsize = 0;
        if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall)
        {
           retsize = funcsp->paramsize ;
        }
        gen_label(retlab);
        if (!noepilogue)
        {
            if (allocaAP)
            {
                gen_icode(i_loadstack, 0, allocaAP, 0);
            }
/*			if (funcsp->loadds && funcsp->farproc)
                gen_icode(i_unloadcontext,0,0,0);
*/
        
            gen_icode(i_epilogue,0,0,0);
            if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) {
/*				if (funcsp->loadds)
                    gen_icode(i_unloadcontext,0,0,0);
*/
                gen_icode(i_popcontext, 0,0,0);
                gen_icode(i_rett, 0, make_immed(ISZ_NONE,funcsp->linkage == lk_interrupt), 0);
            } else
            {
                gen_icode(i_ret, 0, make_immed(ISZ_NONE,retsize), 0);
            }
        }
    }
    else
    {	
        /* not using gen_igoto because it will make a new block */
        gen_icode(i_goto, NULL, NULL, NULL);
        intermed_tail->dc.v.label = retlab;
    }
}
Esempio n. 6
0
static EXPRESSION *createLambda(BOOLEAN noinline)
{
    EXPRESSION *rv = NULL, **cur = &rv;
    HASHREC *hr;
    EXPRESSION *clsThs, *parentThs;
    SYMBOL *cls = makeID(lambdas->enclosingFunc ? sc_auto : sc_localstatic, lambdas->cls->tp, NULL, AnonymousName());
    SetLinkerNames(cls, lk_cdecl);
    cls->allocate = TRUE;
    if (lambdas->enclosingFunc)
    {
        insert(cls, localNameSpace->syms);
        clsThs = varNode(en_auto, cls); // this ptr
    }
    else
    {
        insert(cls, globalNameSpace->syms); // well if we could put this as an auto in the init func that would be good but there is no way to do that here...
        clsThs = varNode(en_label, cls); // this ptr
        cls->label = nextLabel++;
        insertInitSym(cls);
    }
    {
        INITIALIZER *init = NULL;
        EXPRESSION *exp = clsThs;
        callDestructor(cls, NULL, &exp, NULL, TRUE, FALSE, FALSE);
        initInsert(&init, cls->tp, exp, 0, TRUE);
        if (cls->storage_class != sc_auto)
        {
            insertDynamicDestructor(cls, init);
        }
        else
        {
            cls->dest = init;
        }
    }
    parentThs = varNode(en_auto, (SYMBOL *)basetype(lambdas->func->tp)->syms->table[0]->p); // this ptr
    hr = lambdas->cls->tp->syms->table[0];
    while (hr)
    {
        SYMBOL *sp = (SYMBOL *)hr->p;
        EXPRESSION *en = NULL, *en1 = NULL;
        if (!strcmp(sp->name, "$self"))
        {
            en1 = clsThs;
            en = varNode(en_label, sp);
            deref(&stdpointer, &en);
            en = exprNode(en_assign, en, en1);
        }
        else if (!strcmp(sp->name, "$parent"))
        {
            en1 = parentThs; // get parent from function call
            deref(&stdpointer, &en1);
            en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ;
            deref(&stdpointer, &en);
            en = exprNode(en_assign, en, en1);
        }
        else if (!strcmp(sp->name, "$this"))
        {
            if (!lambdas->next || !lambdas->captureThis)
            {
                en1 = parentThs; // get parent from function call
            }
            else
            {
                SYMBOL *parent = search("$parent", lambdas->cls->tp->syms);
                en1 = varNode(en_auto, cls);
                deref(&stdpointer, &en1);
                en1 = exprNode(en_add, en1, intNode(en_c_i, parent->offset));
            }
            deref(&stdpointer, &en1);
            en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ;
            deref(&stdpointer, &en);
            en = exprNode(en_assign, en, en1);
        }
        else if (sp->lambdaMode)
        {
            LAMBDASP *lsp = (LAMBDASP *)search(sp->name, lambdas->captured);
            if (lsp)
            {
                en1 = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset));
                if (sp->lambdaMode == cmRef)
                {
                    SYMBOL *capture = lsp->parent;
                    deref(&stdpointer, &en1);
                    if (capture->lambdaMode)
                    {
                        en = parentThs;
                        deref(&stdpointer, &en);
                        en = exprNode(en_add, en, intNode(en_c_i, capture->offset));
                    }
                    else // must be an sc_auto
                    {
                        en = varNode(en_auto, capture);
                    }
                    if (isref(capture->tp))
                    {
                        deref(&stdpointer, &en);
                    }
                    en = exprNode(en_assign, en1, en);
                }
                else // cmValue
                {
                    SYMBOL *capture = lsp->parent;
                    TYPE *ctp = capture->tp;
                    if (capture->lambdaMode)
                    {
                        en = parentThs;
                        deref(&stdpointer, &en);
                        en = exprNode(en_add, en, intNode(en_c_i, capture->offset));
                    }
                    else // must be an sc_auto
                    {
                        en = varNode(en_auto, capture);
                    }
                    if (isref(ctp))
                    {
                        ctp = basetype(ctp)->btp;
                        deref(&stdpointer, &en);
                    }
                    if (isstructured(ctp))
                    {
                        FUNCTIONCALL *params = (FUNCTIONCALL *)Alloc(sizeof(FUNCTIONCALL));
                        params->arguments = (INITLIST *)Alloc(sizeof(INITLIST));
                        params->arguments->tp = ctp;
                        params->arguments->exp = en;
                        if (!callConstructor(&ctp, &en1, params, FALSE, NULL, TRUE, FALSE, TRUE, FALSE, FALSE))
                            errorsym(ERR_NO_APPROPRIATE_CONSTRUCTOR, lsp->sym);
                        en = en1;
                    }
                    else
                    {
                        deref(ctp, &en1);
                        deref(ctp, &en);
                        en = exprNode(en_assign, en1, en);
                    }
                }
            }
            else
            {
                diag("createLambda: no capture var");
            }
        }
        if (en)
        {
            *cur = exprNode(en_void, en, NULL);
            cur = &(*cur)->right;            
        }
        hr = hr->next;
    }
    *cur = clsThs; // this expression will be used in copy constructors, or discarded if unneeded
    return rv;
}
Esempio n. 7
0
void cast(TYPE *tp, EXPRESSION **exp)
{
    enum e_node en = en_x_i;
    tp = basetype(tp);
    switch (tp->type == bt_enum ? tp->btp->type : tp->type)
    {
        case bt_lref:
        case bt_rref:
            en = en_x_p;
            break;
        case bt_func:
        case bt_ifunc:
            en = en_x_p;
            break;
        case bt_bit:
            en = en_x_bit;
            break;
        case bt_bool:
            en = en_x_bool;
            break;
        case bt_char:
            if (cparams.prm_charisunsigned)
                en = en_x_uc;
            else
                en = en_x_c;
            break;
        case bt_signed_char:
            en = en_x_c;
            break;
        case bt_unsigned_char:
            en = en_x_uc;
            break;
        case bt_char16_t:
            en = en_x_u16;
            break;
        case bt_char32_t:
            en = en_x_u32;
            break;
        case bt_short:
            en = en_x_s;
            break;
        case bt_unsigned_short:
            en = en_x_us;
            break;
        case bt_wchar_t:
            en = en_x_wc;
            break;
        case bt_int:
            en = en_x_i;
            break;
        case bt_unsigned:
            en = en_x_ui;
            break;
        case bt_long:
            en = en_x_l;
            break;
        case bt_unsigned_long:
            en = en_x_ul;
            break;
        case bt_long_long:
            en = en_x_ll;
            break;
        case bt_unsigned_long_long:
            en = en_x_ull;
            break;
        case bt_float:
            en = en_x_f;
            break;
        case bt_double:
            en = en_x_d;
            break;
        case bt_long_double:
            en = en_x_ld;
            break;
        case bt_float_complex:
            en = en_x_fc;
            break;
        case bt_double_complex:
            en = en_x_dc;
            break;
        case bt_long_double_complex:
            en = en_x_ldc;
            break;
        case bt_float_imaginary:
            en = en_x_fi;
            break;
        case bt_double_imaginary:
            en = en_x_di;
            break;
        case bt_long_double_imaginary:
            en = en_x_ldi;
            break;
        case bt_pointer:
        case bt_aggregate:
            en = en_x_p;
            break;
        case bt_void:
            return;
        case bt_templateparam:
        case bt_templateselector:
        case bt_templatedecltype:
            break;
        default:
            diag("cast error");
            break;
    }
    *exp = exprNode(en, *exp, NULL);
}
Esempio n. 8
0
void deref(TYPE *tp, EXPRESSION **exp)
{
    enum e_node en = en_l_i;
    tp = basetype(tp);
    switch ((tp->type == bt_enum && tp->btp ) ? tp->btp->type : tp->type)
    {
        case bt_lref: /* only used during initialization */
            en = en_l_ref;
            break;
        case bt_rref: /* only used during initialization */
            en = en_l_ref;
            break;
        case bt_bit:
            en = en_l_bit;
            break;
        case bt_bool:
            en = en_l_bool;
            break;
        case bt_char:
            if (cparams.prm_charisunsigned)
                en = en_l_uc;
            else
                en = en_l_c;
            break;
        case bt_signed_char:
            en = en_l_c;
            break;
        case bt_char16_t:
            en = en_l_u16;
            break;
        case bt_char32_t:
            en = en_l_u32;
            break;
        case bt_unsigned_char:
            en = en_l_uc;
            break;
        case bt_short:
            en = en_l_s;
            break;
        case bt_unsigned_short:
            en = en_l_us;
            break;
        case bt_wchar_t:
            en = en_l_wc;
            break;
        case bt_int:
            en = en_l_i;
            break;
        case bt_unsigned:
            en = en_l_ui;
            break;
        case bt_long:
            en = en_l_l;
            break;
        case bt_unsigned_long:
            en = en_l_ul;
            break;
        case bt_long_long:
            en = en_l_ll;
            break;
        case bt_unsigned_long_long:
            en = en_l_ull;
            break;
        case bt_float:
            en = en_l_f;
            break;
        case bt_double:
            en = en_l_d;
            break;
        case bt_long_double:
            en = en_l_ld;
            break;
        case bt_float_complex:
            en = en_l_fc;
            break;
        case bt_double_complex:
            en = en_l_dc;
            break;
        case bt_long_double_complex:
            en = en_l_ldc;
            break;
        case bt_float_imaginary:
            en = en_l_fi;
            break;
        case bt_double_imaginary:
            en = en_l_di;
            break;
        case bt_long_double_imaginary:
            en = en_l_ldi;
            break;
        case bt_pointer:
            if (tp->array || tp->vla)
                return;
            en = en_l_p;
            break;
        case bt_struct:
        case bt_class:
        case bt_union:
        case bt_func:
        case bt_ifunc:
        case bt_any:
        case bt_templateparam:
        case bt_templateselector:
        case bt_templatedecltype:
        case bt_memberptr:
        case bt_aggregate:
            return;
        default:
            diag("deref error");
            break;
    }
    *exp = exprNode(en, *exp, NULL);
}
Esempio n. 9
0
EXPRESSION *convertInitToExpression(TYPE *tp, SYMBOL *sp, SYMBOL *funcsp, INITIALIZER *init, EXPRESSION *thisptr, BOOLEAN isdest)
{
    EXPRESSION *rv = NULL, **pos = &rv;
    EXPRESSION *exp = NULL, **expp;
    EXPRESSION *expsym;
    BOOLEAN noClear = FALSE;
    if (sp)
        sp->destructed = FALSE;
    if (isstructured(tp) || isarray(tp))
    {
        INITIALIZER **i2 = &init;
        while (*i2)
            i2 = &(*i2)->next;
        initInsert(i2, NULL, NULL, tp->size, FALSE);
    }
    if (!sp)
    {
        if (thisptr)
            expsym = thisptr;
        else if (funcsp)
        {
            SYMBOL *sp = (SYMBOL *)basetype(funcsp->tp)->syms->table[0] ? (SYMBOL *)basetype(funcsp->tp)->syms->table[0]->p : NULL;
            if (sp && sp->thisPtr)
                expsym = varNode(en_auto, sp ); // this ptr
            else
                expsym = anonymousVar(sc_auto, tp);
        }
        else
        {
            expsym = intNode(en_c_i, 0);
            diag("convertInitToExpression: no this ptr");
        }
    }
    else switch (sp->storage_class)
    {
        case sc_auto:
        case sc_register:
        case sc_parameter:
            expsym = varNode(en_auto, sp);
            break;
        case sc_localstatic:
            if (sp->linkage3 == lk_threadlocal)
            {
                expsym = exprNode(en_add, thisptr, intNode(en_c_i, sp->offset));
            }
            else
            {
                expsym = varNode(en_label, sp);
            }
            break;
        case sc_static:
        case sc_global:
            if (sp->linkage3 == lk_threadlocal)
            {
                expsym = exprNode(en_add, thisptr, intNode(en_c_i, sp->offset));
            }
            else
            {
                expsym = varNode(en_global, sp);
            }
            break;
        case sc_member:
        case sc_mutable:
            if (thisptr)
                expsym = thisptr;
            else if (funcsp)
                expsym = varNode(en_auto, (SYMBOL *)basetype(funcsp->tp)->syms->table[0]->p); // this ptr
            else
            {
                expsym = intNode(en_c_i, 0);
                diag("convertInitToExpression: no this ptr");
            }
            expsym = exprNode(en_add, expsym, intNode(en_c_i, sp->offset));
            break;
        case sc_external:
/*			expsym = varNode(en_global, sp);
            break;
*/
        default:
            diag("convertInitToExpression: unknown sym type");
            expsym = intNode(en_c_i, 0);
            break;
    }	
    while (init)
    {
        exp = NULL;
        if (init->basetp)
        {
            if (init->noassign)
            {
                exp = init->exp;
                if (exp->type == en_thisref)
                    exp = exp->left;
                if (thisptr && exp->type == en_func)
                {
                    EXPRESSION *exp1 = init->offset ? exprNode(en_add, expsym, intNode(en_c_i, init->offset)) : expsym;
                    if (isarray(tp))
                    {
                        exp->v.func->arguments->exp = exp1;
                    }
                    else
                    {
                        exp->v.func->thisptr = exp1;
                    }
                }
                exp = init->exp;
            }
            else if (!init->exp)
            {
                // usually empty braces, coudl be an error though
                exp = exprNode(en_blockclear, expsym, NULL);
                exp->size = init->offset;
            }
            else if (isstructured(init->basetp) || isarray(init->basetp))
            {
                INITIALIZER *temp = init;
                if (isstructured(temp->basetp))
                {
                    EXPRESSION *exp2 = init->exp;
                    while(exp2->type == en_not_lvalue)
                        exp2 = exp2->left;
                    if (exp2->type == en_func && exp2->v.func->returnSP)
                    {
                        exp2->v.func->returnSP->allocate = FALSE;
                        exp2->v.func->returnEXP = expsym;
                        exp = exp2;
                        noClear = TRUE;
                    }
                    else if (exp2->type == en_thisref && exp2->left->v.func->returnSP)
                    {
                        exp2->left->v.func->returnSP->allocate = FALSE;
                        exp2->left->v.func->returnEXP = expsym;
                        exp = exp2;
                        noClear = TRUE;
                    }
                    else if (cparams.prm_cplusplus)
                    {
                        TYPE *ctype = init->basetp;
                        FUNCTIONCALL *funcparams = Alloc(sizeof(FUNCTIONCALL));
                        funcparams->arguments = Alloc(sizeof(INITLIST));
                        funcparams->arguments->tp = ctype;
                        funcparams->arguments->exp = exp2;
                        callConstructor(&ctype, &expsym, funcparams, FALSE, NULL, TRUE, FALSE, FALSE, FALSE, FALSE); 
                        exp = expsym;
                    }
                    else
                    {
                        exp = exprNode(en_blockassign, expsym, exp2);
                        exp->size = init->basetp->size;
                    }
                }
                else
                {
                    TYPE *btp = init->basetp;
                    while(isarray(btp))
                        btp = basetype(btp)->btp;
                    btp = basetype(btp);
                    while (temp)
                    {
                        if (temp->exp)
                            if (!isarithmeticconst(temp->exp) && !isconstaddress(temp->exp))
                                break;
                        temp = temp->next;
                    }
                    if (temp)
                    {
                        /* some members are non-constant expressions */
                        if (!cparams.prm_c99 && !cparams.prm_cplusplus)
                            error(ERR_C99_NON_CONSTANT_INITIALIZATION);
                        if (!sp)
                        {
                            expsym = anonymousVar(sc_auto, init->basetp);
                            sp = expsym->v.sp;
                        }
                        if (!isstructured(btp) || btp->sp->trivialCons)
                        {
                            exp = exprNode(en_blockclear, expsym, NULL);
                            exp->size = init->basetp->size;
                            exp = exprNode(en_void, exp, NULL);
                            expp = &exp->right;
                        }
                        else
                        {
                            expp = &exp;
                        }
                        {
                            EXPRESSION *right = init->exp;
                            if (!isstructured(btp))
                            {
                                EXPRESSION *asn = exprNode(en_add, expsym, intNode(en_c_i, init->offset));
                                deref(init->basetp, &asn);
                                cast(init->basetp, &right);
                                right = exprNode(en_assign, asn, right);
                            }
                            if (*expp)
                                *expp = exprNode(en_void, *expp, right);
                            else
                                *expp = right;
                            expp = &(*expp)->right;
                        }
                    }
                    else
                    {
                        /* constant expression */
                        SYMBOL *spc ;
                        IncGlobalFlag();
                        exp = anonymousVar(sc_localstatic, init->basetp);
                        spc = exp->v.sp;
                        spc->init = init ;
                        insertInitSym(spc);
                        insert(spc, localNameSpace->syms);
                        DecGlobalFlag();
                        spc->label =nextLabel++;
                        if (expsym)
                        {
                            if (cparams.prm_cplusplus && isstructured(init->basetp) && !init->basetp->sp->trivialCons)
                            {
                                TYPE *ctype = init->basetp;
                                FUNCTIONCALL *funcparams = Alloc(sizeof(FUNCTIONCALL));
                                funcparams->arguments = Alloc(sizeof(INITLIST));
                                funcparams->arguments->tp = ctype;
                                funcparams->arguments->exp = exp;
                                callConstructor(&ctype, &expsym, funcparams, FALSE, NULL, TRUE, FALSE, FALSE, FALSE, FALSE); 
                                exp = expsym;
                            }
                            else
                            {
                                exp = exprNode(en_blockassign, expsym, exp);
                                exp->size = init->basetp->size;
                            }
                        }
                    }
                }
            }
            else if (basetype(init->basetp)->type == bt_memberptr)
            {
                EXPRESSION *exp2 = init->exp;;
                while(exp2->type == en_not_lvalue)
                    exp2 = exp2->left;
                if (exp2->type == en_func && exp2->v.func->returnSP)
                {
                    exp2->v.func->returnSP->allocate = FALSE;
                    exp2->v.func->returnEXP = expsym;
                    exp = exp2;
                }
                else
                {
                    if (exp2->type == en_memberptr)
                    {
                        int lab = dumpMemberPtr(exp2->v.sp, init->basetp, TRUE);
                        exp2 = intNode(en_labcon, lab);
                    }
                    exp = exprNode(en_blockassign, expsym, exp2);
                    exp->size = init->basetp->size;
                }
            }
            else
            {
                EXPRESSION *exps = expsym;
                if (init->offset)
                    exps = exprNode(en_add, exps, intNode(en_c_i, init->offset));
                deref(init->basetp, &exps);
                exp = init->exp;
                if (exp->type == en_void)
                {
                    cast(init->basetp, &exp->right);
                    if (expsym)
                        exp->right = exprNode(en_assign, exps, exp->right);
                }
                else
                {
                    cast(init->basetp, &exp);
                    if (exps)
                        exp = exprNode(en_assign, exps, exp);
                }
            }
            if (sp && sp->init && isatomic(init->basetp) && needsAtomicLockFromType(init->basetp))
            {
                EXPRESSION *p1 = exprNode(en_add, expsym->left, intNode(en_c_i, init->basetp->size - ATOMIC_FLAG_SPACE));
                deref(&stdint, &p1);
                p1 = exprNode(en_assign, p1, intNode(en_c_i, 0));
                exp = exprNode(en_void, exp, p1);
            }
        }
        if (exp)
        {
            if (*pos)
            {
                *pos = exprNode(en_void, *pos, exp);
                pos = &(*pos)->right;
            }
            else
            {
                *pos = exp;
            }
        }
        init = init->next;
    }
    if (sp && sp->storage_class == sc_localstatic)
    {
        if (isdest)
        {
            rv = exprNode(en_voidnz, exprNode(en_void, sp->localInitGuard, rv), intNode(en_c_i, 0));        
        }
        else
        {
            EXPRESSION *guard = anonymousVar(sc_static, &stdint);
            insertInitSym(guard->v.sp);
            deref(&stdpointer, &guard);
            optimize_for_constants(&rv);
            rv = exprNode(en_voidnz, exprNode(en_void, 
                                              exprNode(en_not, guard, NULL), 
                                              exprNode(en_void, rv, exprNode(en_autoinc, guard, intNode(en_c_i, 1)))), intNode(en_c_i, 0));        
            sp->localInitGuard = guard;
        }
    }
    // plop in a clear block if necessary
    if (sp && !noClear && !isdest && (isarray(tp) || isstructured(tp) && (!cparams.prm_cplusplus || basetype(tp)->sp->trivialCons)))
    {
        EXPRESSION *fexp = expsym;
        EXPRESSION *exp;
        if (fexp->type == en_thisref)
            fexp = fexp->left->v.func->thisptr;
        exp = exprNode(en_blockclear, fexp, NULL); 
        exp->size = sp->tp->size;
        rv = exprNode(en_void, exp, rv);
    }
    if (isstructured(tp) && !cparams.prm_cplusplus)
    {
        if (*pos)
        {
            *pos = exprNode(en_void, *pos, expsym);
            pos = &(*pos)->right;
        }
        else
        {
            *pos = expsym;
        }
    }
    return rv;
}
Esempio n. 10
0
void genfunc(SYMBOL *funcsp)
/*
 *      generate a function body and dump the icode
 */
{
    IMODE *allocaAP = NULL;
    SYMBOL *oldCurrentFunc;
    EXPRESSION *funcexp = varNode(en_global, funcsp);
    SYMBOL *tmpl = funcsp;
    if (total_errors)
        return;
    while (tmpl)
        if (tmpl->templateLevel)
            break;
        else
            tmpl = tmpl->parentClass;
//	//printf("%s\n", funcsp->name);
    temporarySymbols = NULL;
    contlab = breaklab =  - 1;
    structret_imode = 0 ;
    tempCount = 0;
    blockCount = 0;
    blockMax = 0;
    exitBlock = 0;
    consIndex = 0;
    oldCurrentFunc = theCurrentFunc;
    theCurrentFunc = funcsp;
    iexpr_func_init();

    if (funcsp->xc && funcsp->xc->xctab)
    {
        EXPRESSION *exp;
        xcexp = varNode(en_auto, funcsp->xc->xctab);
        xcexp = exprNode(en_add, xcexp, intNode(en_c_i, (LLONG_TYPE)&(((struct _xctab *)0)->funcIndex)));
        deref(&stdpointer, &xcexp);
        exp = intNode(en_c_i, 0);
        xcexp = exprNode(en_assign, xcexp, exp);
    }
    else
    {
        xcexp = NULL;
    }
    /*      firstlabel = nextLabel;*/
    cseg();
    gen_line(funcsp->linedata);
    gen_func(funcexp, 1);
    /* in C99 inlines can clash if declared 'extern' in multiple modules */
    /* in C++ we introduce virtual functions that get coalesced at link time */
    if (cparams.prm_cplusplus && (funcsp->linkage == lk_inline || tmpl))
        gen_virtual(funcsp, FALSE);
    else
    {
        if (funcsp->storage_class == sc_global || (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual) && funcsp->inlineFunc.stmt)
                globaldef(funcsp);
        else
            localdef(funcsp);
        gen_strlab(funcsp); /* name of function */
    }
    addblock( - 1);
       if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) {
        gen_icode(i_pushcontext, 0,0,0);
/*		if (funcsp->loadds) */
/*	        gen_icode(i_loadcontext, 0,0,0); */
    }
    gen_icode(i_prologue,0,0,0);
    gen_label(startlab);
    if (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcInitializeFunc)
    {
        gen_expr(funcsp, funcsp->xc->xcInitializeFunc, F_NOVALUE, ISZ_UINT);
        gen_label(funcsp->xc->xcInitLab);
    }
/*    if (funcsp->loadds && funcsp->farproc) */
/*	        gen_icode(i_loadcontext, 0,0,0); */
    AllocateLocalContext(NULL, funcsp);
    if (funcsp->allocaUsed)
    {
            EXPRESSION *allocaExp = anonymousVar(sc_auto, &stdpointer);
            allocaAP = gen_expr(funcsp, allocaExp, 0, ISZ_ADDR);
            gen_icode(i_savestack, 0, allocaAP, 0);
    }
    /* Generate the icode */
    /* LCSE is done while code is generated */
    genstmt(funcsp->inlineFunc.stmt->lower, funcsp);
    if (funcsp->inlineFunc.stmt->blockTail)
    {
        gen_icode(i_functailstart, 0, 0, 0);
        genstmt(funcsp->inlineFunc.stmt->blockTail, funcsp);
        gen_icode(i_functailend, 0, 0, 0);
    }
    genreturn(0, funcsp, 1, 0, allocaAP);
    gen_func(funcexp, 0);
    tFree();
    InsertParameterThunks(funcsp, blockArray[1]);
    optimize(funcsp);
    FreeLocalContext(NULL, funcsp);
        
    AllocateStackSpace(funcsp);
    FillInPrologue(intermed_head, funcsp);
    /* Code gen from icode */
    rewrite_icode(); /* Translate to machine code & dump */
    if (chosenAssembler->gen->post_function_gen)
        chosenAssembler->gen->post_function_gen(funcsp, intermed_head);
    if (cparams.prm_cplusplus && (funcsp->linkage == lk_inline || tmpl))
        gen_endvirtual(funcsp);
    XTDumpTab(funcsp);
    intermed_head = NULL;
    dag_rundown();
    oFree();
    theCurrentFunc = oldCurrentFunc;
    if (blockCount > maxBlocks)
        maxBlocks = blockCount;
    if (tempCount > maxTemps)
        maxTemps = tempCount;
}