segment.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,496 行 · 第 1/4 页
C
1,496 行
/****************************************************************************
*
* 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 "compcfg.h"
#include "tgtenv.h"
#include "cgfront.h"
#include "cgback.h"
#include "cgdata.h"
#include "codegen.h"
#include "ring.h"
#include "errdefns.h"
#include "vbuf.h"
#include "memmgr.h"
#include "pragdefn.h"
#include "cginfo.h"
#include "pcheader.h"
#include "dbgsupp.h"
#include "initdefs.h"
typedef struct pc_segment PC_SEGMENT;
PCH_struct pc_segment { // PC_SEGMENT -- segment on PC
PC_SEGMENT *next; // - next in ring
PC_SEGMENT *sibling; // - related segment
char *class_name; // - class name
SYMBOL label; // - symbol for label in segment
unsigned attrs; // - attributes
fe_seg_id seg_id; // - id for segment
target_offset_t align; // - alignment
target_size_t offset; // - offset within segment
#if _INTEL_CPU
hw_reg_set binding; // - register bound to the segment
#endif
// - segment:
unsigned dgroup : 1; // - is part of DGROUP
unsigned lab_gened : 1; // - label has been generated
unsigned used : 1; // - has been used
unsigned fixed_alignment : 1;// - has a fixed alignment (no changes)
unsigned cg_defed : 1; // - defined to code generator
unsigned module_prefix : 1; // - name has ModuleName as a prefix
unsigned has_data : 1; // - has data gened in segment
unsigned only_strings : 1; // - only strings go in segment
char name[1]; // - name
};
typedef struct { // DEF_SEG -- code/data default segments
PC_SEGMENT *pcseg; // - default pc segment
unsigned ctr; // - # of segments allocated
unsigned ds_used : 1; // - TRUE ==> has been used
} DEF_SEG;
static fe_seg_id seg_max; // last segment # used
static fe_seg_id seg_import; // next import segment #
#if _INTEL_CPU
static fe_seg_id seg_code_comdat; // segment # for code comdat
#endif
static fe_seg_id seg_default_code; // segment # for default code segment
static target_size_t dgroup_size; // amount of DGROUP used so far
static PC_SEGMENT *seg_list; // list of defined segments
static DEF_SEG code_def_seg; // code segment -- default info.
static DEF_SEG data_def_seg; // data segment -- default info.
static struct {
unsigned in_back_end : 1; // TRUE ==> now in CGBKMAIN
unsigned use_def_seg : 1; // TRUE ==> #pragma def_seg active
} flags;
enum // SEGMENT-ATTRIBUTE COMBINATIONS USED:
{ SGAT_CODE_BASED // - code: based
= GIVEN_NAME | INIT | GLOBAL | EXEC
, SGAT_CODE_GEN // - code: being generated
= GIVEN_NAME | INIT | GLOBAL | EXEC
, SGAT_DATA_BASED // - data: based
= GIVEN_NAME | GLOBAL | INIT | PRIVATE
, SGAT_STACK // - data: stack
= GIVEN_NAME | GLOBAL
, SGAT_DATA_CON1 // - data: constant(1)
= GIVEN_NAME | BACK | ROM | INIT
, SGAT_DATA_CON2 // - data: constant(2)
= GIVEN_NAME | ROM | INIT
, SGAT_DATA_RW // - data: read/write initialized
= GIVEN_NAME | GLOBAL | INIT
, SGAT_CPP // - used for common code
= GIVEN_NAME | GLOBAL | INIT | EXEC
, SGAT_BSS // - data: read/write uninitialized
= GIVEN_NAME | GLOBAL
, SGAT_DATA_PRIVATE_RW // - data: private read/write
= GIVEN_NAME | PRIVATE | INIT
, SGAT_DATA_PRIVATE_RO // - data: private read-only
= GIVEN_NAME | PRIVATE | INIT | ROM
, SGAT_DATA_COMMON_INIT // - data: common, init'ed, R/W
= GIVEN_NAME | GLOBAL | INIT | COMMON | COMDAT
, SGAT_DATA_COMMON_INIT_ROM // - data: common, init'ed, R/O
= GIVEN_NAME | GLOBAL | INIT | COMMON | COMDAT | ROM
, SGAT_DATA_COMMON_ZERO // - data: common, uninitialized
= GIVEN_NAME | GLOBAL | COMMON | COMDAT
, SGAT_TLS_LIMIT // - thread-local storage delimiter seg
= GIVEN_NAME | ROM | INIT | THREAD_LOCAL
, SGAT_TLS_DATA // - thread-local data
= GIVEN_NAME | GLOBAL | INIT | THREAD_LOCAL
};
enum {
SA_IN_DGROUP = 0x01,
SA_MODULE_PREFIX = 0x02,
SA_DEFINE_ANYTIME = 0x04,
SA_NULL = 0x00
};
enum {
ADS_MODULE_PREFIX = 0x01,
ADS_CONST_SEGMENT = 0x02,
ADS_STRING_SEGMENT = 0x04,
ADS_CODE_SEGMENT = 0x08,
ADS_ZM_SEGMENT = 0x10,
ADS_NULL = 0x00
};
#define _markUsed( s, v ) \
{ PC_SEGMENT *t = s, *p; \
t->used = v; \
for( p = t->sibling; p != t; p = p->sibling ) { \
p->used = v; \
} \
}
static void addSibling( PC_SEGMENT *seg, PC_SEGMENT *sib )
{
DbgAssert( sib->sibling == sib );
sib->sibling = seg->sibling;
seg->sibling = sib;
}
static SYMBOL segEmitLabel( // EMIT SEGMENT LABEL
PC_SEGMENT* seg ) // - current segment
{
SYMBOL label; // - label in segment
label = seg->label;
if( label != NULL && ! seg->lab_gened ) {
if( seg->seg_id == SEG_STACK ) {
CGAutoDecl( (cg_sym_handle)label, T_UINT_1 );
} else {
CgBackGenLabel( label );
}
seg->lab_gened = TRUE;
_markUsed( seg, TRUE );
}
return label;
}
static void checkSegmentOverflow( // CHECK FOR SEGMENTS OVERFLOW
void )
{
if( seg_max < 0 || seg_import >= 0 ) {
CFatal( "Too many segments -- sub-divide source module" );
}
}
static PC_SEGMENT *segIdLookup( // LOOKUP SEGMENT FOR ID
fe_seg_id seg_id ) // - segment id
{
PC_SEGMENT* curr; // - current segment
PC_SEGMENT* retn; // - segment for id
retn = NULL;
RingIterBeg( seg_list, curr ) {
if( curr->seg_id == seg_id ) {
retn = curr;
break;
}
} RingIterEnd( curr );
return retn;
}
#if _CPU == _AXP || COMP_CFG_COFF == 1
static fe_seg_id markSegmentComdat( // MARK SEGMENT AS COMDAT SEGMENT
fe_seg_id seg_id ) // - segment id
{
PC_SEGMENT* seg = segIdLookup( seg_id );
DbgVerify( NULL != seg, "markSegmentComdat -- no segment" );
seg->attrs |= COMDAT;
return( seg_id );
}
#endif
static PC_SEGMENT *segNameLookup( // LOOKUP SEGMENT FOR NAME
char *name ) // - segment name
{
PC_SEGMENT* curr; // - current segment
PC_SEGMENT* retn; // - segment for id
retn = NULL;
RingIterBeg( seg_list, curr ) {
if( 0 == strcmp( curr->name, name ) ) {
retn = curr;
break;
}
} RingIterEnd( curr );
return retn;
}
static void segmentCgDefine( // DEFINE A SEGMENT
PC_SEGMENT *segment ) // - current segment
{
if( ! segment->cg_defed ) {
BEDefSeg( segment->seg_id
, segment->attrs
, segment->name
, segment->align );
segment->cg_defed = TRUE;
}
}
static PC_SEGMENT *segmentAlloc( // SEGMENT: ALLOCATE NEW SEGMENT
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 ) // - control mask
{
PC_SEGMENT *curr; // - segment pointer
size_t size; // - size of segment name
#if _INTEL_CPU && COMP_CFG_COFF == 0
//alpha permits segments defined anywhere and we need it for comdat data
//ditto for COFF
DbgVerify( ! flags.in_back_end || ( attrs & PRIVATE ) || ( control & SA_DEFINE_ANYTIME )
, "segmentAlloc -- defining in back end" );
#endif
size = strlen( seg_name );
curr = RingAlloc( &seg_list, sizeof( PC_SEGMENT ) + size );
curr->sibling = curr;
stvcpy( curr->name, seg_name, size );
curr->offset = 0;
curr->dgroup = (( control & SA_IN_DGROUP ) != 0 );
curr->lab_gened = FALSE;
if( class_name != NULL ) {
curr->class_name = strpermsave( class_name );
} else {
curr->class_name = NULL;
}
curr->used = FALSE;
curr->module_prefix = (( control & SA_MODULE_PREFIX ) != 0 );
curr->fixed_alignment = FALSE;
curr->cg_defed = FALSE;
curr->has_data = FALSE;
curr->only_strings = FALSE;
curr->label = NULL;
curr->attrs = attrs;
#if _INTEL_CPU
HW_CAsgn( curr->binding, HW_EMPTY );
#endif
if( seg_id == SEG_NULL ) {
seg_id = ++seg_max;
checkSegmentOverflow();
} else {
if( seg_id > seg_max ) {
seg_max = seg_id;
checkSegmentOverflow();
}
}
curr->seg_id = seg_id;
switch( seg_id ) {
case SEG_PROF_BEG:
case SEG_PROF_REF:
case SEG_PROF_END:
// we don't want padding introduced
curr->align = TARGET_LONG;
// we don't want alignment changed either
curr->fixed_alignment = TRUE;
break;
case SEG_INIT_BEG:
case SEG_INIT_REF:
case SEG_INIT_END:
case SEG_FINI_BEG:
case SEG_FINI_REF:
case SEG_FINI_END:
// we don't want padding introduced
#if _INTEL_CPU
curr->align = TARGET_SHORT;
#elif _CPU == _AXP
curr->align = TARGET_POINTER;
#else
#error no alignment set
#endif
// we don't want alignment changed either
curr->fixed_alignment = TRUE;
break;
default:
curr->align = TARGET_CHAR;
if( flags.in_back_end ) {
segmentCgDefine( curr );
}
break;
}
return( curr );
}
static void initDefSeg( // SET NEW DEFAULT SEGMENT INFO
DEF_SEG *def_seg, // - default segment info.
PC_SEGMENT *pcseg ) // - default segment
{
if( def_seg->pcseg != pcseg ) {
def_seg->pcseg = pcseg;
def_seg->ctr = 0;
def_seg->ds_used = FALSE;
}
}
static void pruneDefSeg( // PRUNE A DEFAULT SEGMENT IF NOT USED
DEF_SEG *def_seg ) // - default segment info.
{
PC_SEGMENT *pcseg; // - pc segment for default
if( ! def_seg->ds_used ) {
pcseg = def_seg->pcseg;
if( pcseg != NULL && ! pcseg->used ) {
RingDealloc( &seg_list, pcseg );
}
}
}
static PC_SEGMENT *addDefSeg( // ADD A DEFAULT PC SEGMENT
DEF_SEG *def_seg, // - default segment info.
unsigned ads_control ) // - control mask
{
unsigned attrs; // - attributes for segment
PC_SEGMENT *curr; // - segment pointer
VBUF seg_name; // - virtual buffer for name
unsigned sa_control; // - segmentAlloc control mask
VbufInit( &seg_name );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?