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 + -
显示快捷键?