objpass1.c

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

C
1,236
字号
    section *           sect;
    class_entry *       class;
    bool                isovlclass;

    isovlclass = FALSE;
    if( FmtData.type & MK_OVERLAYS ) {
        sdata->iscode = CheckOvlClass( clname, &isovlclass );
    }
    if( sdata->iscode ) {
        if( !sdata->is32bit ) {
            LinkState |= HAVE_16BIT_CODE;
        }
    }
    sect = DBIGetSect( clname );
    if( sect == NULL ) {
        if( !(FmtData.type & MK_OVERLAYS) || isovlclass ) {
            sect = CurrSect;
        } else {
            sect = NonSect;
        }
    }
    class = FindClass( sect, clname, sdata->is32bit, sdata->iscode );
    AddSegment( sdata, class );
    if( isovlclass ) {
        sdata->u.leader->info |= SEG_OVERLAYED;
    }
    if( !sdata->isdead && !sdata->isuninit && !sdata->iscdat ) {
        sdata->data = AllocStg( sdata->length );
    }
}

static void CheckQNXSegMismatch( stateflag mask )
/***********************************************/
{
    if( FmtData.type & MK_QNX && LinkState & mask
                                && !FmtData.u.qnx.seen_mismatch ) {
        LnkMsg( WRN+LOC+MSG_CANNOT_HAVE_16_AND_32, NULL );
        FmtData.u.qnx.seen_mismatch = TRUE;
    }
}

extern void AddSegment( segdata *sd, class_entry *class )
/*******************************************************/
/* Add a segment to the segment list for an object file */
{
    unsigned_16     info;
    unsigned_16     dbiflags;

    DEBUG((DBG_OLD,"- adding segment %s, class %s",sd->u.name, class->name ));
    DEBUG(( DBG_OLD, "- - size = %h, comb = %x, alignment = %x",
                      sd->length, sd->combine, sd->align ));
    info = 0;
    dbiflags = DBIColSeg( class );
    if( sd->is32bit ) {
        info |= USE_32;
        if( dbiflags == NOT_DEBUGGING_INFO ) {  //can use SEGD32 in 16-bit dbi
            Set32BitMode();
            CheckQNXSegMismatch( HAVE_16BIT_CODE );
        }
    } else if( dbiflags == NOT_DEBUGGING_INFO ) {
        Set16BitMode();
        CheckQNXSegMismatch( FMT_SEEN_32_BIT );
    }
    if( class->flags & CLASS_CODE ) {
        info |= SEG_CODE;
    }
    if( sd->isabs ) {
        info |= SEG_ABSOLUTE;
        sd->isdefd = TRUE;
    }
    if( DBISkip( dbiflags ) ) {
        sd->isdead = TRUE;
    }
    if( sd->isabs || sd->combine == COMBINE_INVALID ) {
        MakeNewLeader( sd, class, info );
    } else {
        char    *seg_name = sd->u.name;

        FindALeader( sd, class, info );
        if( (sd->u.leader->info & USE_32) != (info & USE_32) ) {
            char    *segname_16;
            char    *segname_32;

            if( info & USE_32 ) {
                segname_16 = sd->u.leader->segname;
                segname_32 = seg_name;
            } else {
                segname_16 = seg_name;
                segname_32 = sd->u.leader->segname;
            }
            LnkMsg( ERR+MSG_CANT_COMBINE_32_AND_16, "12", segname_32, segname_16 );
        }
    }
    Ring2Append( &CurrMod->segs, sd );
    sd->u.leader->dbgtype = dbiflags;
    if( sd->isabs ) {
        sd->u.leader->seg_addr.off = 0;
        sd->u.leader->seg_addr.seg = sd->a.frame;
    } else if( !sd->isdead ) {
        DBIAddLocal( dbiflags, sd->length );
    }
}

extern class_entry * FindClass( section *sect, char *name, bool is32bit,
                                bool iscode )
/*********************************************************************/
{
    class_entry *   currclass;
    class_entry *   lastclass;
    unsigned        namelen;

    if( is32bit ) is32bit = CLASS_32BIT;
    currclass = sect->classlist;
    lastclass = currclass;
    for(;;) {
        if( currclass == NULL ) break;
        if( stricmp( currclass->name, name ) == 0
                        && !((currclass->flags & CLASS_32BIT) ^ is32bit) ) {
            return( currclass );
        }
        lastclass = currclass;
        currclass = currclass->next_class;
    }
    namelen = strlen( name );
    currclass = CarveAlloc( CarveClass );
    currclass->name = AddStringTable( &PermStrings, name, namelen + 1 );
    currclass->segs = NULL;
    currclass->section = sect;
    currclass->flags = is32bit;
    currclass->next_class = NULL;
    if( lastclass == NULL ) {
        sect->classlist = currclass;
    } else {
        lastclass->next_class = currclass;
    }
    DBIColClass( currclass );
    if( iscode ) {
        currclass->flags |= CLASS_CODE;
    }
    if( IsConstClass( name, namelen ) ) {
        currclass->flags |= CLASS_READ_ONLY;
    }
    if( IsStackClass( name, namelen ) ) {
        currclass->flags |= CLASS_STACK;
    }
    return( currclass );
}

static void CheckForLast( seg_leader *seg, class_entry *class )
/*************************************************************/
// check to see if this segment should be the last one in an autogroup.
{
    if( CurrMod->modinfo & MOD_LAST_SEG && class->flags & CLASS_CODE ) {
        if( LastCodeSeg != NULL ) {             // more than one code seg
            LastCodeSeg->info &= ~LAST_SEGMENT; // so don't end at previous
        }
        LastCodeSeg = seg;
        seg->info |= LAST_SEGMENT;
    }
}

static bool CheckClassName( void *_seg, void *_sdata )
/****************************************************/
{
    seg_leader *seg = _seg;
    segdata *sdata = _sdata;

    return stricmp( seg->segname, sdata->u.name ) == 0 &&
                                seg->combine != COMBINE_INVALID;
}

static void AddToLeader( seg_leader *seg, segdata *sdata )
/********************************************************/
{
    segdata *   first;
    offset      length;

    if( sdata->combine == COMBINE_COMMON ) {
        first = RingFirst( seg->pieces );
        length = max( first->length, sdata->length );
        if( first->isuninit ) {
            first->isdead = TRUE;
            RingPush( &seg->pieces, sdata );
            sdata->length = length;
        } else {
            sdata->isdead = TRUE;
            RingAppend( &seg->pieces, sdata );
            first->length = length;
        }
    } else {    // it must be COMBINE_ADD
        RingAppend( &seg->pieces, sdata );
    }
}

static void FindALeader( segdata *sdata, class_entry *class, unsigned_16 info )
/*****************************************************************************/
{
    seg_leader *seg;

    seg = RingLookup( class->segs, CheckClassName, sdata );
    if( seg == NULL ) {
        MakeNewLeader( sdata, class, info );
    } else {
        sdata->u.leader = seg;
        AddToLeader( seg, sdata );
    }
}

extern seg_leader *InitLeader( char *segname, unsigned_16 info )
/**************************************************************/
{
    seg_leader * seg;

    seg = CarveAlloc( CarveLeader );
    seg->next_seg = NULL;
    seg->grp_next = NULL;
    seg->pieces = NULL;
    seg->class = NULL;
    seg->size = 0;
    seg->num = 0;
    seg->seg_addr.off = NULL;
    seg->seg_addr.seg = UNDEFINED;
    seg->group = NULL;
    seg->info = info;
    seg->segname = StringStringTable( &PermStrings, segname );
    seg->dbgtype = NOT_DEBUGGING_INFO;
    seg->segflags = FmtData.def_seg_flags;
    return( seg );
}

extern void FreeLeader( void *seg )
/*********************************/
{
    RingWalk( ((seg_leader *)seg)->pieces, FreeSegData );
    CarveFree( CarveLeader, seg );
}

static void MakeNewLeader( segdata *sdata, class_entry *class, unsigned_16 info)
/******************************************************************************/
{
    sdata->u.leader = InitLeader( sdata->u.name, info );
    sdata->u.leader->align = sdata->align;
    sdata->u.leader->combine = sdata->combine;
    sdata->u.leader->class = class;
    CheckForLast( sdata->u.leader, class );
    RingAppend( &class->segs, sdata->u.leader );
    RingAppend( &sdata->u.leader->pieces, sdata );
}

static bool CmpLeaderPtr( void *a, void *b )
/******************************************/
{
    return a == b;
}

extern void AddToGroup( group_entry *group, seg_leader *seg )
/***********************************************************/
{
    if( Ring2Lookup( group->leaders, CmpLeaderPtr, seg ) ) return;
    if( seg->group != NULL && seg->group != group ) {
        LnkMsg( LOC+ERR+MSG_SEG_IN_TWO_GROUPS, "123", seg->segname,
                                   seg->group->sym->name, group->sym->name );
        return;
    }
    if( (group->leaders != NULL) && ((group->leaders->info & USE_32) != (seg->info & USE_32)) ) {
        char    *segname_16;
        char    *segname_32;

        if( seg->info & USE_32 ) {
            segname_16 = group->leaders->segname;
            segname_32 = seg->segname;
        } else {
            segname_16 = seg->segname;
            segname_32 = group->leaders->segname;
        }
        LnkMsg( ERR+MSG_CANT_COMBINE_32_AND_16, "12", segname_32, segname_16 );
    }
    seg->group = group;
    Ring2Append( &group->leaders, seg );
}

extern void SetAddPubSym(symbol *sym, int type, mod_entry *mod, offset off,
                         unsigned_16 frame )
/*************************************************************************/
{
    sym->mod = mod;
    SET_SYM_TYPE( sym, type );
    XDefSymAddr( sym, off, frame );
    Ring2Append( &mod->publist, sym );
}

extern void DefineSymbol( symbol *sym, segnode *seg, offset off,
                          unsigned_16 frame )
/**************************************************************/
// do the object file independent public symbol definition.
{
    unsigned    name_len;
    bool        frame_ok;

    if( seg != NULL ) {
        frame = 0;
    }
    name_len = strlen( sym->name );
    if( sym->addr.seg != UNDEFINED && !IS_SYM_COMMUNAL(sym) ) {
        if( seg != NULL && sym->p.seg != NULL ) {
            frame_ok = (sym->p.seg->u.leader == seg->entry->u.leader);
            if( sym->p.seg->u.leader->combine != COMBINE_COMMON ) {
                frame_ok = FALSE;
            }
        } else if( sym->p.seg != NULL ) {
            frame_ok = FALSE;
        } else if( frame != sym->addr.seg ) {
            frame_ok = FALSE;
        } else {
            frame_ok = TRUE;
        }
        if( !(frame_ok && off == sym->addr.off) ) {
            ReportMultiple( sym, sym->name, name_len );
        }
    } else {
        if( IS_SYM_COMMUNAL(sym) || IS_SYM_IMPORTED(sym) ) {
            sym = HashReplace( sym );
            if( IS_SYM_COMMUNAL(sym) ) {
                sym->p.seg = NULL;
            }
        }

        ClearSymUnion( sym );
        SetAddPubSym(sym, SYM_REGULAR, CurrMod, off, frame);
        sym->info &= ~SYM_DISTRIB;
        if( seg != NULL ) {
            if( LinkFlags & STRIP_CODE ) {
                DefStripSym( sym, seg->entry );
            }
            if( seg->info & SEG_CODE ) {
                if( FmtData.type & MK_OVERLAYS && FmtData.u.dos.distribute
                    && LinkState & SEARCHING_LIBRARIES ) {
                    sym->info |= SYM_DISTRIB;
                }
            }
            sym->p.seg = seg->entry;
            if( sym->p.seg->isabs )
                sym->info |= SYM_ABSOLUTE;
            TryDefVector( sym );
        } else {
            if( LinkFlags & STRIP_CODE ) {
                CleanStripInfo( sym );
            }
            sym->info |= SYM_ABSOLUTE;
            sym->p.seg = NULL;
        }
    }
}

static segdata *GetSegment( char *seg_name, char *class_name, char *group_name,
                            unsigned align, unsigned comb, bool use_16 )
/*****************************************************************************/
{
    section *           sect;
    class_entry *       class;
    group_entry *       group;
    unsigned_16         info;
    segdata *           sdata;

    sect = GetOvlSect( class_name );
    class = FindClass( sect, class_name, !use_16, FALSE );
    info = 0;
    sdata = AllocSegData();
    sdata->u.name = seg_name;
    sdata->align = align;
    sdata->combine = comb;
    sdata->isuninit = TRUE;
    if( !use_16 ) {
        info |= USE_32;
        sdata->is32bit = TRUE;
    }
    FindALeader( sdata, class, info );
    Ring2Append( &CurrMod->segs, sdata );
    if( group_name != NULL ) {
        /* put in appropriate group */
        group = GetGroup( group_name );
        AddToGroup( group, sdata->u.leader );
    }
    return sdata;
}

static void NearAllocCommunal( symbol *sym, unsigned size )
/*********************************************************/
{
    sym->p.seg = GetSegment( CommunalSegName, BSSClassName, DataGrpName,
                                     2, COMBINE_ADD, !IS_SYM_COMM32(sym) );
    sym->p.seg->length = size;
}

static void FarAllocCommunal( symbol *sym, unsigned size )
/********************************************************/
{
    segdata *   seg;
    segdata *   first;

    first = NULL;
    for(;;) {
        seg = GetSegment( sym->name, FarDataClassName, NULL,
                          0, COMBINE_INVALID, !IS_SYM_COMM32(sym) );
        if( first == NULL ) first = seg;
        if( size < MAX_SEGMENT ) {
            seg->length = size;
            break;
        } else {
            seg->length = MAX_SEGMENT;
            size -= MAX_SEGMENT;
        }

⌨️ 快捷键说明

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