i86obj.c

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

C
2,113
字号
        if( lib == NULL )
            break;
        NeedMore( Imports, sizeof( unsigned_16 ) );
        _ARRAY( Imports, unsigned_16 ) = _TargetInt( LIBNAME_COMMENT );
        Imports->used += sizeof( unsigned_16 );
        OutString( ( (char*)FEAuxInfo( lib, LIBRARY_NAME ) ) + 1, Imports );
        PutObjRec( CMD_COMENT, Imports->array, Imports->used );
        Imports->used = 0;
    }
    KillArray( Imports );
    Imports = NULL;
    KillArray( SegInfo );
    FiniAbsPatches();
    EndModule();
    CloseObj();
    FEMessage( MSG_CODE_SIZE, (pointer)CodeSize );
    FEMessage( MSG_DATA_SIZE, (pointer)DataSize );
}


static  void    FiniTarg( void )
/******************************/
{
    union{
        offset           s;
        long_offset      l;
    }size;
    byte        attr;
    index_rec   *rec;
    object      *obj;

    FlushObject();
    obj = CurrSeg->obj;
    if( obj->exports != NULL ) {
        KillArray( obj->exports );
        obj->exports = NULL;
    }
    rec = AskIndexRec( obj->index );
#ifdef _OMF_32
    size.s = _TargetInt( rec->max_size );
#else //SEG32DBG dwarf, codview
    if( rec->attr & SEG_USE_32 ) {
        size.l = _TargetLongInt( rec->max_size );
    } else {
        size.s = _TargetInt( rec->max_size );
    }
#endif
    if( rec->exec ) {
        CodeSize += rec->max_size + rec->total_comdat_size;
    } else if( rec->cidx == _NIDX_DATA ) {
        DataSize += rec->max_size + rec->total_comdat_size;
    }
    if( rec->big ) {
        attr = rec->attr | SEG_BIG;
        PatchObj( obj->segfix, SEGDEF_ATTR, &attr, sizeof( byte ) );
    } else {
#ifdef _OMF_32
        PatchObj( obj->segfix, SEGDEF_SIZE, (byte *)&size.s, sizeof( offset ) );
#else   //SEG32DBG dwarf, codview
        if( rec->attr & SEG_USE_32 ) {
            PatchObj( obj->segfix, SEGDEF_SIZE, (byte *)&size.l, sizeof( long_offset ) );
        } else {
            PatchObj( obj->segfix, SEGDEF_SIZE, (byte *)&size.s, sizeof( offset ) );
        }
#endif
    }
    if( obj->exports != NULL ) {
        KillArray( obj->exports );
    }
    KillStatic( &obj->data );
    KillStatic( &obj->fixes );
    _Free( obj, sizeof( object ) );
}

static  void    DoPatch( patch *pat, offset lc ) {
/************************************************/

    unsigned_32 lword;
    unsigned_16 word;
    byte        bite;

    if( pat->attr & LONG_PATCH ) {
        if( pat->attr & ADD_PATCH ) {
            GetFromObj( pat->ref, pat->where,
                       (byte *)&lword, sizeof( long_offset ) );
            _TargetAddL( lword, lc );
        } else {
            lword = _TargetLongInt( lc );
        }
        PatchObj( pat->ref, pat->where, (byte *)&lword, sizeof( long_offset ) );
    } else if( pat->attr & WORD_PATCH ) {
        if( pat->attr & ADD_PATCH ) {
            GetFromObj( pat->ref, pat->where, (byte *)&word, sizeof( short_offset ) );
            _TargetAddW( word, lc );
        } else {
            word = _TargetInt( lc );
        }
        PatchObj( pat->ref, pat->where, (byte *)&word, sizeof( short_offset ) );
    } else {
        if( pat->attr & ADD_PATCH ) {
            GetFromObj( pat->ref, pat->where, &bite, sizeof( byte ) );
            _TargetAddB( bite, lc );
        } else {
            bite = _TargetInt( lc );
        }
        PatchObj( pat->ref, pat->where, &bite, sizeof( byte ) );
    }
}



static  void    FreeAbsPatch( abspatch *patch ) {
/***********************************************/

    abspatch    **owner;

    owner = &AbsPatches;
    while( *owner != patch ) {
        owner = &(*owner)->link;
    }
    *owner = (*owner)->link;
    _Free( patch, sizeof( abspatch ) );
}


static  void    FiniAbsPatches( void ) {
/********************************/

    abspatch    *patch;
    abspatch    *junk;

    patch = AbsPatches;
    while( patch != NULL ) {
        DoPatch( &patch->pat, patch->value );
        junk = patch;
        patch = patch->link;
        _Free( junk, sizeof( abspatch ) );
    }
}


/*%% Code Burst Routines*/


extern  void    SetUpObj( bool is_data ) {
/****************************************/

    object      *obj;
    bool        old_data;

    obj = CurrSeg->obj;
    if( obj == NULL )
        return;
    Out = &obj->data;
    OutBuff = obj->data.array;
    if( obj->fixes.used >= BUFFSIZE - TOLERANCE ) {
        EjectLEData();
        return;
    }
    if( (Imports != NULL) && (Imports->used >= BUFFSIZE - TOLERANCE) ) {
         EjectLEData();
         return;
    }
    /* so that a call will always fit */
    CheckLEDataSize( 4*sizeof( offset ), FALSE );
    if( CurrSeg->exec ) {
        old_data = CurrSeg->data_in_code;
        CurrSeg->data_in_code = is_data;
        if( is_data != old_data ) {
            if( is_data ) {
                CurrSeg->start_data_in_code = TRUE;
            } else {
                OutSelect( FALSE );
                SetUpObj( FALSE );
            }
        }
    }
}


static  void    OutExport( sym_handle sym ) {
/*******************************************/

    array_control       *exp;
    object              *obj;
    fe_attr             attr;


    obj = CurrSeg->obj;
    exp = obj->exports;
    if( exp == NULL ) {
        exp = InitArray( sizeof( byte ), MODEST_EXP, INCREMENT_EXP );
        obj->exports = exp;
    }
    if( obj->exports->used >= BUFFSIZE - TOLERANCE ) {
        EjectExports();
    }
    attr = FEAttr( sym );
    /* are we switching from global to statics or vis-versa */
    if( obj->gen_static_exports ) {
        if( attr & FE_GLOBAL ) {
            EjectExports();
            obj->gen_static_exports = FALSE;
        }
    } else {
        if( !(attr & FE_GLOBAL) ) {
            EjectExports();
            obj->gen_static_exports = TRUE;
        }
    }
    if( obj->exports->used == 0 ) {
        if( CurrSeg->btype == BASE_GRP ) {
            OutIdx( CurrSeg->base, exp );   /* group index*/
        } else {
#ifdef _OMF_32
            OutIdx( FlatGIndex, exp ); // will be 0 if we have none
#else
            OutIdx( 0, exp );
#endif
        }
        OutIdx( obj->index, exp );      /* segment index*/
    }
    OutObjectName( sym, exp );
    NeedMore( exp, sizeof( offset ) );
    _ARRAY( exp, offset ) = _TargetOffset( CurrSeg->location );
    exp->used += sizeof( offset );
    OutIdx( 0, exp );                   /* type index*/
}


static  void    GenComdef( void ) {
/****************************/

    array_control       *comdef;
    unsigned            count;
    unsigned_8          type;
    unsigned_8          ind;
    unsigned long       size;
    sym_handle          sym;
    unsigned            rec;

    if( CurrSeg->comdat_label != NULL &&
        CurrSeg->max_written < CurrSeg->comdat_size ) {
        if( CurrSeg->max_written != 0 ) {
            Zoiks( ZOIKS_080 );
        }
        /* have to eject any pending imports here or the ordering
           gets messed up */
        EjectImports();
        size = CurrSeg->comdat_size - CurrSeg->max_written;
        comdef = InitArray( sizeof( byte ), MODEST_EXP, INCREMENT_EXP );
        sym = CurrSeg->comdat_symbol;
        OutObjectName( sym, comdef );
        NeedMore( comdef, 4 );
        _ARRAY( comdef, unsigned_8 ) = 0; /* type index */
        comdef->used += sizeof( unsigned_8 );
        if( CurrSeg->btype == BASE_GRP && CurrSeg->base == DGroupIndex ) {
            type = COMDEF_NEAR;
        } else {
            type = COMDEF_FAR;
        }
        _ARRAY( comdef, unsigned_8 ) = type; /* common type */
        comdef->used += sizeof( unsigned_8 );
        if( type == COMDEF_FAR ) {
            _ARRAY( comdef, unsigned_8 ) = 1; /* number of elements */
            comdef->used += sizeof( unsigned_8 );
        }
        /*
            Strictly speaking, this should be <= 0x80. However a number
            of tools (including our own!) have problems with doing a
            128 byte COMDEF size in 1 byte, so we'll waste some space
            and use 2 bytes, but sleep much sounder at night.
        */
        if( size < 0x80 ) {
            count = 1;
            ind = 0;
        } else if( size < 0x1000 ) {
            count = 2;
            ind = COMDEF_LEAF_2;
        } else if( size < 0x100000 ) {
            count = 3;
            ind = COMDEF_LEAF_3;
        } else {
            count = 4;
            ind = COMDEF_LEAF_4;
        }
        if( ind != 0 ) {
            /* multi-byte indicator */
            _ARRAY( comdef, unsigned_8 ) = ind;
            comdef->used += sizeof( unsigned_8 );
        }
        NeedMore( comdef, count );
        do {
            /* element size */
            _ARRAY( comdef, unsigned_8 ) = size & 0xff;
            comdef->used += sizeof( unsigned_8 );
            size >>= 8;
            --count;
        } while( count != 0 );
        if( FEAttr( sym ) & FE_GLOBAL ) {
            rec = CMD_COMDEF;
        } else {
            rec = CMD_LCOMDEF;
        }
        PutObjRec( rec, comdef->array, comdef->used );
        KillArray( comdef );
        TellImportHandle( sym, ImportHdl++ );
    }
}

static void GetSymLName( char *name, void *nidx )
{
    *(unsigned *)nidx = GetNameIdx( name, "", TRUE );
}

static unsigned NeedComdatNidx( import_type kind ) {
/***************************************************/

    if( CurrSeg->comdat_nidx == 0 ) {
        DoOutObjectName( CurrSeg->comdat_symbol, GetSymLName,
                        &CurrSeg->comdat_nidx, kind );
        FlushNames();
    }
    return( CurrSeg->comdat_nidx );
}


static  void    NormalData( void ) {
/****************************/

    GenComdef();
    CurrSeg->total_comdat_size += CurrSeg->comdat_size;
    EjectLEData();
    FlushLineNum();
    FlushSelect();
    CurrSeg->location = CurrSeg->max_written = CurrSeg->max_size;
    CurrSeg->comdat_size = 0;
    CurrSeg->comdat_label = NULL;
    CurrSeg->comdat_symbol = NULL;
    CurrSeg->need_base_set = TRUE;
    CurrSeg->prefix_comdat_state = PCS_OFF;
    KillLblRedirects();
}


static  void    ComdatData( label_handle lbl, sym_handle sym ) {
/**************************************************************/

    GenComdef();
    CurrSeg->total_comdat_size += CurrSeg->comdat_size;
    EjectLEData();
    FlushLineNum();
    FlushSelect();
    CurrSeg->obj->lines_generated = FALSE;
    CurrSeg->location = CurrSeg->max_written = 0;
    CurrSeg->comdat_size = 0;
    CurrSeg->comdat_nidx = 0;
    CurrSeg->comdat_label = lbl;
    if( sym != NULL ) {
        CurrSeg->comdat_symbol = sym;
    } else {
        NeedComdatNidx( SPECIAL );
        CurrSeg->comdat_prefix_import =
                GenImport( CurrSeg->comdat_symbol, SPECIAL );
        TellCommonLabel( lbl, CurrSeg->comdat_prefix_import );
    }
    CurrSeg->need_base_set = TRUE;
    CurrSeg->prefix_comdat_state = PCS_OFF;
    KillLblRedirects();
}

static void     OutVirtFuncRef( sym_handle virt ) {
/*************************************************/

    object      *obj;
    unsigned    extdef;

    if( virt == NULL ) {
        extdef = 0;
    } else {
        extdef = GenImport( virt, NORMAL );
    }
    EjectLEData();
    obj = CurrSeg->obj;
    Out = &obj->data;
    OutBuff = obj->data.array;
    Out->used = 0;
    NeedMore( Out, sizeof( unsigned_16 ) );
    _ARRAY( Out, unsigned_16 ) = _TargetInt( LINKER_COMMENT );
    Out->used += sizeof( unsigned_16 );
    OutByte( LDIR_VF_REFERENCE );
    OutIdx( extdef, Out );
    if( CurrSeg->comdat_symbol != NULL ) {
        OutIdx( 0, Out );
        OutIdx( NeedComdatNidx( NORMAL ), Out );
    } else {
        OutIdx( CurrSeg->sidx, Out );
    }
    PutObjRec( CMD_COMENT, Out->array, Out->used );
    Out->used = 0;
}


extern  void    OutLabel( label_handle lbl ) {
/********************************************/

    temp_patch          **owner;
    temp_patch          *curr_pat;
    array_control       *ctl;
    patch               *pat;
    int                 i;
    pointer             patptr;
    object              *obj;
    offset              lc;
    sym_handle          sym;
    fe_attr             attr;
    void                *cookie;
    virt_func_ref_list  *curr;
    virt_func_ref_list  *next;

    sym = AskForLblSym( lbl );
    if( sym != NULL ) {

⌨️ 快捷键说明

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