wat2can1.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,387 行 · 第 1/3 页
C
1,387 行
hdl->d.reg.num_regs = 1;
hdl->d.reg.reg[ 0 ] = watReg2CanReg( loc_class & 0x0f );
break;
case WAT_IND_REG:
hdl = CanSNew( CANS_IND_REG );
hdl->d.indr.off = watReg2CanReg( get8() );
switch( loc_class & 0x0f ) {
case WAT_IR_CALLOC_NEAR:
hdl->d.indr.calloc = 1;
hdl->d.indr.far_ptr = 0;
break;
case WAT_IR_CALLOC_FAR:
hdl->d.indr.calloc = 1;
hdl->d.indr.far_ptr = 0;
hdl->d.indr.seg = watReg2CanReg( get8() );
break;
case WAT_IR_RALLOC_NEAR:
hdl->d.indr.calloc = 0;
hdl->d.indr.far_ptr = 0;
break;
case WAT_IR_RALLOC_FAR:
hdl->d.indr.calloc = 0;
hdl->d.indr.far_ptr = 1;
hdl->d.indr.seg = watReg2CanReg( get8() );
break;
default:
/**/ never_reach();
}
break;
default:
Fatal( MSG_CPP_EXTENSION );
}
return( hdl );
}
STATIC void symbOneVariable( uint_8 symb_class, name_handle *hdl ) {
symb_handle var_hdl;
switch( symb_class & 0x0f ) {
case WAT_VAR_MODULE:
var_hdl = CanSNew( CANS_MEM_LOC );
var_hdl->d.memloc.mem_hdl = getAddr32();
var_hdl->d.memloc.is_static = 1;
var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
*hdl = hdlName();
var_hdl->d.nat.name_hdl = *hdl;
headSymb = CanSIBefore( headSymb, var_hdl );
break;
case WAT_VAR_LOCAL:
/**/ never_reach();
break;
case WAT_VAR_MODULE_386:
var_hdl = CanSNew( CANS_MEM_LOC );
var_hdl->d.memloc.mem_hdl = getAddr48();
var_hdl->d.memloc.is_static = 1;
var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
*hdl = hdlName();
var_hdl->d.nat.name_hdl = *hdl;
headSymb = CanSIBefore( headSymb, var_hdl );
break;
default:
Fatal( MSG_CPP_EXTENSION );
}
/**/myassert( endOfRecord() );
}
STATIC void symbVariable( uint_8 symb_class ) {
name_handle garbage;
symbOneVariable( symb_class, &garbage );
}
STATIC int symbOneLocal( symb_handle block, name_handle *hdl ) {
/*
Assumes that block has no BLOCK_END or EPILOG yet
*/
uint_8 symb_class;
/**/myassert( block != NULL );
if( wat->ptr == wat->finish ) {
return( 0 );
}
symb_class = nextRec();
switch( symb_class & 0xf0 ) {
case WAT_VARIABLE:
splatRec( SPLAT_COUNT );
if( ( symb_class & 0x0f ) == WAT_VAR_LOCAL ) {
symb_handle var_hdl;
var_hdl = hdlLocation();
var_hdl->d.nat.type_hdl = mapIdx( getIndex() );
*hdl = hdlName();
var_hdl->d.nat.name_hdl = *hdl;
CanSIBefore( block, var_hdl );
} else {
symbOneVariable( symb_class, hdl );
}
/**/ myassert( endOfRecord() );
return( 1 );
break;
case WAT_CODE:
case WAT_NEW_BASE:
case SPLAT:
return( 0 );
break;
default:
/**/ never_reach();
return( 0 );
}
}
STATIC void symbParseLocals( symb_handle block, uint_8 num_parms ) {
/*
We need to give names to the parameters to a function. Unfortunately,
there is no direct provision for this in the WATCOM debugging info.
The following assumption is made:
name of parm 0 is name of last local
name of parm 1 is name of 2nd last local
...
name of parm num_parms-1 is name of (last-num_parms+1)st local
We'll keep track of num_parms locals in a vector. When done, we'll
flip the vector a few times and assign to the parms.
*/
name_handle *name_vec;
uint_8 cur_off;
symb_handle walk;
uint_8 walk_off;
/**/myassert( block != NULL && num_parms > 0 );
name_vec = alloca( num_parms * sizeof( name_handle ) );
for( cur_off = 0; cur_off < num_parms; ++cur_off ) {
name_vec[ cur_off ] = NAME_NULL;
}
cur_off = 0;
for(;;) {
if( symbOneLocal( block, name_vec + cur_off ) == 0 ) break;
++cur_off;
if( cur_off == num_parms ) {
cur_off = 0;
}
}
/* name_vec[ cur_off ] is the name of the last parm */
/* name_vec[ ( cur_off + 1 ) % num_parms ] is the name of the 2nd last... */
walk = CanSFwd( block );
walk_off = 0;
do {
if( cur_off == 0 ) {
cur_off = num_parms;
}
--cur_off;
/**/ myassert( walk->class == CANS_MEM_LOC ||
walk->class == CANS_BP_OFFSET ||
walk->class == CANS_REGISTER );
walk->d.nat.name_hdl = name_vec[ cur_off ];
walk = CanSFwd( walk );
++walk_off;
} while( walk_off < num_parms );
}
STATIC symb_handle symbCode( uint_8 symb_class ) {
symb_handle block; /* the block we are creating */
uint_16 parent_offset; /* offset of parent block in ddSymbols */
symb_handle parent_hdl; /* handle for parent block */
symb_handle work_hdl; /* a temporary working handle */
symb_handle prolog_hdl; /* handle for the prolog/ret_val */
uint_8 epilog_size; /* size of the epilog */
uint_8 num_parms; /* number of parameters in registers */
unsigned i; /* general counter */
int is32rec; /* is this one of the 32bit records? */
symb_handle parm_hdl;
cantype *blk_type;
proc_parm *parm_list; /* blk_type->d.proc.parms */
cantype *parm_type;
int_32 bp_offset;
block = offMapCur();
symb_class &= 0x0f;
switch( symb_class ) {
case WAT_CODE_BLOCK:
case WAT_CODE_NEAR_RTN:
case WAT_CODE_FAR_RTN:
is32rec = 0;
block->extra = get16();
block->d.block.size = get16();
break;
case WAT_CODE_BLOCK_386:
case WAT_CODE_NEAR_RTN_386:
case WAT_CODE_FAR_RTN_386:
is32rec = 1;
block->extra = get32();
block->d.block.size = get32();
break;
default:
Fatal( MSG_CPP_EXTENSION );
}
parent_offset = get16();
if( parent_offset != 0 ) {
parent_hdl = offMap( parent_offset );
block->d.block.start_offset = block->extra - parent_hdl->extra;
} else {
parent_hdl = CANS_NULL;
block->d.block.start_offset = block->extra;
}
prolog_hdl = CanSNew( CANS_PROLOG );
switch( symb_class ) {
case WAT_CODE_BLOCK:
case WAT_CODE_BLOCK_386:
num_parms = 0;
prolog_hdl->d.prolog.size = 0;
prolog_hdl->d.prolog.has_ret_val = 0;
prolog_hdl->d.prolog.has_ret_addr = 0;
prolog_hdl->d.prolog.ret_addr_offset = 0;
CanSIAfter( block, prolog_hdl );
epilog_size = 0;
break;
case WAT_CODE_NEAR_RTN:
case WAT_CODE_FAR_RTN:
case WAT_CODE_NEAR_RTN_386:
case WAT_CODE_FAR_RTN_386:
prolog_hdl->d.prolog.size = get8();
epilog_size = get8(); /* save for later */
prolog_hdl->d.prolog.has_ret_addr = 1;
if( is32rec ) {
bp_offset = get32();
} else {
bp_offset = (int_32)get16();
}
prolog_hdl->d.prolog.ret_addr_offset = bp_offset;
block->d.nat.type_hdl = mapIdx( getIndex() );
blk_type = CanTFind( block->d.nat.type_hdl );
/**/ myassert( blk_type == NULL || blk_type->class == CANT_PROCEDURE );
work_hdl = hdlLocation();
if( work_hdl != CANS_NULL ) {
CanSIAfter( prolog_hdl, work_hdl );
prolog_hdl->d.prolog.has_ret_val = 1;
} else {
prolog_hdl->d.prolog.has_ret_val = 0;
}
num_parms = get8();
/**/ myassert( blk_type == NULL ||
num_parms <= blk_type->d.proc.num_parms );
if( blk_type != NULL ) {
parm_list = blk_type->d.proc.parms;
} else {
parm_list = NULL;
}
for( i = 0; i < num_parms; ++i ) {
parm_hdl = hdlLocation();
CanSIBefore( block, parm_hdl );
if( parm_list != NULL ) {
parm_hdl->d.nat.type_hdl = parm_list[ i ].type;
}
}
/* note we need the value of i from above loop inside this if() {} */
num_parms = blk_type->d.proc.num_parms;
if( i < num_parms && blk_type != NULL ) {
/*
Now we have to build the stack-based parms, bp_offset was set
to the bp offset of the return address above. We add 2, 4, or 6
depending on near/far/386/386far
*/
switch( symb_class ) { /* note the major fall through! */
case WAT_CODE_FAR_RTN_386:
bp_offset += 2;
case WAT_CODE_NEAR_RTN_386:
case WAT_CODE_FAR_RTN:
bp_offset += 2;
case WAT_CODE_NEAR_RTN:
bp_offset += 2;
}
/**/ myassert( parm_list == blk_type->d.proc.parms );
for(;;) {
parm_hdl = CanSNew( CANS_BP_OFFSET );
CanSIBefore( block, parm_hdl );
parm_hdl->d.bpoff.offset = bp_offset;
parm_hdl->d.nat.type_hdl = parm_list[ i ].type;
parm_type = CanTFind( parm_hdl->d.nat.type_hdl );
++i;
if( i == num_parms ) break;
if( is32rec ) { /* determine positioning of next arg */
bp_offset += ( ( parm_type->size + 31 ) &~(int_32)31 ) / 8;
} else {
bp_offset += ( ( parm_type->size + 15 ) &~(int_32)15 ) / 8;
}
}
}
block->d.nat.name_hdl = hdlName();
CanSIBefore( block, prolog_hdl ); /* add the PROLOG */
break;
}
/**/myassert( endOfRecord() );
if( num_parms > 0 ) {
symbParseLocals( block, num_parms );
} else {
name_handle garbage;
while( symbOneLocal( block, &garbage ) ) {
/* nop */
}
}
wat->ptr = wat->start_rec;
wat->rec_len = 0;
/**/myassert( endOfRecord() );
work_hdl = CanSNew( CANS_EPILOG ); /* add the EPILOG */
work_hdl->d.epilog.size = epilog_size;
CanSIBefore( block, work_hdl );
work_hdl = CanSNew( CANS_BLOCK_END ); /* add the BLOCK_END */
work_hdl->d.end.start = block;
block->d.block.end = work_hdl;
CanSIBefore( block, work_hdl ); /* complete the block */
/* attach to parent or to headSymb as appropriate */
if( parent_hdl != CANS_NULL ) {
/**/ myassert( parent_hdl->class == CANS_BLOCK );
work_hdl = parent_hdl->d.block.end;
/**/ myassert( work_hdl != NULL );
/**/ myassert( work_hdl->class == CANS_BLOCK_END );
work_hdl = CanSBwd( work_hdl );
/**/ myassert( work_hdl->class == CANS_EPILOG );
CanSIBefore( work_hdl, block );
} else {
headSymb = CanSIBefore( headSymb, block );
}
return( block );
}
STATIC void symbNewBase( uint_8 symb_class ) {
symb_handle seg_hdl;
seg_hdl = CanSNew( CANS_CHANGE_SEG );
switch( symb_class & 0x0f ) {
case WAT_NB_ADD_PREV_SEG:
Fatal( MSG_ADD_PREV_SEG );
case WAT_NB_SET_BASE:
seg_hdl->d.cseg.seg = getAddr32();
break;
case WAT_NB_SET_BASE_386:
seg_hdl->d.cseg.seg = getAddr48();
break;
default:
/**/ never_reach();
}
headSymb = CanSIBefore( headSymb, seg_hdl );
}
STATIC void parseSymbol( void ) {
uint_8 symb_class;
symb_class = nextRec();
splatRec( SPLAT_COUNT );
switch( symb_class & 0xf0 ) {
case WAT_VARIABLE: symbVariable( symb_class ); break;
case WAT_CODE: symbCode( symb_class ); break;
case WAT_NEW_BASE: symbNewBase( symb_class ); break;
case SPLAT: wat->ptr += wat->rec_len - 2; break;
default:
/**/ never_reach();
}
/**/myassert( endOfRecord() );
}
void Wat2CanTandS( seghdr *dd_types, seghdr *dd_symbols ) {
/*******************************************************/
int index;
uint_8 *finish;
/* setup */
ddTypes = dd_types;
ddSymbols = dd_symbols;
headSymb = CANS_NULL;
unDefdType = CanTReserve();
stbHdl = MemAlloc( 128 * sizeof( type_handle ) );
for( index = 0; index < 128; ++index ) {
stbHdl[ index ] = unDefdType;
}
initTypeMap();
wat = MemAlloc( sizeof( *wat ) );
offsetMap = NULL;
if( dd_types != NULL ) {
/* parse types */
parsingTypes = 1;
wat->next = NULL;
wat->index = 1;
wat->start_rec = wat->ptr = ddTypes->data;
wat->rec_len = 0;
finish = ddTypes->data + ddTypes->alloc;
wat->finish = finish;
#ifndef NDEBUG
{
int fh;
fh = open( "debug.seg", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE|S_IREAD );
if( fh != -1 ) {
write( fh, ddTypes->data, ddTypes->alloc );
close( fh );
}
}
#endif
while( wat->ptr < finish ) {
parseType();
}
/**/ myassert( wat->next == NULL );
SegDetachData( ddTypes );
CanTMunge();
CanMisc.types_present = 1;
}
MemFree( stbHdl );
if( dd_symbols != NULL ) {
/* parse symbols */
parsingTypes = 0;
wat->next = NULL;
wat->index = 1;
wat->start_rec = wat->ptr = ddSymbols->data;
wat->rec_len = 0;
finish = ddSymbols->data + ddSymbols->alloc;
wat->finish = finish;
#ifndef NDEBUG
{
int fh;
fh = open( "symbols.seg", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IWRITE|S_IREAD );
if( fh != -1 ) {
write( fh, ddSymbols->data, ddSymbols->alloc );
close( fh );
}
}
#endif
while( wat->ptr < finish ) {
parseSymbol();
}
/**/ myassert( wat->next == NULL );
SegDetachData( ddSymbols );
CanSSetHead( headSymb );
CanMisc.symbs_present = 1;
}
/* cleanup */
destroyOffsetMap();
MemFree( wat );
finiTypeMap();
CanTReUse( unDefdType );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?