cgiobuff.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 817 行 · 第 1/2 页
C
817 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "memmgr.h"
#include "errdefns.h"
#include "cgiobuff.h"
#include "ring.h"
#include "iosupp.h"
#include "fname.h"
#include "toggle.h"
#include "dbg.h"
#include "icodes.h"
#include "stats.h"
#include "cgdata.h"
#include "icopmask.h"
#include "stringl.h"
#include "conpool.h"
#include "pcheader.h"
#define CGIOBUFF_CHECK (-(sizeof(CGIOBUFF)|1))
// This must be free at bottom of a block for that block to be re-used
// for another virtual file
#define MAX_REUSE ( sizeof( CGINTER ) * 8 + sizeof( BUFF_XFER ) )
// maximum capacity of a buffer before an IC_NEXT instruction is req'd
#define MAX_WRITE_AMT ( TMPBLOCK_BSIZE - sizeof( BUFF_XFER ) - sizeof( CGINTER ) )
#ifndef NDEBUG
#define DICT_SIZE 4
#include "pragdefn.h"
#else
#define DICT_SIZE 128
#endif
typedef struct buff_dict BUFFDICT;
struct buff_dict {
BUFFDICT *next;
CGIOBUFF *dict[DICT_SIZE];
};
static BUFFDICT *directoryOfBufs;
static unsigned maxDictIndex;
static CGIOBUFF *allBufs;
static CGIOBUFF *reusableBufs;
static CGIOBUFF *beingWritten; // NULL or the one being written
static icop_mask icMaskTable[] = {
#include "ic_mask.gh"
};
// defines ic_op_type ICOpTypes[]
#include "itypvec.h"
#define doReadOpNUL NULL
#define doReadOpBIN NULL
#define doReadOpCON ConstantPoolMapIndex
#define doReadOpSYM SymbolMapIndex
#define doReadOpSTR StringMapIndex
#define doReadOpTYP TypeMapIndex
#define doReadOpSCP ScopeMapIndex
#define doReadOpSRC SrcFileMapIndex
static CGIRELOCFN *relocReadOperand[] = {
#define ITYPE( typ ) ((CGIRELOCFN*) doReadOp##typ)
#include "itypes.h"
};
ExtraRptCtr( ctr_buffers ); // counts buffers
ExtraRptCtr( ctr_usage ); // counts bytes used in buffers
typedef struct { // disk transfer code
CGINTER leap_ins; // - IC_NEXT (value.uvalue has disk block)
DISK_OFFSET offset; // - disk offset
} BUFF_XFER;
#define pointXferOffset( ctl, off ) ( (void*)( (ctl)->data + (off)) )
#define pointXfer( ctl ) ( (void*)( (ctl)->data + (ctl)->free_offset) )
static BUFFDICT *newDict( void )
{
BUFFDICT *dict;
dict = CPermAlloc( sizeof( *dict ) );
memset( dict, 0, sizeof( *dict ) );
dict->next = directoryOfBufs;
directoryOfBufs = dict;
++maxDictIndex;
return( dict );
}
static void addDirectoryEntry( CGIOBUFF *e )
{
unsigned dict_index;
unsigned dict_offset;
BUFFDICT *dict;
dict_index = e->disk_addr / DICT_SIZE;
dict_offset = e->disk_addr % DICT_SIZE;
DbgAssert( dict_index <= (maxDictIndex + 1) );
dict = directoryOfBufs;
if( dict_index != maxDictIndex ) {
dict = newDict();
}
dict->dict[ dict_offset ] = e;
}
static CGIOBUFF **findDirectoryEntry( DISK_ADDR disk_addr )
{
unsigned dict_index;
unsigned dict_offset;
unsigned i;
BUFFDICT *dict;
dict_index = disk_addr / DICT_SIZE;
dict_offset = disk_addr % DICT_SIZE;
DbgAssert( dict_index <= maxDictIndex );
dict = directoryOfBufs;
i = maxDictIndex;
for(;;) {
if( i == dict_index ) break;
DbgAssert( i != 0 );
--i;
dict = dict->next;
DbgAssert( dict != NULL );
}
return( &(dict->dict[ dict_offset ]) );
}
static void setDirectoryEntry( DISK_ADDR disk_addr, CGIOBUFF *e )
{
CGIOBUFF **dict;
dict = findDirectoryEntry( disk_addr );
*dict = e;
}
static void addToReuseList( // ADD BUFFER TO REUSE LIST (IF IT CAN BE REUSED)
CGIOBUFF *ctl ) // - buffer control
{
CGIOBUFF *head;
CGIOBUFF *head_next;
if( ctl->reuse_next != NULL ) {
return;
}
if( ctl->writing ) {
return;
}
if( ctl->free_offset > ( TMPBLOCK_BSIZE - MAX_REUSE ) ) {
return;
}
if( reusableBufs != NULL ) {
head = reusableBufs;
head_next = head->reuse_next;
// insert between 'head' and 'head_next'
ctl->reuse_prev = head;
ctl->reuse_next = head_next;
head_next->reuse_prev = ctl;
head->reuse_next = ctl;
} else {
ctl->reuse_prev = ctl;
ctl->reuse_next = ctl;
reusableBufs = ctl;
}
}
static void removeFromReuseList(// DETACH BUFFER FROM REUSE LIST
CGIOBUFF *ctl ) // - buffer control
{
CGIOBUFF *prev;
CGIOBUFF *next;
DbgAssert( ctl->reuse_next != NULL );
DbgAssert( ctl->reuse_prev != NULL );
prev = ctl->reuse_prev;
next = ctl->reuse_next;
prev->reuse_next = next;
next->reuse_prev = prev;
if( reusableBufs == ctl ) {
if( prev == next ) {
reusableBufs = NULL;
} else {
reusableBufs = prev;
}
}
// must be here in case 'prev' == 'next'
ctl->reuse_prev = NULL;
ctl->reuse_next = NULL;
}
static CGIOBUFF *allocateBuffer(// ALLOCATE A NEW BUFFER
DISK_ADDR block ) // - block number
{
CGIOBUFF *ctl; // - new buffer
ctl = CMemAlloc( sizeof( *ctl ) );
ctl->next = NULL;
ctl->reuse_prev = NULL;
ctl->reuse_next = NULL;
ctl->disk_addr = block;
ctl->free_offset = 0;
ctl->reading = 0;
ctl->written = FALSE;
ctl->writing = FALSE;
ctl->active = FALSE;
DbgStmt( ctl->check = CGIOBUFF_CHECK );
RingAppend( &allBufs, ctl );
ExtraRptIncrementCtr( ctr_buffers );
return ctl;
}
static CGIOBUFF *findWrBuffer( // FIND A BUFFER FOR WRITING
void )
{
CGIOBUFF *ctl; // - buffer control
DISK_ADDR block; // - block number
ctl = reusableBufs;
if( ctl != NULL ) {
removeFromReuseList( ctl );
} else {
block = IoSuppTempNextBlock( 1 );
ctl = allocateBuffer( block );
addDirectoryEntry( ctl );
}
ctl->active = TRUE;
ctl->writing = TRUE;
ctl->written = FALSE;
DbgAssert( ctl->check == CGIOBUFF_CHECK );
return( ctl );
}
static CGIOBUFF *findRdBuffer( // FIND A BUFFER FOR READING
DISK_ADDR block ) // - disk block
{
CGIOBUFF *ctl;
CGIOBUFF **dict;
dict = findDirectoryEntry( block );
ctl = *dict;
if( ctl == NULL ) {
ctl = allocateBuffer( block );
setDirectoryEntry( block, ctl );
IoSuppTempRead( block, TMPBLOCK_BSIZE, ctl->data );
ctl->written = TRUE;
ctl->free_offset = TMPBLOCK_BSIZE;
}
ctl->active = TRUE;
++ctl->reading;
DbgAssert( ctl->check == CGIOBUFF_CHECK );
return ctl;
}
static void finishWrBuffer( // COMPLETE WRITE-USE OF A BUFFER
CGIOBUFF *ctl ) // - buffer control
{
DbgAssert( ctl->check == CGIOBUFF_CHECK );
ctl->writing = FALSE;
if( ctl->reading == 0 ) {
ctl->active = FALSE;
}
addToReuseList( ctl );
}
static void finishRdBuffer( // COMPLETE READ-USE OF A BUFFER
CGIOBUFF *ctl ) // - buffer control
{
DbgAssert( ctl->check == CGIOBUFF_CHECK );
-- ctl->reading;
if( ctl->reading == 0 && ! ctl->writing ) {
ctl->active = FALSE;
addToReuseList( ctl );
}
}
CGIOBUFF *CgioBuffWrOpen( // GET BUFFER FOR WRITING
void )
{
return findWrBuffer();
}
static CGIOBUFF *switchToNextBuffer( CGIOBUFF *ctl )
{
CGIOBUFF *next; // - next buffer control
BUFF_XFER *xfer; // - transfer record
next = findWrBuffer();
xfer = pointXfer( ctl );
xfer->leap_ins.opcode = IC_NEXT;
xfer->leap_ins.value.uvalue = next->disk_addr;
xfer->offset = next->free_offset;
ctl->free_offset += sizeof( BUFF_XFER );
finishWrBuffer( ctl );
return( next );
}
CGINTER *CgioBuffPCHRead( // READ FROM PCH AND WRITE INTO BUFFER
CGINTER *buff, // - alternate buffer for PCHReadLoc
CGIOBUFF **pctl ) // - addr( buffer control )
{
CGIRELOCFN *relocate; // - relocator function
CGINTER *p_instr; // - IC to process
CGINTER *s_instr; // - past last IC to process
CGIOBUFF *ctl; // - buffer control
CGINTER *start; // - first destination for IC
CGINTER *dest; // - destination for IC
CGINTER *stop; // - last destination for IC
unsigned opcode; // - IC opcode
#define CBP_LIMIT ( MAX_WRITE_AMT - CGINTER_BLOCKING * sizeof(CGINTER) )
ctl = *pctl;
start = pointXfer( ctl );
dest = start;
stop = pointXferOffset( ctl, CBP_LIMIT );
for(;;) {
if( dest >= stop ) {
ctl->free_offset += ((char*)dest) - (char*)start;
ctl = switchToNextBuffer( ctl );
start = pointXfer( ctl );
dest = start;
stop = pointXferOffset( ctl, CBP_LIMIT );
}
PCHReadLocSize( p_instr, buff, CGINTER_BLOCKING * sizeof( *p_instr ) );
s_instr = &p_instr[ CGINTER_BLOCKING ];
do {
opcode = p_instr->opcode;
if( icMaskTable[ opcode ] & ICOPM_PCHREAD ) {
ctl->free_offset += ((char*)dest) - (char*)start;
*pctl = ctl;
// rest of block can be ignored
#ifndef NDEBUG
{
CGINTER *c = p_instr + 1;
DbgAssert( c <= s_instr );
DbgAssert(( s_instr - c ) < CGINTER_BLOCKING );
while( c < s_instr ) {
DbgAssert( c->opcode == IC_PCH_PAD );
++c;
}
}
#endif
return( p_instr );
}
relocate = relocReadOperand[ ICOpTypes[ opcode ] ];
if( relocate != NULL ) {
dest->value.pvalue = (*relocate)( p_instr->value.pvalue );
} else {
dest->value = p_instr->value;
}
dest->opcode = opcode;
++dest;
++p_instr;
} while( p_instr < s_instr );
}
#undef CBP_LIMIT
}
CGVALUE CgioMapIndex( unsigned opcode, CGVALUE value )
/****************************************************/
{
ic_op_type op_class;
CGIRELOCFN *reloc;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?