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