sslgen.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 589 行 · 第 1/2 页

C
589
字号
        for( ;; ) {
            if( ins == NULL ) return( change );
            next = ins->flink;
            if( !dead_code ) break;
            if( ins->ins == INS_LABEL ) break;
            DelStream( ins );
            ins = next;
            change = 1;
        }
        dead_code = 0;
        switch( ins->ins & INS_MASK ) {
        case INS_JUMP:
            for( dest = ins->ptr; dest->ins == INS_LABEL; dest = dest->flink )
                ;
            switch( dest->ins & INS_MASK ) {
            case INS_KILL:
                /* jump to kill */
                next = NewIns( dest->ins );
                next->operand = dest->operand;
                AddStream( ins, next );
                DelStream( ins );
                next = next->flink;
                change = 1;
                break;
            case INS_RETURN:
                /* jump to return */
                next = NewIns( INS_RETURN );
                AddStream( ins, next );
                DelStream( ins );
                next = next->flink;
                change = 1;
                break;
            case INS_JUMP:
                /* jump to jump */
                if( ins == dest ) {
                    next = NewIns( INS_KILL );
                    next->operand = 0;
                    AddStream( ins, next );
                    DelStream( ins );
                    next = next->flink;
                } else {
                    ((instruction *)ins->ptr)->operand--;
                    ins->ptr = dest->ptr;
                    ((instruction *)ins->ptr)->operand++;
                }
                change = 1;
                break;
            }
            dead_code = 1;
            break;
        case INS_CALL:
            dest = ins->ptr;
            if( dest->location == NO_LOCATION ) break;
            for( ; dest->ins == INS_LABEL; dest = dest->flink ) {
            }
            switch( dest->ins & INS_MASK ) {
            case INS_KILL:
                /* call to kill */
                dead_code = 1;
                next = NewIns( dest->ins );
                next->operand = dest->operand;
                AddStream( ins, next );
                DelStream( ins );
                change = 1;
                break;
            case INS_RETURN:
                /* call to return */
                DelStream( ins );
                change = 1;
                break;
            case INS_JUMP:
                /* call to jump */
                ((instruction *)ins->ptr)->operand--;
                ins->ptr = dest->ptr;
                ((instruction *)ins->ptr)->operand++;
                change = 1;
                break;
            default:
                for( dest = ins->flink;
                     dest->ins == INS_LABEL;
                     dest = dest->flink )
                    ;
                if( dest->ins == INS_RETURN ) {
                    /* call followed by a return */
                    ins->ins = INS_JUMP;
                    change = 1;
                    dead_code = 1;
                }
                break;
            }
            break;
        case INS_RETURN:
            dead_code = 1;
            break;
        case INS_KILL:
            dead_code = 1;
            break;
        case INS_LABEL:
            /* dead label */
            if( ins->operand == 0 ) {
                DelStream( ins );
                change = 1;
            }
            break;
        }
    }
}


static unsigned Locate(void)
{
    instruction *ins;
    unsigned    loc;

    loc = 0;
    for( ins = FirstIns; ins != NULL; ins = ins->flink ) {
        ins->location = loc;
        switch( ins->ins & INS_MASK ) {
        case INS_RETURN:
        case INS_IN_ANY:
            loc += sizeof( char );
            break;
        case INS_INPUT:
        case INS_ERROR:
        case INS_OUTPUT:
            loc += sizeof( char ) + sizeof( char );
            if( ins->ins & INS_LONG ) loc += sizeof( char );
            break;
        case INS_JUMP:
        case INS_CALL:
            loc += sizeof( char ) + sizeof( char );
            if( ins->ins & INS_LONG ) loc += sizeof( char );
            break;
        case INS_IN_CHOICE:
        case INS_CHOICE:
            loc += sizeof( char ) + sizeof( char ) + ins->operand *
                       ( sizeof( char ) + sizeof( unsigned short ) );
            if( ins->ins & INS_LONG ) loc += ins->operand * sizeof( char );
            break;
        case INS_SET_RESULT:
        case INS_SET_PARM:
            loc += sizeof( char ) + sizeof( char );
            if( ins->ins & INS_LONG ) loc += sizeof( char );
            break;
        case INS_SEMANTIC:
            loc += sizeof( char ) + sizeof( char );
            if( ins->ins & INS_LONG ) loc += sizeof( char );
            break;
        case INS_KILL:
            loc += sizeof( char ) + sizeof( char );
            if( ins->ins & INS_LONG ) loc += sizeof( char );
            break;
        case INS_LABEL:
            loc += 0;
            break;
        }
    }
    return( loc );
}


static char Expand(void)
{
    instruction *ins;
    instruction *dest;
    signed int  diff;
    char        change;

    change = 0;
    for( ins = FirstIns; ins != NULL; ins = ins->flink ) {
        switch( ins->ins ) {
        case INS_JUMP: /* short form */
        case INS_CALL: /* short form */
            dest = ins->ptr;
            diff = dest->location - ins->location;
            if( diff != (signed char) diff ) {
                ins->ins |= INS_LONG; /* change to long form */
                change = 1;
            }
            break;
        }
    }
    return( change );
}

extern void GenCode(void)
{
    while( Optimize() )
        ;
    do {
        Locate();
    } while( Expand() );
}

static void OutOper( instruction *ins )
{
    if( ins->ins & INS_LONG ) {
        OutWord( ins->operand );
    } else {
        OutByte( ins->operand );
    }
}

static void OutDisp( instruction *ins )
{
    int disp;

    disp = ((instruction *)ins->ptr)->location - ins->location;
    if( ins->ins & INS_LONG ) {
        OutWord( disp );
    } else {
        OutByte( disp );
    }
}

void DumpGenCode(void)
{
    instruction *ins;
    instruction *next;
    choice_entry *choice;

    OutStartSect( "Code", Locate() );
    for( ins = FirstIns; ins != NULL; ins = next ) {
        next = ins->flink;
        if( ins->ins != INS_LABEL ) OutByte( ins->ins );
        Dump( "[%.4x] %c ", ins->location, (ins->ins & INS_LONG) ? 'L' : 'S' );
        switch( ins->ins & INS_MASK ) {
        case INS_INPUT:
            Dump( "INPUT: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_IN_ANY:
            Dump( "IN_ANY\n" );
            break;
        case INS_OUTPUT:
            Dump( "OUTPUT: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_ERROR:
            Dump( "ERROR: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_JUMP:
            Dump( "JUMP L%.4x\n", ((instruction *)ins->ptr)->location );
            OutDisp( ins );
            break;
        case INS_CALL:
            Dump( "CALL L%.4x\n", ((instruction *)ins->ptr)->location );
            OutDisp( ins );
            break;
        case INS_SET_RESULT:
            Dump( "SET RES: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_RETURN:
            Dump( "RETURN\n" );
            break;
        case INS_IN_CHOICE:
        case INS_CHOICE:
            Dump( "%sCHOICE: %d\n", (ins->ins == INS_IN_CHOICE) ? "IN_" : "",
                  ins->operand );
            OutByte( ins->operand );
            for( choice = ins->ptr; choice != NULL; choice = choice->link ) {
                Dump( "        %4d L%.4x\n", choice->value,
                      choice->lbl->location );
                if( ins->ins & INS_LONG ) {
                    OutWord( choice->value );
                } else {
                    OutByte( choice->value );
                }
                OutWord( choice->lbl->location );
            }
            break;
        case INS_SET_PARM:
            Dump( "SET PARM: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_SEMANTIC:
            Dump( "SEMANTIC: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_KILL:
            Dump( "KILL: %d\n", ins->operand );
            OutOper( ins );
            break;
        case INS_LABEL:
            Dump( "LABEL: %d\n", ins->operand );
            break;
        }
        DelStream( ins );
    }
    OutEndSect();
}

⌨️ 快捷键说明

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