⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gstmt386.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 3 页
字号:
        stmt = stmt->next;
    }
}
//-------------------------------------------------------------------------


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);
}

//-------------------------------------------------------------------------

void bingen(int lower, int avg, int higher, AMODE *ap1, struct cases *cs)
{
    AMODE *ap2 = make_immed(cs->ptrs[avg].id);
    AMODE *ap3 = make_label(cs->ptrs[avg].label);
    if (cs->ptrs[avg].binlabel !=  - 1)
        gen_label(cs->ptrs[avg].binlabel);
    gen_coden(op_cmp, ap1->length, ap1, ap2);
    gen_code(op_je, ap3, 0);
    if (avg == lower)
    {
        if (cs->deflab < 0)
            cs->deflab = nextlabel++;
        ap3 = make_label(cs->deflab);
        gen_code(op_jmp, ap3, 0);
    }
    else
    {
        int avg1 = (lower + avg) / 2;
        int avg2 = (higher + avg + 1) / 2;
        if (avg + 1 < higher)
            ap3 = make_label(cs->ptrs[avg2].binlabel = nextlabel++);
        else
            ap3 = make_label(cs->deflab);
        if (ap1->length < 0)
            gen_code(op_jg, ap3, 0);
        else
            gen_code(op_ja, ap3, 0);
        bingen(lower, avg1, avg, ap1, cs);
        if (avg + 1 < higher)
            bingen(avg + 1, avg2, higher, ap1, cs);
    }
}

//-------------------------------------------------------------------------
int sortcmp(const void *one, const void *two)
{
    if (((struct caseptrs *)one)->id < ((struct caseptrs *)two)->id)
        return -1;
    if (((struct caseptrs *)one)->id > ((struct caseptrs *)two)->id)
        return 1;
    return 0;
}
void genbinaryswitch(SNODE *stmt, struct cases *cs)
{
    AMODE *ap1;
    initstack();
    ap1 = gen_expr(stmt->exp, FALSE, FALSE, BESZ_DWORD);
    do_extend(ap1, ap1->length, F_DREG);
    gather_cases(stmt->s1,cs,FALSE);
    qsort(cs->ptrs,cs->count, sizeof(cs->ptrs[0]), sortcmp);
    bingen(0, (cs->count) / 2, cs->count, ap1, cs);
    freeop(ap1);
}

//-------------------------------------------------------------------------

void gencompactswitch(SNODE *stmt, struct cases *cs)
{
    int tablab, size;
    AMODE *ap,  *ap2;
    LLONG_TYPE i;
    tablab = nextlabel++;
    initstack();
    ap = gen_expr(stmt->exp, FALSE, FALSE, BESZ_DWORD);
    size = ap->length;
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
        do_extend(ap, BESZ_QWORD, F_AXDX);
    else
        do_extend(ap, BESZ_DWORD, F_DREG | F_VOL);
    initstack();
    if (size == BESZ_QWORD || size ==  - 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 
            if (size < 0)
                gen_codes(op_jl, 0, make_label(cs->deflab), 0);
            else
            {
                peep_tail->noopt = TRUE;
                gen_codes(op_jb, 0, make_label(cs->deflab), 0);
            }
        }
        else
        if (size < 0)
        {
            gen_codes(op_test, BESZ_DWORD, makedreg(EDX), makedreg(EDX));
            gen_codes(op_jl, 0, make_label(cs->deflab), 0);
        }
        gen_codes(op_cmp, BESZ_DWORD, makedreg(EAX), make_immed(cs->top - cs->bottom)
            );
    }
    else
    {
        if (cs->bottom)
        {
            gen_codes(op_sub, BESZ_DWORD, ap, make_immed(cs->bottom));
            if (size < 0)
                gen_codes(op_jl, 0, make_label(cs->deflab), 0);
            else
            {
                peep_tail->noopt = TRUE;
                gen_codes(op_jb, 0, make_label(cs->deflab), 0);
            }
        }
        else
        if (size < 0)
        {
            gen_codes(op_test, BESZ_DWORD, ap, ap);
            gen_codes(op_jl, 0, make_label(cs->deflab), 0);
        }
        gen_codes(op_cmp, BESZ_DWORD, ap, make_immed(cs->top - cs->bottom));
    }
    if (size < 0)
        gen_codes(op_jge, 0, make_label(cs->deflab), 0);
    else
        gen_codes(op_jnc, 0, make_label(cs->deflab), 0);
    ap->mode = am_indispscale;
    ap->sreg = ap->preg;
    ap->preg =  - 1;
    ap->scale = 2;
    ap->offset = makeintnode(en_labcon, tablab);
    gen_codes(op_jmp, BESZ_DWORD, ap, 0);

    initstack();
    align(stdaddrsize);
    gen_label(tablab);

    gather_cases(stmt->s1,cs,TRUE);
    for (i = 0; i < cs->top - cs->bottom; i++)
        gen_codes(op_dd, 4, make_label(cs->ptrs[i].label), 0);
}

//-------------------------------------------------------------------------

void gensimpleswitch(SNODE *stmt, struct cases *cs)
{
    int i = 0, j;
    AMODE *ap1,  *ap2,  *ap3,  *ap4;
    int size = natural_size(stmt->exp);
    initstack();
    ap1 = gen_expr(stmt->exp, FALSE, FALSE, BESZ_DWORD);
    if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
        do_extend(ap1, ap1->length, F_AXDX);
    else
        do_extend(ap1, ap1->length, F_DREG);
    gather_cases(stmt->s1,cs,FALSE);
    qsort(cs->ptrs,cs->count, sizeof(cs->ptrs[0]), sortcmp);

    for (i = 0; i < cs->count; i++)
    {
        if (size == BESZ_QWORD || size ==  - BESZ_QWORD)
        {
            int lab = nextlabel++;
            ap2 = make_immed(cs->ptrs[i].id);
            #if sizeof(LLONG_TYPE) == 4
                ap4 = make_immed(cs->ptrs[i].id < 0 ? 0xffffffff : 0);
            #else 
                ap4 = make_immed(cs->ptrs[i].id >> 32);
            #endif 
            ap3 = make_label(cs->ptrs[i].label);
            gen_coden(op_cmp, BESZ_DWORD, makedreg(EAX), ap2);
            gen_code(op_jne, make_label(lab), 0);
            gen_coden(op_cmp, BESZ_DWORD, makedreg(EDX), ap4);
            gen_code(op_je, ap3, 0);
            gen_label(lab);
        }
        else
        {
            ap2 = make_immed(cs->ptrs[i].id);
            ap3 = make_label(cs->ptrs[i].label);
            gen_coden(op_cmp, ap1->length, ap1, ap2);
            gen_code(op_je, ap3, 0);
        }
    }
    gen_codes(op_jmp, 0, make_label(cs->deflab), 0);
    freeop(ap1);
}

//-------------------------------------------------------------------------


//-------------------------------------------------------------------------


void genxswitch(SNODE *stmt)
/*
 *      analyze and generate best switch statement.
 */
{
    int oldbreak;
    struct cases cs;
    int a = 1;
    OCODE *result;
    oldbreak = breaklab;
    breaklab = nextlabel++;
    memset(&cs,0,sizeof(cs));
#if sizeof(LLONG_TYPE) == 4
    cs.top = INT_MIN;
    cs.bottom = INT_MAX;
#else
    cs.top = (a << 63); // LLONG_MIN
    cs.bottom = cs.top - 1; // LLONG_MAX
#endif
    cs.deflab = nextlabel++;
    switch (analyzeswitch(stmt,&cs))
    {
        case 3:
            gensimpleswitch(stmt, &cs);
            break;
        case 2:
            genbinaryswitch(stmt, &cs);
            break;
        case 1:
            gencompactswitch(stmt, &cs);
            break;
        case 0:
            break;
    }
    result = gen_codes(op_blockstart, 0, 0, 0);
    result->blocknum = (int)stmt->label;
    genstmt(stmt->s1);
    result = gen_codes(op_blockend, 0, 0, 0);
    result->blocknum = (int)stmt->label;
    if (!cs.diddef)
        gen_label(cs.deflab);
    gen_label(breaklab);
    breaklab = oldbreak;
}

//-------------------------------------------------------------------------

void AddProfilerData(void)
{
    char pname[256];
    if (prm_profiler)
    {
        sprintf(pname, "%s", currentfunc->name);
        plabel = stringlit(pname, FALSE, strlen(pname + 1));
        gen_codes(op_push, BESZ_DWORD , make_label(plabel), 0);
        call_library("__profile_in");
        gen_codes(op_pop, BESZ_DWORD , makedreg(ECX), 0);
    }
}

//-------------------------------------------------------------------------

void SubProfilerData(void)
{
    if (prm_profiler)
    {
        gen_codes(op_push, BESZ_DWORD , make_label(plabel), 0);
        call_library("__profile_out");
        gen_codes(op_pop, BESZ_DWORD , makedreg(ECX), 0);
    }
}

//-------------------------------------------------------------------------

OCODE *ThunkAddPeep(OCODE *after, int op, AMODE *ap1, AMODE *ap2)
{
    OCODE *new;
    new = xalloc(sizeof(OCODE));
    new->opcode = op;
    if (op == op_label)
    {
        new->oper1 = ap1;
        new->oper2 = 0;
    }
    else
    {
        new->oper1 = copy_addr(ap1);
        new->oper2 = copy_addr(ap2);
    }
    //        fixlen(new->oper1);
    //        fixlen(new->oper2);
    new->fwd = after->fwd;
    after->fwd->back = new;
    new->back = after;
    after->fwd = new;
    return new;
}

//-------------------------------------------------------------------------

void ThunkUncommittedStack(void)
{
    if (lc_maxauto >= 4096)
    {
        OCODE *after = frame_ins->back;
        AMODE *ap;
        remove_peep_entry(frame_ins);
        after = ThunkAddPeep(after, op_mov, makedreg(ECX), make_immed
            (lc_maxauto));
        ap = set_symbol("___substack", 1);
        after = ThunkAddPeep(after, op_call, ap, 0);
    }
}

//-------------------------------------------------------------------------

AMODE *genreturn(SNODE *stmt, int flag)
/*
 *      generate a return statement.
 */
{
    AMODE *ap = 0,  *ap1,  *ap2;
    ENODE ep;
    int size, esize, t, q;
    SubProfilerData();
    ThunkUncommittedStack();
    if (stmt != 0 && stmt->exp != 0)
    {
        if (!genning_inline)
            initstack();
        if (currentfunc->tp->btp && isstructured(currentfunc->tp->btp))
        {
            size = currentfunc->tp->btp->size;
            ep.nodetype = en_ul_ref;
            ep.v.p[0] = stmt->exp;
            ap = gen_expr(&ep, FALSE, FALSE, 0);
            returndreg = TRUE;
        }
        else if (currentfunc->tp->btp && currentfunc->tp->btp->type ==
            bt_memberptr)
        {
            size = 4;
            ap = gen_expr(stmt->exp, FALSE, TRUE, BESZ_DWORD );
            returndreg = TRUE;

        }
        else
        {
            {
                if (currentfunc->tp->btp->type == bt_bool)
                    size = 5;
                else
                    size = currentfunc->tp->btp->size;
                if (size == 4 && currentfunc->tp->btp->type == bt_float)
                    size = 7;
                if (currentfunc->tp->btp->type == bt_farpointer)
                {
                    size = currentfunc->tp->btp->type == bt_long ?  - 6: 6;
                    ap = gen_expr(stmt->exp, FALSE, FALSE, size);
                    do_extend(ap, size, F_AXDX);
                    ap->length = BESZ_QWORD;
                    retsize = 8;
                }
                else if (currentfunc->tp->btp->type == bt_longlong ||
                    currentfunc->tp->btp->type == bt_unsignedlonglong)
                {
                    size = currentfunc->tp->btp->type == bt_long ?  - BESZ_QWORD: BESZ_QWORD;
                    ap = gen_expr(stmt->exp, FALSE, FALSE, size);
                    do_extend(ap, size, F_AXDX);
                }
                else if (currentfunc->tp->btp->type == bt_float || currentfunc->tp->btp->type == bt_double 
                        || currentfunc->tp->btp->type == bt_longdouble)
                {
                    retsize = 10;
                    ap = gen_expr(stmt->exp, FALSE, FALSE, 10);
                    do_extend(ap, 10, F_FREG);
                }
                else if (currentfunc->tp->btp->type == bt_fimaginary || currentfunc->tp->btp->type == bt_rimaginary 
                        || currentfunc->tp->btp->type == bt_lrimaginary)
                {
                    retsize = 17;
                    ap = gen_expr(stmt->exp, FALSE, FALSE, 17);
                    do_extend(ap, 17, F_FREG);
                }
                else if (currentfunc->tp->btp->type == bt_fcomplex || currentfunc->tp->btp->type == bt_rcomplex 
                        || currentfunc->tp->btp->type == bt_lrcomplex)
                {
                    retsize = 22;
                    ap = gen_expr(stmt->exp, FALSE, FALSE, 22);
                    do_extend(ap, 22, 0);
                }
                else
                {
                    returndreg = TRUE;
                    retsize = 4;

                    ap = gen_expr(stmt->exp, FALSE, FALSE, size);
                    do_extend(ap, size, F_DREG | F_VOL);
                    if (!genning_inline && ap->preg != 0)
                    {
                        gen_codes(op_mov, size, makedreg(0), ap);
                        ap = makedreg(EAX);
                    }
                }
            }
        }
    }
    if (flag &1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -