Example #1
0
static EXPRESSION *newReturn(TYPE *tp)
{
    EXPRESSION *exp ;
    if (!isstructured(tp) && !isvoid(tp))
    {
        exp = varNode(en_auto, anonymousVar(sc_auto, tp));
        deref(tp, &exp);
    }
    else
        exp = intNode(en_c_i, 0);
    return exp;
}
Example #2
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;
}
Example #3
0
void SetupVariables(SYMBOL *sp)
/* Copy all the func args into the xsyms table.
 * This copies the function parameters twice...
 */
{
    HASHTABLE *syms = sp->inlineFunc.syms;
    while (syms)
    {
        HASHREC *hr = syms->table[0];
        while (hr)
        {
            SYMBOL *sx = (SYMBOL *)hr->p;
            if (sx->storage_class == sc_auto)
            {
                SYMBOL *sxnew = anonymousVar(sc_auto, sx->tp);
                EXPRESSION *ev = varNode(en_auto, sxnew);
                deref(sx->tp, &ev);
                sx->inlineFunc.stmt = (STATEMENT *)ev;
            }
            hr = hr->next;
        }
        syms = syms->next;
    }
}
Example #4
0
void genfunc(SYMBOL *funcsp)
/*
 *      generate a function body and dump the icode
 */
{
    IMODE *allocaAP = NULL;
    SYMBOL *oldCurrentFunc;
    EXPRESSION *funcexp = varNode(en_global, funcsp);
    if (total_errors)
        return;
//	//printf("%s\n", funcsp->name);
    contlab = breaklab =  - 1;
    structret_imode = 0 ;
    tempCount = 0;
    blockCount = 0;
    blockMax = 0;
    exitBlock = 0;
    oldCurrentFunc = theCurrentFunc;
    theCurrentFunc = funcsp;
    iexpr_func_init();
    /*      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)
        gen_virtual(funcsp, FALSE);
    else
    {
        if (funcsp->storage_class == sc_global)
                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 (funcsp->loadds && funcsp->farproc) */
/*	        gen_icode(i_loadcontext, 0,0,0); */
    AllocateLocalContext(NULL, funcsp);
    if (funcsp->allocaUsed)
    {
            EXPRESSION *allocaExp = varNode(en_auto, 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)
        gen_endvirtual(funcsp);
    intermed_head = NULL;
    dag_rundown();
    oFree();
    theCurrentFunc = oldCurrentFunc;
    if (blockCount > maxBlocks)
        maxBlocks = blockCount;
    if (tempCount > maxTemps)
        maxTemps = tempCount;
}
Example #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;
    }
}
Example #6
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;
}
Example #7
0
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP)
/*
 *      generate a return statement.
 */
{
    IMODE *ap = NULL,  *ap1, *ap3;
    EXPRESSION ep;
    int size;
    /* 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))
        {
            EXPRESSION *en = anonymousVar(sc_parameter, &stdpointer);
            SYMBOL *sp = en->v.sp;
            gen_expr(funcsp, stmt->select, 0, ISZ_ADDR);
            DumpIncDec(funcsp);
            sp->offset = chosenAssembler->arch->retblocksize;
            sp->allocate = FALSE;
            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;
            deref(&stdpointer, &en);
            ap = gen_expr(funcsp, en, 0, ISZ_ADDR);
            size = ISZ_ADDR;
        }
        else
        {
            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;
        }
    }
    else
    {
        DumpIncDec(funcsp);
    }
    if (ap)
    {
        ap1 = tempreg(size, 0);
        ap1->retval = TRUE;
        gen_icode(i_assn, ap1, ap, 0);
    }
    if (stmt && stmt->destexp)
    {
        gen_expr(funcsp, stmt->destexp, F_NOVALUE, ISZ_ADDR);
    }
    /* 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);
*/
        
            if (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcRundownFunc)
                gen_expr(funcsp, funcsp->xc->xcRundownFunc, F_NOVALUE, ISZ_UINT);
            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_UINT,funcsp->linkage == lk_interrupt), 0);
            } else
            {
                gen_icode(i_ret, 0, make_immed(ISZ_UINT,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;
    }
}