segment.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,496 行 · 第 1/4 页
C
1,496 行
VStrNull( &seg_name );
++def_seg->ctr;
sa_control = SA_NULL;
if( ads_control & ADS_MODULE_PREFIX ) {
if(( ads_control & ADS_CODE_SEGMENT ) == 0 && DataSegName[0] != '\0' ) {
VStrConcStr( &seg_name, DataSegName );
} else {
VStrConcStr( &seg_name, ModuleName );
}
sa_control |= SA_MODULE_PREFIX;
}
if( ads_control & ADS_STRING_SEGMENT ) {
sa_control |= SA_DEFINE_ANYTIME;
}
VStrConcStr( &seg_name, def_seg->pcseg->name );
if( ads_control & ADS_ZM_SEGMENT ) {
VStrConcDecimal( &seg_name, def_seg->ctr );
}
if( def_seg == &code_def_seg ) {
attrs = SGAT_CODE_GEN;
} else {
if( ads_control & ADS_CONST_SEGMENT ) {
attrs = SGAT_DATA_PRIVATE_RO;
} else {
attrs = SGAT_DATA_PRIVATE_RW;
}
VStrConcDecimal( &seg_name, def_seg->ctr );
}
curr = segmentAlloc( seg_name.buf, NULL, SEG_NULL, attrs, sa_control );
if( 0 == ( attrs & EXEC ) ) {
_markUsed( curr, TRUE );
}
if( ads_control & ADS_STRING_SEGMENT ) {
curr->only_strings = TRUE;
}
VbufFree( &seg_name );
return( curr );
}
static
target_size_t segmentTypeSize( // SEGMENT: SIZE OF TYPE
TYPE type ) // - type to be sized
{
target_size_t size;
size = CgMemorySize( type );
if( size == 0 ) {
size = TARGET_CHAR;
}
return( size );
}
target_offset_t SegmentAlignment( // SEGMENT: ALIGNMENT FOR SYMBOL
SYMBOL sym ) // - symbol to align
{
target_offset_t align;
TYPE type;
TYPE align_type;
if( CompFlags.dont_align_segs ) {
return( TARGET_CHAR );
}
#if _CPU == _AXP
if( PackAmount != TARGET_CHAR ) {
#else
if( OptSize <= 50 || PackAmount != TARGET_CHAR ) {
#endif
type = sym->sym_type;
align_type = AlignmentType( type );
align = segmentTypeSize( align_type );
if( align == TARGET_CHAR ) {
// no alignment; let PackAlignment know the real size
align = segmentTypeSize( type );
}
align = PackAlignment( TARGET_MAX_PACKING, align );
} else {
align = TARGET_CHAR;
}
return( align );
}
target_offset_t SegmentAdjust( // SEGMENT: ADJUST OFFSET TO ALIGN
fe_seg_id segid, // - segment identifier
target_size_t offset, // - current offset
target_offset_t align ) // - required aligment
{
target_size_t calc_offset;
target_offset_t adjust;
switch( segid ) {
case SEG_INIT_BEG:
case SEG_INIT_REF:
case SEG_INIT_END:
case SEG_FINI_BEG:
case SEG_FINI_REF:
case SEG_FINI_END:
/* no padding in these segments */
return( 0 );
}
calc_offset = offset;
calc_offset += align - 1;
calc_offset &= ~(((target_size_t) align ) - 1 );
adjust = calc_offset - offset;
_CHECK_ADJUST( adjust, calc_offset, offset );
return( adjust );
}
struct seg_look { // used to lookup segments
const char *seg_name; // - segment name
const char *class_name; // - segment class name
unsigned attrs; // - attributes
fe_seg_id seg_id; // - id for segment
target_offset_t align; // - segment alignment
target_size_t sym_size; // - space needed for symbol
target_size_t sym_align; // - alignment needed for symbol
unsigned use_seg_id : 1; // - for lookup
unsigned use_attrs : 1; // - for lookup
unsigned use_align : 1; // - for lookup
unsigned use_sym_size_align : 1; // - for lookup
unsigned use_name : 1; // - for lookup
unsigned use_only_strings : 1; // - for lookup
};
static boolean same_segment( // DETERMINE IF SAME SEGMENT
void * _curr, // - current segment
const void * _lk ) // - segment lookup structure
{
PC_SEGMENT *curr = _curr;
const struct seg_look* lk = _lk;
target_offset_t align_adjust;
target_size_t new_offset;
if( lk->use_seg_id && lk->seg_id != SEG_NULL && curr->seg_id != lk->seg_id ) {
return( FALSE );
}
if( lk->use_attrs && curr->attrs != lk->attrs ) {
return( FALSE );
}
if( lk->use_align && curr->align != lk->align ) {
return( FALSE );
}
if( lk->use_sym_size_align ) {
align_adjust = SegmentAdjust( curr->seg_id, curr->offset, lk->sym_align );
new_offset = curr->offset + align_adjust + lk->sym_size;
_CHECK_ADJUST( new_offset, new_offset, curr->offset );
if( new_offset == 0 ) {
return( FALSE );
}
}
if( lk->use_name ) {
if( strcmp( curr->name, lk->seg_name ) != 0 ) {
return( FALSE );
}
if( curr->class_name != NULL ) {
if( lk->class_name == NULL ) {
return( FALSE );
}
if( strcmp( curr->class_name, lk->class_name ) != 0 ) {
return( FALSE );
}
} else {
if( lk->class_name != NULL ) {
return( FALSE );
}
}
}
if( lk->use_only_strings && !curr->only_strings ) {
return( FALSE );
}
return( TRUE );
}
static PC_SEGMENT *segmentDefine(// SEGMENT: DEFINE IF REQUIRED
const char *seg_name, // - segment name
const char *class_name, // - segment class name
fe_seg_id seg_id, // - segment id (if not SEG_NULL)
unsigned attrs, // - segment attributes
unsigned control ) // - segmentAlloc control mask
{
PC_SEGMENT *curr; // - current segment
struct seg_look lk; // - look-up structure
#if _INTEL_CPU
const char* pc_reg; // - scans register bound to segment
char pc_reg_name[8]; // - name of pc register
for( pc_reg = seg_name; ; ++pc_reg ) {
if( *pc_reg == '\0' ) {
pc_reg_name[0] = '\0';
break;
}
if( *pc_reg == ':' ) {
stvcpy( pc_reg_name, seg_name, pc_reg - seg_name );
seg_name = pc_reg + 1;
break;
}
}
#endif
lk.seg_id = seg_id;
lk.use_seg_id = TRUE;
lk.attrs = attrs;
lk.use_attrs = TRUE;
lk.use_align = FALSE;
lk.use_sym_size_align = FALSE;
lk.seg_name = seg_name;
lk.class_name = class_name;
lk.use_name = TRUE;
lk.use_only_strings = FALSE;
curr = RingLookup( seg_list, &same_segment, &lk );
if( curr == NULL ) {
curr = segmentAlloc( lk.seg_name, lk.class_name, lk.seg_id, lk.attrs, control );
#if _INTEL_CPU
if( pc_reg_name[0] != '\0' ) {
curr->binding = PragRegName( pc_reg_name );
}
#endif
}
return curr;
}
#if _CPU == 8086
static fe_seg_id createHugeSegment( target_size_t size, unsigned ads_control )
{
PC_SEGMENT *curr;
fe_seg_id id;
target_size_t used;
id = SEG_NULL;
while( size > 0 ) {
curr = addDefSeg( &data_def_seg, ads_control );
if( id == SEG_NULL ) {
id = curr->seg_id;
}
used = min( size, TARGET_UINT_MAX+1 );
curr->offset = used;
curr->align = 16;
_markUsed( curr, TRUE );
curr->has_data = TRUE;
size -= used;
}
return( id );
}
fe_seg_id SegmentAddHuge( // SEGMENT: ADD SYMBOL TO HUGE SEGMENT
target_size_t size ) // - size of symbol
{
return( createHugeSegment( size, ADS_MODULE_PREFIX ) );
}
fe_seg_id SegmentAddConstHuge( // SEGMENT: ADD CONST SYMBOL TO HUGE SEGMENT
target_size_t size ) // - size of symbol
{
return( createHugeSegment( size, ADS_MODULE_PREFIX | ADS_CONST_SEGMENT ) );
}
#else
fe_seg_id SegmentAddHuge( // SEGMENT: ADD SYMBOL TO HUGE SEGMENT
target_size_t size ) // - size of symbol
{
return( SegmentAddFar( size, 16 ) );
}
fe_seg_id SegmentAddConstHuge( // SEGMENT: ADD CONST SYMBOL TO HUGE SEGMENT
target_size_t size ) // - size of symbol
{
return( SegmentAddConstFar( size, 16 ) );
}
#endif
static void accumAlignment( PC_SEGMENT *curr, target_offset_t align )
{
if( ! curr->fixed_alignment ) {
curr->align = max( curr->align, align );
}
}
static fe_seg_id findFarSegment(// SEGMENT: ADD SYMBOL TO FAR SEGMENT
target_size_t size, // - size of symbol
target_offset_t align, // - alignment of symbol
unsigned ads_control ) // - addDefSeg control word
{
PC_SEGMENT *curr; // - new segment
struct seg_look lk; // - look-up structure
lk.use_seg_id = FALSE;
if( ads_control & ADS_CODE_SEGMENT ) {
lk.attrs = SGAT_CODE_BASED;
} else if( ads_control & ADS_CONST_SEGMENT ) {
lk.attrs = SGAT_DATA_PRIVATE_RO;
} else {
lk.attrs = SGAT_DATA_PRIVATE_RW;
}
lk.use_attrs = TRUE;
lk.use_align = FALSE;
lk.sym_size = size;
lk.sym_align = align;
lk.use_sym_size_align = TRUE;
lk.use_name = FALSE;
lk.use_only_strings = FALSE;
if( ads_control & ADS_STRING_SEGMENT ) {
lk.use_only_strings = TRUE;
}
curr = RingLookup( seg_list, &same_segment, &lk );
if( curr == NULL ) {
if( ads_control & ADS_CODE_SEGMENT ) {
curr = addDefSeg( &code_def_seg, ads_control );
code_def_seg.ds_used = TRUE;
} else {
curr = addDefSeg( &data_def_seg, ads_control );
data_def_seg.ds_used = TRUE;
}
}
curr->offset += SegmentAdjust( curr->seg_id, curr->offset, align );
curr->offset += size;
accumAlignment( curr, align );
_markUsed( curr, TRUE );
curr->has_data = TRUE;
return( curr->seg_id );
}
fe_seg_id SegmentAddFar( // SEGMENT: ADD SYMBOL TO FAR SEGMENT
target_size_t size, // - size of symbol
target_offset_t align ) // - alignment of symbol
{
return( findFarSegment( size, align, ADS_MODULE_PREFIX ) );
}
fe_seg_id SegmentAddConstFar( // SEGMENT: ADD CONST SYMBOL TO FAR SEGMENT
target_size_t size, // - size of symbol
target_offset_t align ) // - alignment of symbol
{
return( findFarSegment( size, align, ADS_MODULE_PREFIX | ADS_CONST_SEGMENT ) );
}
fe_seg_id SegmentAddStringConstFar(// SEGMENT: ADD CONST STRING TO FAR SEGMENT
target_size_t size, // - size of symbol
target_offset_t align ) // - alignment of symbol
{
return( findFarSegment( size, align,
ADS_MODULE_PREFIX |
ADS_CONST_SEGMENT |
ADS_STRING_SEGMENT ) );
}
fe_seg_id SegmentAddStringCodeFar(// SEGMENT: ADD CONST STRING TO CODE SEGMENT
target_size_t size, // - size of symbol
target_offset_t align ) // - alignment of symbol
{
return( findFarSegment( size, align,
ADS_CODE_SEGMENT |
ADS_STRING_SEGMENT ) );
}
fe_seg_id SegmentAddSym( // SEGMENT: ADD SYMBOL TO SPECIFIED SEGMENT
SYMBOL sym, // - sym to add
fe_seg_id id, // - id of segment to use
target_size_t size, // - size of sym
target_offset_t align ) // - alignment for sym
{
PC_SEGMENT *curr; // - new segment
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?