wat2can1.c

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

C
1,387
字号
        hdl->d.reg.num_regs = 1;
        hdl->d.reg.reg[ 0 ] = watReg2CanReg( loc_class & 0x0f );
        break;

    case WAT_IND_REG:
        hdl = CanSNew( CANS_IND_REG );
        hdl->d.indr.off = watReg2CanReg( get8() );
        switch( loc_class & 0x0f ) {
        case WAT_IR_CALLOC_NEAR:
            hdl->d.indr.calloc = 1;
            hdl->d.indr.far_ptr = 0;
            break;
        case WAT_IR_CALLOC_FAR:
            hdl->d.indr.calloc = 1;
            hdl->d.indr.far_ptr = 0;
            hdl->d.indr.seg = watReg2CanReg( get8() );
            break;
        case WAT_IR_RALLOC_NEAR:
            hdl->d.indr.calloc = 0;
            hdl->d.indr.far_ptr = 0;
            break;
        case WAT_IR_RALLOC_FAR:
            hdl->d.indr.calloc = 0;
            hdl->d.indr.far_ptr = 1;
            hdl->d.indr.seg = watReg2CanReg( get8() );
            break;
        default:
/**/        never_reach();
        }
        break;

    default:
        Fatal( MSG_CPP_EXTENSION );
    }
    return( hdl );
}

STATIC void symbOneVariable( uint_8 symb_class, name_handle *hdl ) {

    symb_handle var_hdl;

    switch( symb_class & 0x0f ) {
    case WAT_VAR_MODULE:
        var_hdl = CanSNew( CANS_MEM_LOC );
        var_hdl->d.memloc.mem_hdl = getAddr32();
        var_hdl->d.memloc.is_static = 1;
        var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
        *hdl = hdlName();
        var_hdl->d.nat.name_hdl = *hdl;
        headSymb = CanSIBefore( headSymb, var_hdl );
        break;

    case WAT_VAR_LOCAL:
/**/    never_reach();
        break;

    case WAT_VAR_MODULE_386:
        var_hdl = CanSNew( CANS_MEM_LOC );
        var_hdl->d.memloc.mem_hdl = getAddr48();
        var_hdl->d.memloc.is_static = 1;
        var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
        *hdl = hdlName();
        var_hdl->d.nat.name_hdl = *hdl;
        headSymb = CanSIBefore( headSymb, var_hdl );
        break;

    default:
        Fatal( MSG_CPP_EXTENSION );
    }
/**/myassert( endOfRecord() );
}

STATIC void symbVariable( uint_8 symb_class ) {

    name_handle garbage;

    symbOneVariable( symb_class, &garbage );
}

STATIC int symbOneLocal( symb_handle block, name_handle *hdl ) {
/*
    Assumes that block has no BLOCK_END or EPILOG yet
*/
    uint_8  symb_class;

/**/myassert( block != NULL );
    if( wat->ptr == wat->finish ) {
        return( 0 );
    }
    symb_class = nextRec();
    switch( symb_class & 0xf0 ) {
    case WAT_VARIABLE:
        splatRec( SPLAT_COUNT );
        if( ( symb_class & 0x0f ) == WAT_VAR_LOCAL ) {
            symb_handle var_hdl;
            var_hdl = hdlLocation();
            var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
            *hdl = hdlName();
            var_hdl->d.nat.name_hdl = *hdl;
            CanSIBefore( block, var_hdl );
        } else {
            symbOneVariable( symb_class, hdl );
        }
/**/    myassert( endOfRecord() );
        return( 1 );
        break;
    case WAT_CODE:
    case WAT_NEW_BASE:
    case SPLAT:
        return( 0 );
        break;
    default:
/**/    never_reach();
        return( 0 );
    }
}

STATIC void symbParseLocals( symb_handle block, uint_8 num_parms ) {
/*
    We need to give names to the parameters to a function.  Unfortunately,
    there is no direct provision for this in the WATCOM debugging info.
    The following assumption is made:

        name of parm 0 is name of last local
        name of parm 1 is name of 2nd last local
        ...
        name of parm num_parms-1 is name of (last-num_parms+1)st local

    We'll keep track of num_parms locals in a vector.  When done, we'll
    flip the vector a few times and assign to the parms.
*/

    name_handle *name_vec;
    uint_8      cur_off;
    symb_handle walk;
    uint_8      walk_off;

/**/myassert( block != NULL && num_parms > 0 );
    name_vec = alloca( num_parms * sizeof( name_handle ) );
    for( cur_off = 0; cur_off < num_parms; ++cur_off ) {
        name_vec[ cur_off ] = NAME_NULL;
    }
    cur_off = 0;
    for(;;) {
        if( symbOneLocal( block, name_vec + cur_off ) == 0 ) break;
        ++cur_off;
        if( cur_off == num_parms ) {
            cur_off = 0;
        }
    }
    /* name_vec[ cur_off ] is the name of the last parm */
    /* name_vec[ ( cur_off + 1 ) % num_parms ] is the name of the 2nd last... */
    walk = CanSFwd( block );
    walk_off = 0;
    do {
        if( cur_off == 0 ) {
            cur_off = num_parms;
        }
        --cur_off;
/**/    myassert(   walk->class == CANS_MEM_LOC ||
                    walk->class == CANS_BP_OFFSET ||
                    walk->class == CANS_REGISTER );
        walk->d.nat.name_hdl = name_vec[ cur_off ];
        walk = CanSFwd( walk );
        ++walk_off;
    } while( walk_off < num_parms );
}


STATIC symb_handle symbCode( uint_8 symb_class ) {

    symb_handle     block;          /* the block we are creating            */
    uint_16         parent_offset;  /* offset of parent block in ddSymbols  */
    symb_handle     parent_hdl;     /* handle for parent block              */
    symb_handle     work_hdl;       /* a temporary working handle           */
    symb_handle     prolog_hdl;     /* handle for the prolog/ret_val        */
    uint_8          epilog_size;    /* size of the epilog                   */
    uint_8          num_parms;      /* number of parameters in registers    */
    unsigned        i;              /* general counter                      */
    int             is32rec;        /* is this one of the 32bit records?    */
    symb_handle     parm_hdl;
    cantype         *blk_type;
    proc_parm       *parm_list;     /* blk_type->d.proc.parms               */
    cantype         *parm_type;
    int_32          bp_offset;

    block = offMapCur();
    symb_class &= 0x0f;
    switch( symb_class ) {
    case WAT_CODE_BLOCK:
    case WAT_CODE_NEAR_RTN:
    case WAT_CODE_FAR_RTN:
        is32rec = 0;
        block->extra = get16();
        block->d.block.size = get16();
        break;
    case WAT_CODE_BLOCK_386:
    case WAT_CODE_NEAR_RTN_386:
    case WAT_CODE_FAR_RTN_386:
        is32rec = 1;
        block->extra = get32();
        block->d.block.size = get32();
        break;
    default:
        Fatal( MSG_CPP_EXTENSION );
    }
    parent_offset = get16();
    if( parent_offset != 0 ) {
        parent_hdl = offMap( parent_offset );
        block->d.block.start_offset = block->extra - parent_hdl->extra;
    } else {
        parent_hdl = CANS_NULL;
        block->d.block.start_offset = block->extra;
    }

    prolog_hdl = CanSNew( CANS_PROLOG );
    switch( symb_class ) {
    case WAT_CODE_BLOCK:
    case WAT_CODE_BLOCK_386:
        num_parms = 0;
        prolog_hdl->d.prolog.size = 0;
        prolog_hdl->d.prolog.has_ret_val = 0;
        prolog_hdl->d.prolog.has_ret_addr = 0;
        prolog_hdl->d.prolog.ret_addr_offset = 0;
        CanSIAfter( block, prolog_hdl );
        epilog_size = 0;
        break;
    case WAT_CODE_NEAR_RTN:
    case WAT_CODE_FAR_RTN:
    case WAT_CODE_NEAR_RTN_386:
    case WAT_CODE_FAR_RTN_386:
        prolog_hdl->d.prolog.size = get8();
        epilog_size = get8();               /* save for later */
        prolog_hdl->d.prolog.has_ret_addr = 1;
        if( is32rec ) {
            bp_offset = get32();
        } else {
            bp_offset = (int_32)get16();
        }
        prolog_hdl->d.prolog.ret_addr_offset = bp_offset;
        block->d.nat.type_hdl = mapIdx( getIndex() );
        blk_type = CanTFind( block->d.nat.type_hdl );
/**/    myassert( blk_type == NULL || blk_type->class == CANT_PROCEDURE );
        work_hdl = hdlLocation();
        if( work_hdl != CANS_NULL ) {
            CanSIAfter( prolog_hdl, work_hdl );
            prolog_hdl->d.prolog.has_ret_val = 1;
        } else {
            prolog_hdl->d.prolog.has_ret_val = 0;
        }
        num_parms = get8();
/**/    myassert( blk_type == NULL ||
            num_parms <= blk_type->d.proc.num_parms );
        if( blk_type != NULL ) {
            parm_list = blk_type->d.proc.parms;
        } else {
            parm_list = NULL;
        }
        for( i = 0; i < num_parms; ++i ) {
            parm_hdl = hdlLocation();
            CanSIBefore( block, parm_hdl );
            if( parm_list != NULL ) {
                parm_hdl->d.nat.type_hdl = parm_list[ i ].type;
            }
        }
        /* note we need the value of i from above loop inside this if() {} */
        num_parms = blk_type->d.proc.num_parms;
        if( i < num_parms && blk_type != NULL ) {
            /*
               Now we have to build the stack-based parms, bp_offset was set
               to the bp offset of the return address above.  We add 2, 4, or 6
               depending on near/far/386/386far
            */
            switch( symb_class ) {      /* note the major fall through! */
            case WAT_CODE_FAR_RTN_386:
                bp_offset += 2;
            case WAT_CODE_NEAR_RTN_386:
            case WAT_CODE_FAR_RTN:
                bp_offset += 2;
            case WAT_CODE_NEAR_RTN:
                bp_offset += 2;
            }
/**/        myassert( parm_list == blk_type->d.proc.parms );
            for(;;) {
                parm_hdl = CanSNew( CANS_BP_OFFSET );
                CanSIBefore( block, parm_hdl );
                parm_hdl->d.bpoff.offset = bp_offset;
                parm_hdl->d.nat.type_hdl = parm_list[ i ].type;
                parm_type = CanTFind( parm_hdl->d.nat.type_hdl );
                ++i;
                if( i == num_parms ) break;
                if( is32rec ) { /* determine positioning of next arg */
                    bp_offset += ( ( parm_type->size + 31 ) &~(int_32)31 ) / 8;
                } else {
                    bp_offset += ( ( parm_type->size + 15 ) &~(int_32)15 ) / 8;
                }
            }
        }
        block->d.nat.name_hdl = hdlName();
        CanSIBefore( block, prolog_hdl );   /* add the PROLOG */
        break;
    }

/**/myassert( endOfRecord() );
    if( num_parms > 0 ) {
        symbParseLocals( block, num_parms );
    } else {
        name_handle garbage;

        while( symbOneLocal( block, &garbage ) ) {
            /* nop */
        }
    }
    wat->ptr = wat->start_rec;
    wat->rec_len = 0;
/**/myassert( endOfRecord() );

    work_hdl = CanSNew( CANS_EPILOG );      /* add the EPILOG */
    work_hdl->d.epilog.size = epilog_size;
    CanSIBefore( block, work_hdl );
    work_hdl = CanSNew( CANS_BLOCK_END );   /* add the BLOCK_END */
    work_hdl->d.end.start = block;
    block->d.block.end = work_hdl;
    CanSIBefore( block, work_hdl );         /* complete the block */

        /* attach to parent or to headSymb as appropriate */
    if( parent_hdl != CANS_NULL ) {
/**/    myassert( parent_hdl->class == CANS_BLOCK );
        work_hdl = parent_hdl->d.block.end;
/**/    myassert( work_hdl != NULL );
/**/    myassert( work_hdl->class == CANS_BLOCK_END );
        work_hdl = CanSBwd( work_hdl );
/**/    myassert( work_hdl->class == CANS_EPILOG );
        CanSIBefore( work_hdl, block );
    } else {
        headSymb = CanSIBefore( headSymb, block );
    }

    return( block );
}

STATIC void symbNewBase( uint_8 symb_class ) {

    symb_handle seg_hdl;

    seg_hdl = CanSNew( CANS_CHANGE_SEG );
    switch( symb_class & 0x0f ) {
    case WAT_NB_ADD_PREV_SEG:
        Fatal( MSG_ADD_PREV_SEG );
    case WAT_NB_SET_BASE:
        seg_hdl->d.cseg.seg = getAddr32();
        break;
    case WAT_NB_SET_BASE_386:
        seg_hdl->d.cseg.seg = getAddr48();
        break;
    default:
/**/    never_reach();
    }
    headSymb = CanSIBefore( headSymb, seg_hdl );
}

STATIC void parseSymbol( void ) {

    uint_8  symb_class;

    symb_class = nextRec();
    splatRec( SPLAT_COUNT );
    switch( symb_class & 0xf0 ) {
    case WAT_VARIABLE:  symbVariable( symb_class );         break;
    case WAT_CODE:      symbCode( symb_class );             break;
    case WAT_NEW_BASE:  symbNewBase( symb_class );          break;
    case SPLAT:         wat->ptr += wat->rec_len - 2;       break;
    default:
/**/    never_reach();
    }
/**/myassert( endOfRecord() );
}

void Wat2CanTandS( seghdr *dd_types, seghdr *dd_symbols ) {
/*******************************************************/

    int         index;
    uint_8      *finish;

    /* setup */
    ddTypes = dd_types;
    ddSymbols = dd_symbols;
    headSymb = CANS_NULL;
    unDefdType = CanTReserve();
    stbHdl = MemAlloc( 128 * sizeof( type_handle ) );
    for( index = 0; index < 128; ++index ) {
        stbHdl[ index ] = unDefdType;
    }
    initTypeMap();
    wat = MemAlloc( sizeof( *wat ) );
    offsetMap = NULL;

    if( dd_types != NULL ) {
        /* parse types */
        parsingTypes = 1;
        wat->next = NULL;
        wat->index = 1;
        wat->start_rec = wat->ptr = ddTypes->data;
        wat->rec_len = 0;
        finish = ddTypes->data + ddTypes->alloc;
        wat->finish = finish;
#ifndef NDEBUG
        {
            int fh;
            fh = open( "debug.seg", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE|S_IREAD );
            if( fh != -1 ) {
                write( fh, ddTypes->data, ddTypes->alloc );
                close( fh );
            }
        }
#endif
        while( wat->ptr < finish ) {
            parseType();
        }
/**/    myassert( wat->next == NULL );
        SegDetachData( ddTypes );
        CanTMunge();
        CanMisc.types_present = 1;
    }
    MemFree( stbHdl );

    if( dd_symbols != NULL ) {
        /* parse symbols */
        parsingTypes = 0;
        wat->next = NULL;
        wat->index = 1;
        wat->start_rec = wat->ptr = ddSymbols->data;
        wat->rec_len = 0;
        finish = ddSymbols->data + ddSymbols->alloc;
        wat->finish = finish;
#ifndef NDEBUG
        {
            int fh;
            fh = open( "symbols.seg", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE|S_IREAD );
            if( fh != -1 ) {
                write( fh, ddSymbols->data, ddSymbols->alloc );
                close( fh );
            }
        }
#endif
        while( wat->ptr < finish ) {
            parseSymbol();
        }
/**/    myassert( wat->next == NULL );
        SegDetachData( ddSymbols );
        CanSSetHead( headSymb );
        CanMisc.symbs_present = 1;
    }

    /* cleanup */
    destroyOffsetMap();
    MemFree( wat );
    finiTypeMap();
    CanTReUse( unDefdType );
}

⌨️ 快捷键说明

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