cgio.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 817 行 · 第 1/2 页
C
817 行
prev = RingPred( *a_old, element );
if( prev == NULL ) {
retn = FALSE;
} else {
RingPruneWithPrev( a_old, element, prev );
RingAppend( a_new, element );
retn = TRUE;
}
return retn;
}
void CgioFreeFile( // FREE A VIRTUAL FILE
CGFILE *ctl ) // - control for file
{
_dump( ctl, "free file" );
if( saveGenData( ctl ) ) {
freeGenData( ctl );
}
#if 0
RingPrune( &cg_file_ring, ctl );
CarveFree( carveCGFILE, ctl );
#else
if( ! changeRing( &cg_file_removed, ctl, &cg_file_ring ) ) {
#ifndef NDEBUG
int changed =
#endif
changeRing( &cg_file_removed, ctl, &cg_thunk_ring );
DbgVerify( changed, "CgioFreeFile -- could not free" );
}
#endif
}
void CgioWalkFiles( // WALK THRU FILES
void (*rtn) // - traversal routine
( CGFILE *curr ) ) // - - passed current file
{
CGFILE *curr;
RingIterBegSafe( cg_file_ring, curr ) {
(*rtn)( curr );
} RingIterEndSafe( curr )
}
void CgioThunkStash( // STASH AWAY A THUNK TO BE GEN'ED
CGFILE* thunk ) // - that thunk
{
#ifndef NDEBUG
int changed =
#endif
changeRing( &cg_thunk_ring, thunk, &cg_file_ring );
DbgVerify( changed, "CgioThunkStash -- could not stash" );
_dump( thunk, "stash thunk" );
}
void CgioThunkAddrTaken( // INDICATE ADDR TAKEN OF THUNK BY GEN'ED CODE
SYMBOL thunk ) // - a thunk
{
CGFILE* thunk_file; // - file for the thunk
ExtraRptIncrementCtr( cgio_locates_thunk );
thunk_file = CgioLocateFile( thunk );
if( thunk_file == NULL ) {
thunk_file = lookupFile( thunk, cg_thunk_ring );
}
if( thunk_file != NULL
&& thunk_file->thunk ) {
_dump( thunk_file, "thunk addr taken" );
CgioThunkMarkGen( thunk_file );
}
}
void CgioThunkMarkGen( // MARK THUNK TO BE GENERATED
CGFILE* thunk ) // - CGFILE for thunk symbol
{
_dump( thunk, "thunk marked to generate" );
DbgVerify( thunk != NULL, "CgioThunkMarkGen -- no thunk" );
thunk->refed = TRUE;
}
void CgioWalkThunks( // WALK THRU STASHED THUNKS
void (*rtn) // - traversal routine
( CGFILE *curr ) ) // - - passed current file
{
CGFILE *curr;
RingIterBegSafe( cg_thunk_ring, curr ) {
(*rtn)( curr );
} RingIterEndSafe( curr )
}
CGFILE *CgioLocateFile( // LOCATE LIVE FILE FOR A SYMBOL
SYMBOL sym ) // - symbol for file
{
ExtraRptIncrementCtr( cgio_locates );
return lookupFile( sym, cg_file_ring );
}
CGFILE* CgioLocateAnyFile( // LOCATE LIVE OR REMOVED FILE FOR A SYMBOL
SYMBOL sym ) // - the symbol
{
CGFILE* retn; // - the CGFILE for the symbol
retn = CgioLocateFile( sym );
if( retn == NULL ) {
retn = lookupFile( sym, cg_thunk_ring );
if( retn == NULL ) {
retn = lookupFile( sym, cg_file_removed );
}
}
return retn;
}
#define doWriteOpNUL NULL
#define doWriteOpBIN NULL
#define doWriteOpCON ConstantPoolGetIndex
#define doWriteOpSYM SymbolGetIndex
#define doWriteOpSTR StringGetIndex
#define doWriteOpTYP TypeGetIndex
#define doWriteOpSCP ScopeGetIndex
#define doWriteOpSRC SrcFileGetIndex
static CGIRELOCFN *relocWriteOperand[] = {
#define ITYPE( typ ) ((CGIRELOCFN*) doWriteOp##typ)
#include "itypes.h"
};
CGVALUE CgioGetIndex( unsigned opcode, CGVALUE value )
/****************************************************/
{
ic_op_type op_class;
CGIRELOCFN *reloc;
op_class = ICOpTypes[ opcode ];
reloc = relocWriteOperand[ op_class ];
if( reloc != NULL ) {
value.pvalue = reloc( value.pvalue );
}
return( value );
}
CGFILE *CGFileGetIndex( CGFILE *e )
{
return( CarveGetIndex( carveCGFILE, e ) );
}
CGFILE *CGFileMapIndex( CGFILE *e )
{
return( CarveMapIndex( carveCGFILE, e ) );
}
static void getCGFileLocn( CGIOBUFF *h, void *cursor, CGFILE_INS *p )
{
p->block = h->disk_addr;
p->offset = ((char*)cursor) - h->data;
}
static unsigned padOutICBlock( unsigned ics )
{
auto CGINTER pad_ic;
if(( ics % CGINTER_BLOCKING ) != 0 ) {
pad_ic.opcode = IC_PCH_PAD;
do {
++ics;
pad_ic.value.uvalue = ics;
PCHWriteUnaligned( &pad_ic, sizeof( pad_ic ) );
} while(( ics % CGINTER_BLOCKING ) != 0 );
}
return( ics );
}
static void saveCGFILE( void *e, carve_walk_base *d )
{
CGFILE *file = e;
SYMBOL fn_sym;
CGIOBUFF *h;
CGIOBUFF *stop_buffer;
CGINTER *cursor;
CGINTER *stop_cursor;
ic_op_type op_class;
unsigned opcode;
unsigned ics;
void *zap_reloc;
CGIRELOCFN *reloc;
auto CGINTER terminator;
auto CGINTER zap_ref;
auto CGFILE_INS zap_locn;
if( !file->write_to_pch
|| file->symbol == BRINF_SYMBOL ) {
return;
}
PCHWriteCVIndex( d->index );
fn_sym = SymbolGetIndex( file->symbol );
PCHWrite( &fn_sym, sizeof( fn_sym ) );
fn_sym = SymbolGetIndex( file->opt_retn );
PCHWrite( &fn_sym, sizeof( fn_sym ) );
PCHWriteUInt( file->flags );
h = CgioBuffRdOpen( file->first );
cursor = (CGINTER *) ( h->data + file->offset );
ics = 0;
if( file->done ) {
// CGFILE contains a finished function
for(;;) {
opcode = cursor->opcode;
op_class = ICOpTypes[ opcode ];
reloc = relocWriteOperand[ op_class ];
if( reloc != NULL ) {
void *save = cursor->value.pvalue;
cursor->value.pvalue = reloc( save );
PCHWriteUnaligned( cursor, sizeof( *cursor ) );
cursor->value.pvalue = save;
} else {
PCHWriteUnaligned( cursor, sizeof( *cursor ) );
}
++ics;
if( opcode == IC_EOF ) break;
h = CgioBuffReadIC( h, &cursor );
}
} else {
// CGFILE contains a function in progress
stop_buffer = file->buffer;
stop_cursor = (CGINTER *) ( stop_buffer->data + stop_buffer->free_offset );
// Ivan's bug fix simplified:
// if stop_cursor randomly contains an IC_NEXT opcode, the final
// CgioBuffRead may leap off into never-never land;
// since we can always write one more instruction, we simply
// make sure we have a benign opcode so that the following loop
// terminates properly (many thanks to Ivan for tracking this down!)
// Note: this is the only case where we are reading a CGFILE that
// is not terminated by an IC_EOF but the same precaution must be
// taken if we ever do it in some other case
stop_cursor->opcode = IC_NO_OP;
DbgAssert( stop_cursor->opcode != IC_NEXT );
for(;;) {
if( h == stop_buffer && cursor == stop_cursor ) break;
opcode = cursor->opcode;
// might be the destination of a CgioZap
zap_ref.opcode = IC_NO_OP;
switch( opcode ) {
case IC_BLOCK_OPEN:
case IC_BLOCK_DEAD:
getCGFileLocn( h, cursor, &zap_locn );
zap_reloc = ModuleIsZap2( &zap_locn );
if( zap_reloc != NULL ) {
zap_ref.opcode = IC_ZAP2_REF;
zap_ref.value.pvalue = zap_reloc;
}
break;
case IC_NO_OP:
getCGFileLocn( h, cursor, &zap_locn );
if( ModuleIsZap1( &zap_locn ) ) {
zap_ref.opcode = IC_ZAP1_REF;
zap_ref.value.ivalue = 0;
}
break;
}
op_class = ICOpTypes[ opcode ];
reloc = relocWriteOperand[ op_class ];
if( reloc != NULL ) {
void *save = cursor->value.pvalue;
cursor->value.pvalue = reloc( save );
PCHWriteUnaligned( cursor, sizeof( *cursor ) );
cursor->value.pvalue = save;
} else {
PCHWriteUnaligned( cursor, sizeof( *cursor ) );
}
++ics;
if( zap_ref.opcode != IC_NO_OP ) {
PCHWriteUnaligned( &zap_ref, sizeof( zap_ref ) );
++ics;
ics = padOutICBlock( ics );
}
h = CgioBuffReadIC( h, &cursor );
}
terminator.opcode = IC_PCH_STOP;
PCHWriteUnaligned( &terminator, sizeof( terminator ) );
++ics;
}
padOutICBlock( ics );
CgioBuffRdClose( h );
}
static void markFreeCGFILE( void *p )
{
CGFILE *c = p;
c->write_to_pch = FALSE;
}
pch_status PCHWriteCGFiles( void )
{
unsigned terminator = CARVE_NULL_INDEX;
CGFILE *curr;
auto carve_walk_base data;
CarveWalkAllFree( carveCGFILE, markFreeCGFILE );
RingIterBeg( cg_file_ring, curr ) {
curr->write_to_pch = TRUE;
} RingIterEnd( curr )
CarveWalkAll( carveCGFILE, saveCGFILE, &data );
PCHWriteCVIndex( terminator );
return( PCHCB_OK );
}
pch_status PCHReadCGFiles( void )
{
cv_index i;
unsigned opcode;
CGFILE *curr;
SYMBOL sym;
auto CGINTER instr[ CGINTER_BLOCKING ];
auto cvinit_t data;
CGINTER *p_instr;
CarveInitStart( carveCGFILE, &data );
for(;;) {
PCHLocateCVIndex( i );
if( i == CARVE_NULL_INDEX ) break;
curr = CarveInitElement( &data, i );
RingAppend( &cg_file_ring, curr );
sym = SymbolMapIndex( PCHReadPtr() );
initCGFILE( curr, sym );
curr->opt_retn = SymbolMapIndex( PCHReadPtr() );
curr->flags = PCHReadUInt();
for(;;) {
// The following comment is a trigger for the ICMASK program to
// start scanning for case IC_* patterns.
// ICMASK BEGIN PCHREAD (do not remove)
/* fake case labels for ICMASK program (do not remove)
case IC_PCH_STOP:
case IC_ZAP1_REF:
case IC_ZAP2_REF:
case IC_EOF:
*/
// ICMASK END (do not remove)
p_instr = CgioBuffPCHRead( instr, &(curr->buffer) );
opcode = p_instr->opcode;
if( opcode == IC_PCH_STOP ) break;
if( opcode == IC_EOF ) {
DbgAssert( ICOpTypes[ opcode ] == ICOT_NUL );
// this writes the IC_EOF into the buffer
CgioCloseOutputFile( curr );
break;
}
switch( opcode ) {
case IC_ZAP1_REF:
ModuleAdjustZap1( curr );
break;
case IC_ZAP2_REF:
ModuleAdjustZap2( curr, p_instr->value.pvalue );
break;
DbgDefault( "unexpected IC opcode during PCH read" );
}
}
}
return( PCHCB_OK );
}
pch_status PCHInitCGFiles( boolean writing )
{
cv_index n;
if( writing ) {
n = CarveLastValidIndex( carveCGFILE );
PCHWriteCVIndex( n );
n = CarveLastValidIndex( carveCGFILE_GEN );
PCHWriteCVIndex( n );
} else {
CGFILE *curr;
// shut down all pending functions so that the CGIOBUFF can stabilize
// to a point where there are no outstanding writes in progress
RingIterBeg( cg_file_ring, curr ) {
if( ! curr->done ) {
CgioCloseOutputFile( curr );
}
} RingIterEnd( curr )
cg_file_ring = NULL;
carveCGFILE = CarveRestart( carveCGFILE );
n = PCHReadCVIndex();
CarveMapOptimize( carveCGFILE, n );
carveCGFILE_GEN = CarveRestart( carveCGFILE_GEN );
n = PCHReadCVIndex();
CarveMapOptimize( carveCGFILE_GEN, n );
}
return( PCHCB_OK );
}
pch_status PCHFiniCGFiles( boolean writing )
{
if( ! writing ) {
CarveMapUnoptimize( carveCGFILE );
CarveMapUnoptimize( carveCGFILE_GEN );
}
return( PCHCB_OK );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?