Esempio n. 1
0
void genbinaryswitch(SNODE *stmt, struct cases *cs)
{
    AMODE *ap1;
	int size = natural_size(stmt->exp);
    InitRegs();
    ap1 = gen_expr_external(stmt->exp, FALSE, F_DREG, BESZ_DWORD);
    gather_cases(stmt->s1,cs,FALSE);
    qsort(cs->ptrs,cs->count, sizeof(cs->ptrs[0]), size < 0 ? sortcmpsigned : sortcmpunsigned);
    bingen(0, (cs->count) / 2, cs->count, ap1, cs, size);
}
Esempio n. 2
0
void gencompactswitch(SNODE *stmt, int deflab)
{       int             tablab,curlab,i, size = natural_size(stmt->exp);
        AMODE    *ap,*ap2;
  long switchbottom=gswitchbottom, switchcount=gswitchcount;
  long switchtop=gswitchtop;
  int *switchlabels=0;
				tablab = nextlabel++;
        curlab = nextlabel++;
        initstack();
        ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
				initstack();
				if (switchbottom)
					gen_code(op_sub,4,ap,make_immed(switchbottom));
				if (size < 0)
					gen_code(op_jl,0,make_label(deflab),0);
				else
					gen_code(op_jb,0,make_label(deflab),0);
				gen_code(op_cmp,4,ap,make_immed(switchtop-switchbottom));
				if (size < 0)
					gen_code(op_jge,0,make_label(deflab),0);
				else
					gen_code(op_jnc,0,make_label(deflab),0);
				gen_code(op_shl,4,ap,make_immed(2));
				ap2 = xalloc(sizeof(AMODE));
				ap->mode = am_indisp;
				ap2->preg = ap->preg;
				ap->offset = makenode(en_labcon,(char *)tablab,0);
				gen_code(op_jmp,4,ap,0);

				initstack();
				align(4);
				gen_label(tablab);
		switchlabels = xalloc((switchtop-switchbottom) * sizeof(int));
	for (i=switchbottom; i < switchtop; i++) {
		switchlabels[i-switchbottom] = deflab;
	}
	stmt = stmt->s1;
	while (stmt) {
                if( stmt->s2 )          /* default case ? */
                        {
                        stmt->label = (SNODE *)deflab;
												diddef = TRUE;
                        }
                else
                        {
												switchlabels[(int)stmt->label-switchbottom] = curlab;
												stmt->label = (SNODE *)curlab;
                        }
                if(stmt->next != 0 )
                        curlab = nextlabel++;
                stmt = stmt->next;
                }
	for (i=0; i < switchtop-switchbottom; i++)
		gen_code(op_dd,4,make_label(switchlabels[i]),0);
}
Esempio n. 3
0
void gen_for(SNODE *stmt)
/*
 *      generate code to evaluate a for loop
 */
{       int     old_break, old_cont, exit_label, loop_label;
        old_break = breaklab;
        old_cont = contlab;
        loop_label = nextlabel++;
        exit_label = nextlabel++;
        contlab = nextlabel++;
        initstack();
        if( stmt->label != 0 )
                gen_expr(stmt->label,F_ALL | F_NOVALUE
                        ,natural_size(stmt->label));
				
        gen_code(op_jmp,0,make_label(contlab),0);
        gen_label(loop_label);
        if( stmt->s1 != 0 ) {
								breaklab = exit_label;
                genstmt(stmt->s1);
				}
        initstack();
        if( stmt->s2 != 0 )
                gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
				gen_label(contlab);
				if (stmt->lst)
		 			gen_line(stmt->lst);
        initstack();
        if( stmt->exp != 0 )
                truejp(stmt->exp,loop_label);
				else
						gen_code(op_jmp,0,make_label(loop_label),0);
				gen_label(exit_label);
 				breaklab = old_break;
				contlab = old_cont;
}
Esempio n. 4
0
void genbinaryswitch(SNODE *stmt, int deflab)
{
	int curlab, i=0,j,size = natural_size(stmt->exp);
	AMODE *ap1;
  long switchbottom=gswitchbottom, switchcount=gswitchcount;
  long switchtop=gswitchtop;
  int *switchlabels=0;
  long *switchids=0;
  int *switchbinlabels=0;
	curlab = nextlabel++;
  initstack();
  ap1 = gen_expr(stmt->exp,F_DREG,4);
	global_flag++;
		switchlabels = xalloc((switchcount) * sizeof(int));
		switchbinlabels = xalloc((switchcount) * sizeof(int));
		switchids = xalloc((switchcount) * sizeof(long));
	global_flag--;
	stmt = stmt->s1;
	while (stmt) {
                if( stmt->s2 )          /* default case ? */
                        {
                        stmt->label = (SNODE *) deflab;
												diddef = TRUE;
                        }
                else
                        {
												switchlabels[i] = curlab;
												switchbinlabels[i] = -1;
												switchids[i++] = (int)stmt->label;
												stmt->label = (SNODE *)curlab;
                        }
                if( stmt->next != 0 )
                        curlab = nextlabel++;
                stmt = stmt->next;
                }
	for (i=0; i < switchcount; i++)
		for (j=i+1; j < switchcount; j++)
			if (switchids[j] < switchids[i]) {
				int temp = switchids[i];
				switchids[i] = switchids[j];
				switchids[j] = temp;
				temp = switchlabels[i];
				switchlabels[i] = switchlabels[j];
				switchlabels[j] = temp;
			}
	bingen(0,(switchcount)/2,switchcount,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
	freeop(ap1);
}
Esempio n. 5
0
int analyzeswitch(SNODE *stmt, struct cases *cs)
{
    int size = natural_size(stmt->exp);
    count_cases(stmt->s1,cs) ;
    cs->top++;
    if (cs->count == 0)
        return (0);
    if (cs->count < 5)
        return 3;
    if (cs->count *10 / (cs->top - cs->bottom) >= 8)
        return (1);
    // do a simple switch instead of a binary if it is a long long
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
        return 3;
    return (2);
}
Esempio n. 6
0
void gencompactswitch(SNODE *stmt, struct cases *cs)
{
    int tablab, size;
    AMODE *ap,  *ap2;
    LLONG_TYPE i;
    tablab = nextlabel++;
    InitRegs();
    size = natural_size(stmt->exp);
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
    {
	    ap = gen_expr_external(stmt->exp, FALSE, F_AXDX, BESZ_QWORD);
        if (cs->bottom)
        {
            gen_codes(op_sub, BESZ_DWORD, makedreg(EAX), make_immed(cs->bottom));
            #if sizeof(LLONG_TYPE) == 4
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom < 0
                    ?  - 1: 0));
            #else 
                gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom >>
                    32));
            #endif 
        }
Esempio n. 7
0
void genstmt(STATEMENT *stmt, SYMBOL *funcsp)
/*
 *      genstmt will generate a statement and follow the next pointer
 *      until the block is generated.
 */
{
    while (stmt != 0)
    {
        switch (stmt->type)
        {
            case st_varstart:
                gen_varstart(stmt->select);
                break;
            case st_dbgblock:
                gen_dbgblock(stmt->label);
                break;
            case st_tryblock:
/*				gen_tryblock(stmt->label); */
                break;
            case st_block:
                genstmt(stmt->lower, funcsp);
                genstmt(stmt->blockTail, funcsp);
                break;
            case st_label:
                gen_label((int)stmt->label);
                break;
            case st_goto:
                gen_igoto(i_goto, (int)stmt->label);
                break;
            case st_asmgoto:
                gen_igoto(i_asmgoto, (int)stmt->label);
                break;
            case st_asmcond:
                gen_igoto(i_asmcond, (int)stmt->label);
                break;
            case st_throw:
/*                gen_throw((TYPE *)stmt->lst, stmt->select);*/
                break;
/*			case st_functailexpr: 
                gen_icode(i_functailstart, 0, 0, 0); 
                gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select)); *
                gen_icode(i_functailend, 0, 0, 0);
               break;
*/
            case st_expr:
            case st_declare:
                gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select));
                break;
            case st_return:
                genreturn(stmt, funcsp, 0, 0, NULL);
                break;
            case st_line:
                gen_line(stmt->lineData);
                break;
            case st_select:
                genselect(stmt, funcsp, TRUE);
                break;
            case st_notselect:
                genselect(stmt, funcsp, FALSE);
                break;
            case st_switch:
                genxswitch(stmt, funcsp);
                break;
            case st__genword:
                gen_genword(stmt, funcsp);
                break;
            case st_passthrough:
                gen_asm(stmt);
                break;
            case st_datapassthrough:
                gen_asmdata(stmt);
                break;
            default:
                diag("unknown statement.");
                break;
        }
        stmt = stmt->next;
    }
}
Esempio n. 8
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. 9
0
void genstmt(SNODE *stmt)
/*
 *      genstmt will generate a statement and follow the next pointer
 *      until the block is generated.
 */
{
		   while( stmt != 0 )
                {
                switch( stmt->stype )
                        {
												case st_block:
																genstmt(stmt->exp);
																break;
                        case st_label:
                                gen_label((int)stmt->label);
                                break;
                        case st_goto:
                                gen_code(op_jmp,0,make_label((int)stmt->label),0);
                                break;
                        case st_expr:
                                initstack();
                                gen_expr(stmt->exp,F_ALL | F_NOVALUE,
                                        natural_size(stmt->exp));
                                break;
                        case st_return:
                                genreturn(stmt,0);
                                break;
                        case st_if:
                                genif(stmt);
                                break;
                        case st_while:
                                genwhile(stmt);
                                break;
                        case st_do:
                                gendo(stmt);
                                break;
                        case st_for:
                                gen_for(stmt);
                                break;
                        case st_continue:
                                gen_code(op_jmp,0,make_label(contlab),0);
                                break;
                        case st_break:
                                gen_code(op_jmp,0,make_label(breaklab),0);
                                break;
                        case st_switch:
                                genxswitch(stmt);
                                break;
												case st_line:
		 														gen_line(stmt);
																break;
												case st_asm:
																if (stmt->exp)
																	add_peep(stmt->exp);
																break;
												case st__genword:
																gen_code(op_genword,0,make_immed((int)stmt->exp),0);
																break;
                        default:

                                diag("unknown statement.");
                                break;
                        }
                stmt = stmt->next;
                }
}
Esempio n. 10
0
IMODE *genstmt(STATEMENT *stmt, SYMBOL *funcsp)
/*
 *      genstmt will generate a statement and follow the next pointer
 *      until the block is generated.
 */
{
    IMODE *rv = NULL;
    while (stmt != 0)
    {
        STATEMENT *last = stmt;
        switch (stmt->type)
        {
            case st_varstart:
                gen_varstart(stmt->select);
                break;
            case st_dbgblock:
                gen_dbgblock(stmt->label);
                break;
                break;
            case st_block:
                rv = genstmt(stmt->lower, funcsp);
                genstmt(stmt->blockTail, funcsp);
                break;
            case st_label:
                gen_label((int)stmt->label);
                break;
            case st_goto:
                gen_igoto(i_goto, (int)stmt->label);
                break;
            case st_asmgoto:
                gen_igoto(i_asmgoto, (int)stmt->label);
                break;
            case st_asmcond:
                gen_igoto(i_asmcond, (int)stmt->label);
                break;
            case st_try:
                gen_try(funcsp, stmt, stmt->label, stmt->endlabel, stmt->breaklabel, stmt->lower);
                break;
            case st_catch:
            {
                STATEMENT *last;
                while (stmt && stmt->type == st_catch)
                {
                    gen_catch(funcsp, stmt, stmt->altlabel, stmt->breaklabel, stmt->lower);
                    last = stmt;
                    stmt = stmt->next;
                }
                stmt = last;
                gen_label(stmt->breaklabel);
            }
                break;
            case st_expr:
            case st_declare:
                if (stmt->select)
                    rv = gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select));
                break;
            case st_return:
                genreturn(stmt, funcsp, 0, 0, NULL);
                break;
            case st_line:
                gen_line(stmt->lineData);
                break;
            case st_select:
                genselect(stmt, funcsp, TRUE);
                break;
            case st_notselect:
                genselect(stmt, funcsp, FALSE);
                break;
            case st_switch:
                genxswitch(stmt, funcsp);
                break;
            case st__genword:
                gen_genword(stmt, funcsp);
                break;
            case st_passthrough:
                gen_asm(stmt);
                break;
            case st_datapassthrough:
                gen_asmdata(stmt);
                break;
            default:
                diag("unknown statement.");
                break;
        }
        if (last->type != st_return && last->destexp)
        {
            gen_expr(funcsp, last->destexp, F_NOVALUE, ISZ_ADDR);
        }
        stmt = stmt->next;
    }
    return rv;
}
Esempio n. 11
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;
    }
}