distrib.c

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

C
553
字号
    while( !(list->ovl_num & SECT_VISITED ) ) {
        list = list->parent;
    }
    while( sect != NULL ) {
        sect->ovl_num &= ~SECT_VISITED;
        sect = sect->parent;
    }
    return( list->ovl_num );
}

extern void DefDistribSym( symbol * sym )
/***************************************/
/* move current module based on where this symbol has been referenced from,
 * and make the symbol point to the current module. All symbols which get
 * passed to this routine are in an overlay class. */
{
    arcdata *   arcs;
    segdata *   seg;

    if( sym->info & SYM_REFERENCED ) {
        arcs = CurrMod->x.arclist;
        if( CurrMod->modinfo & MOD_FIXED ) {
            seg = sym->p.seg;
            if( seg->iscode ) {      // if code..
                NewRefVector( sym, sym->u.d.ovlref, arcs->ovlref );
            } else if( !( sym->u.d.ovlstate & OVL_FORCE ) ) {
                // don't generate a vector.
                sym->u.d.ovlstate |= OVL_FORCE | OVL_NO_VECTOR;
            }
        } else {
            if( arcs->ovlref == NO_ARCS_YET ) {
                arcs->ovlref = sym->u.d.ovlref;
            } else {
                arcs->ovlref = LowestAncestor( arcs->ovlref,
                                               SectOvlTab[sym->u.d.ovlref] );
            }
        }
    }
    sym->u.d.modnum = CurrModHandle;
}

static void AddArc( dist_arc arc )
/********************************/
/* add an arc to the arclist for the current module */
{
    arcdata *   arclist;

    arclist = CurrMod->x.arclist;
    if( arclist->numarcs >= ArcBufLen ) {
        _ChkAlloc( arclist, sizeof(arcdata)
                             + (ArcBufLen * 2 - 1) * sizeof(dist_arc) );
        memcpy( arclist, ArcBuffer, sizeof(arcdata)
                                       + (ArcBufLen-1) * sizeof(dist_arc));
        _LnkFree( ArcBuffer );
        CurrMod->x.arclist = arclist;
        ArcBuffer = arclist;
        ArcBufLen *= 2;
    }
    arclist->arcs[arclist->numarcs] = arc;
    arclist->numarcs++;
}

static bool NotAnArc( dist_arc arc )
/**********************************/
/* return TRUE if this is not an arc in the current module */
{
    unsigned    index;
    arcdata *   arclist;

    arclist = CurrMod->x.arclist;
    index = arclist->numarcs;
    while( index != 0 ) {
        index--;
        if( arclist->arcs[index].test == arc.test ) {
            return( FALSE );
        }
    }
    return( TRUE );
}

extern void RefDistribSym( symbol * sym )
/***************************************/
/* add an arc to the reference graph if it is not already in the graph */
{
    mod_entry * mod;
    segdata *   seg;
    dist_arc    arc;

    arc.sym = sym;
    if( sym->info & SYM_DEFINED ) {
        if( sym->info & SYM_DISTRIB ) {
            mod = ModTable[ sym->u.d.modnum ];
            if( mod->modinfo & MOD_FIXED ) {        // add reference, as long
                seg = sym->p.seg;                   // as it is a code ref.
                if( seg->iscode ) {
                    AddArc( arc );
                }
            } else {
                arc.test = sym->u.d.modnum;
                if( NotAnArc( arc ) && ( sym->u.d.modnum != CurrModHandle ) ) {
                    AddArc( arc );
                }
            }
        } else if( ( sym->u.d.ovlstate & OVL_VEC_MASK ) == OVL_UNDECIDED ) {
            if( NotAnArc( arc ) ) {
                AddArc( arc );
            }
        }
    } else {   // just a reference, so it has to be added to the call graph.
        AddArc( arc );
    }
}

static bool NewRefVector( symbol *sym, unsigned_16 ovlnum,
                                                   unsigned_16 sym_ovlnum )
/*************************************************************************/
/* sometimes there can be an overlay vector generated to a routine specified
 * in an .OBJ file caused by a call from a library routine. this checks for
 * this case.*/
{
    if( ( sym->p.seg == NULL )
        || ( ( sym->u.d.ovlstate & OVL_VEC_MASK ) != OVL_UNDECIDED ) ) {
        return( TRUE );
    }
/*
 * at this point, we know it has already been defined, but does not have an
 * overlay vector, and is not data
*/
    if( LowestAncestor( sym_ovlnum, SectOvlTab[ ovlnum ] ) != sym_ovlnum ) {
        Vectorize( sym );
        return( TRUE );
    }
    return( FALSE );
}

static void DoRefGraph( unsigned_16 ovlnum, mod_entry * mod )
/***********************************************************/
/* checks to see if the mod has changed position, and if it has, check all
 * of the routines that mod references */
{
    arcdata *   arcs;
    unsigned_16 ancestor;

    arcs = mod->x.arclist;
/*
 * this next line is necessary to break cycles in the graph.
*/
    if( ( mod->modinfo & MOD_VISITED ) && ( ovlnum == arcs->ovlref )
        || ( mod->modinfo & MOD_FIXED ) )
        return;
    if( arcs->ovlref == NO_ARCS_YET ) {
        arcs->ovlref = 0;
        ancestor = 0;
        ScanArcs( mod );
    } else {
        ancestor = LowestAncestor( ovlnum, SectOvlTab[arcs->ovlref] );
        if( ancestor != arcs->ovlref ) {
            arcs->ovlref = ancestor;
            ScanArcs( mod );
        }
    }
    if( ancestor == 0 ) {   // it's at the root, so pull it out of the graph
        arcs->numarcs = 0;
    }
}

static void DeleteArc( arcdata *arc, unsigned_16 index )
/******************************************************/
/* delete an arc from the specified arc list */
{
    arc->numarcs--;
    if( arc->numarcs > 0 ) {
        arc->arcs[index] = arc->arcs[arc->numarcs];
    }
}

static void ScanArcs( mod_entry *mod )
/************************************/
/* go through all modules referenced by mod, and see if they need to change
 * position because of the position of mod */
{
    arcdata *   arcs;
    symbol *    sym;
    mod_entry * refmod;
    unsigned_16 index;
    unsigned_16 ovlnum;
    dist_arc    currarc;

    mod->modinfo |= MOD_VISITED;
    arcs = mod->x.arclist;
    ovlnum = arcs->ovlref;
    if( ovlnum != NO_ARCS_YET ) {
        index = arcs->numarcs;
        while( index > 0 ) {
            index--;
            currarc = arcs->arcs[index];
            if( currarc.test <= MAX_NUM_MODULES ) {     // GIANT KLUDGE!
                DoRefGraph( ovlnum, MOD_DEREF( currarc.mod ) );
            } else {
                sym = currarc.sym;
                if( sym->info & SYM_DEFINED ) {
                    if( sym->info & SYM_DISTRIB ) {
                        currarc.test = sym->u.d.modnum;
                        refmod = MOD_DEREF( currarc.mod );
                        if( refmod->modinfo & MOD_FIXED ) {
                            if( NewRefVector( sym, ovlnum,
                                              refmod->x.arclist->ovlref ) ) {
                                DeleteArc( arcs, index );
                            }
                        } else {
                            DoRefGraph( ovlnum, refmod );
                            if( !NotAnArc( currarc ) ) {
                                DeleteArc( arcs, index );
                            } else {
                                arcs->arcs[index] = currarc;
                            }
                        }
                    } else {
                        if( ( sym->p.seg == NULL )
                            || NewRefVector( sym, ovlnum,
                               sym->p.seg->u.leader->class->section->ovl_num ) ) {
                            DeleteArc( arcs, index );
                        }
                    }
                } else {
                    if( !( sym->u.d.ovlstate & OVL_REF ) ) {
                        sym->u.d.ovlref = ovlnum;
                        sym->u.d.ovlstate |= OVL_REF;
                    } else {
                        sym->u.d.ovlref = LowestAncestor( ovlnum,
                                                 SectOvlTab[sym->u.d.ovlref] );
                    }
                }
            } /* if (a module) */
        } /* while (arcs left)*/
    } /* if (an ovlnum defined) */
    mod->modinfo &= ~MOD_VISITED;
}

extern void FinishArcs( mod_entry *mod )
/**************************************/
/* check the position of the modules referenced by mod, and then make a
 * more permanent copy of the arclist for this module. */
{
    arcdata *   newarcs;
    unsigned    allocsize;

    ScanArcs( mod );
    if( mod->modinfo & MOD_FIXED ) {    // no need to scan a fixed module
        mod->x.arclist->numarcs = 0;        // more than once
    }
    allocsize = mod->x.arclist->numarcs * sizeof(dist_arc)
                                 + sizeof(arcdata) - sizeof(dist_arc);
    _Pass1Alloc( newarcs, allocsize );
    memcpy( newarcs, mod->x.arclist, allocsize );
    mod->x.arclist = newarcs;
}

extern void DistIndCall( symbol *sym )
/************************************/
// handle indirect calls and their effect on distributed libs.
{
    arcdata *   arcs;
    unsigned_16 ovlsave;

    arcs = CurrMod->x.arclist;
    ovlsave = arcs->ovlref;
    arcs->ovlref = 0;           // make sure current module isn't
    CurrMod->modinfo |= MOD_VISITED;        // visited
    DoRefGraph( 0, MOD_DEREF( sym->u.d.modnum ) );
    CurrMod->modinfo &= ~MOD_VISITED;
    arcs->ovlref = ovlsave;
    sym->u.d.ovlstate |= OVL_REF;
    sym->u.d.ovlref = 0;        // make sure current symbol put in root.
}

⌨️ 快捷键说明

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