fnbody.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,160 行 · 第 1/5 页
C
2,160 行
FNLABEL *curr;
FNLABEL *new_label;
RingIterBeg( currFunction->labels, curr ) {
if( curr->name == name ) {
return( curr );
}
} RingIterEnd( curr )
new_label = RingCarveAlloc( carveFNLABEL, &currFunction->labels );
new_label->name = name;
new_label->block = currFunction->block_count;
new_label->defined = FALSE;
new_label->dangerous = FALSE;
new_label->destination.id = CgFrontLabelGoto();
new_label->destination.defn = LabelAllocLabDef();
if( PragToggle.unreferenced ) {
new_label->referenced = FALSE;
} else {
new_label->referenced = TRUE;
}
return( new_label );
}
static void parseLabels( void )
{
FNLABEL *label;
label = NULL;
for(;;) {
if( CurToken == T_ID ) {
LookPastName();
} else if( CurToken != T_SAVED_ID ) {
break;
}
if( LAToken != T_COLON ) break;
label = findLabel( SavedId );
if( label->defined ) {
CErr2p( ERR_LABEL_ALREADY_DEFINED, label->name );
InfMsgPtr( INF_PREVIOUS_LABEL, &label->destination.defn->locn );
} else {
label->defined = TRUE;
CgFrontLabdefGoto( label->destination.id );
LabelDefine( label->destination.defn );
}
currFunction->dead_code = FALSE;
nextYYToken();
nextYYToken();
}
if( label != NULL ) {
if( ( CurToken == T_RIGHT_BRACE )
|| ( CurToken == T_ALT_RIGHT_BRACE ) ) {
CErr1( ERR_STMT_REQUIRED_AFTER_LABEL );
}
}
}
static void parseIfStmt( void )
{
CSTACK *if_block;
ensureLiveCode();
if_block = beginControl( CS_IF );
initBlkLabel( &if_block->outside );
initBlkLabel( &if_block->u.i.else_part );
nextYYToken();
openScope();
if( EXPR_ANAL_OK == parseBracketExpr( &AnalyseBoolExpr ) ) {
if( if_block->expr_true ) {
CgFrontCode( IC_EXPR_TRASH );
} else if( if_block->expr_false ) {
CgFrontCode( IC_EXPR_TRASH );
if( ! currFunction->dead_code ) {
jumpBlkLabel( &if_block->u.i.else_part, O_GOTO );
}
} else {
if( currFunction->dead_code ) {
CgFrontCode( IC_EXPR_TRASH );
} else {
jumpBlkLabel( &if_block->u.i.else_part, O_IF_FALSE );
}
}
} else {
jumpBlkLabel( &if_block->u.i.else_part, O_GOTO );
currFunction->dead_code = FALSE;
}
}
static void parseElseStmt( void )
{
CSTACK *if_block;
nextYYToken();
if_block = currFunction->control;
if_block->id = CS_ELSE;
if( ( ! currFunction->dead_code )
&&( ! if_block->expr_false ) ) {
jumpBlkLabel( &if_block->outside, O_GOTO );
}
if( ! if_block->expr_true ) {
dumpBlkLabel( &if_block->u.i.else_part );
}
CgFrontLabfreeCs( 1 );
}
static CSTACK *beginLoopControl( int id )
{
CSTACK *loop;
loop = beginControl( id );
initBlkLabel( &loop->outside );
initBlkLabel( &loop->u.l.continue_loop );
loop->u.l.top_loop = CgFrontLabelCs();
return( loop );
}
static CSTACK *beginLoop( int id )
{
CSTACK *loop;
nextYYToken();
loop = beginLoopControl( id );
dumpCSLabel( loop->u.l.top_loop );
return( loop );
}
static void parseWhileStmt( void )
{
CSTACK *loop;
loop = beginLoop( CS_WHILE );
openScope();
if( EXPR_ANAL_OK == parseBracketExpr( &AnalyseBoolExpr ) ) {
if( loop->expr_true ) {
CgFrontCode( IC_EXPR_TRASH );
} else if( loop->expr_false ) {
CgFrontCode( IC_EXPR_TRASH );
jumpBlkLabel( &loop->outside, O_GOTO );
} else {
jumpBlkLabel( &loop->outside, O_IF_FALSE );
}
} else {
jumpBlkLabel( &loop->outside, O_GOTO );
currFunction->dead_code = FALSE;
}
}
static void parseForStmt( void )
{
EXPR_ANAL test_type;
EXPR_ANAL inc_type;
PTREE test_expr;
PTREE inc_expr;
CSTACK *loop;
CGLABEL around;
boolean test_was_const;
nextYYToken();
mustRecog( T_LEFT_PAREN );
if( ! CompFlags.use_old_for_scope ) {
openScope();
}
if( CurToken == T_SEMI_COLON ) {
mustRecog( T_SEMI_COLON );
} else {
ensureLiveCode();
declExprStmt( TRUE );
}
if( CurToken == T_SEMI_COLON ) {
test_type = EXPR_ANAL_NONE;
} else {
test_expr = safeParseExpr( T_SEMI_COLON );
test_was_const = NodeIsConstantInt( test_expr );
test_type = exprAnalyse( &AnalyseBoolExpr, &test_expr );
}
mustRecog( T_SEMI_COLON );
if( CurToken != T_RIGHT_PAREN ) {
inc_expr = safeParseExpr( T_RIGHT_PAREN );
inc_type = exprAnalyse( &AnalyseStmtExpr, &inc_expr );
} else {
inc_type = EXPR_ANAL_NONE;
}
mustRecog( T_RIGHT_PAREN );
loop = beginLoopControl( CS_FOR );
switch( inc_type ) {
case EXPR_ANAL_OK :
around = CgFrontLabelCs();
doJUMP( IC_LABEL_CS, O_GOTO, around );
dumpCSLabel( loop->u.l.top_loop );
emitCodeExpr( inc_expr );
dumpCSLabel( around );
CgFrontLabfreeCs( 1 );
break;
case EXPR_ANAL_NONE :
dumpCSLabel( loop->u.l.top_loop );
break;
}
if( test_type == EXPR_ANAL_OK ) {
warnBoolConst( test_expr, test_was_const );
emitCodeExpr( test_expr );
if( loop->expr_true ) {
CgFrontCode( IC_EXPR_TRASH );
} else {
jumpBlkLabel( &loop->outside, O_IF_FALSE );
}
}
openScope();
}
static PTREE analyseSwitchExpr( // ANALYSE SWITCH EXPRESSION
PTREE expr ) // - parsed expression
{
CSTACK *switch_block;
expr = AnalyseIntegralExpr( expr );
if( expr->op != PT_ERROR ) {
if( NULL != Integral64Type( expr->type ) ) {
SetErrLoc( &expr->locn );
CErr1( ERR_64BIT_SWITCH );
}
switch_block = currFunction->control;
switch_block->u.s.type = expr->type;
if( UnsignedIntType( expr->type ) ) {
switch_block->u.s.is_signed = FALSE;
} else {
switch_block->u.s.is_signed = TRUE;
}
}
return( expr );
}
static void parseSwitchStmt( void )
{
CSTACK *switch_block;
ensureLiveCode();
nextYYToken();
switch_block = beginControl( CS_SWITCH );
switch_block->u.s.type = NULL;
openScope();
initBlkLabel( &switch_block->outside );
switch_block->u.s.cases = NULL;
switch_block->u.s.imm_block = NULL;
switch_block->u.s.default_dropped = 0;
switch_block->u.s.defn_scope = GetCurrScope();
switch_block->u.s.is_signed = TRUE;
switch_block->u.s.default_locn.src_file = NULL;
SrcFileGetTokenLocn( &switch_block->u.s.switch_locn );
parseBracketExpr( &analyseSwitchExpr );
CgFrontSwitchBeg();
LabelSwitchBeg();
FunctionBodyDeadCode();
openScope();
if( ( CurToken == T_LEFT_BRACE ) || ( CurToken == T_ALT_LEFT_BRACE ) ) {
switch_block->u.s.block_after = TRUE;
} else {
switch_block->u.s.block_after = FALSE;
}
}
static boolean is_dup_case( // DIAGNOSE A DUPLICATE CASE
CSTACK *my_switch, // - control-stack entry
PTREE case_value, // - exprn for case
unsigned err_code ) // - code for error message
{
SWCASE *curr; // - current case in search
target_ulong case_uint; // - value to look for
auto char buff[16]; // - buffer for duplicate value
case_uint = case_value->u.uint_constant;
RingIterBeg( my_switch->u.s.cases, curr ) {
if( curr->value == case_uint ) {
if( my_switch->u.s.is_signed ) {
ltoa( case_value->u.int_constant, buff, 10 );
} else {
ultoa( case_value->u.uint_constant, buff, 10 );
}
CErr2p( err_code, buff );
InfMsgPtr( INF_PREVIOUS_CASE, &curr->defined );
return( TRUE );
}
} RingIterEnd( curr )
return( FALSE );
}
static SWCASE *makeCaseEntry( // MAKE CASE/DEFAULT ENTRY
TOKEN_LOCN *srcposn, // - position in source
CSTACK *my_switch ) // - control information
{
SWCASE *ce;
PTREE case_value;
boolean casted;
case_value = safeParseExpr( T_COLON );
ce = NULL;
if( case_value == NULL ) {
srcposn->src_file = NULL;
} else {
case_value = PTreeForceIntegral( case_value );
if( case_value == NULL ) {
srcposn->src_file = NULL;
} else {
*srcposn = case_value->locn;
if( ( my_switch != NULL ) && ( my_switch->u.s.type != NULL ) ) {
if( ! is_dup_case( my_switch
, case_value
, ERR_DUPLICATE_CASE_VALUE ) ) {
case_value = CastIntConstant( case_value
, my_switch->u.s.type
, &casted );
if( ( ! casted )
||( ! is_dup_case( my_switch
, case_value
, ERR_DUPLICATE_CONV_CASE_VALUE ) ) ) {
if( NULL == Integral64Type( case_value->type ) ) {
ce = CarveAlloc( carveSWCASE );
ce->next = NULL;
ce->value = case_value->u.uint_constant;
SrcFileGetTokenLocn( &ce->defined );
} else {
PTreeErrorExpr( case_value, ERR_64BIT_CASE );
}
}
}
LabelSwitch( my_switch->u.s.defn_scope );
}
PTreeFree( case_value );
}
}
mustRecog( T_COLON );
return( ce );
}
static CSTACK *findSwitch( void )
{
CSTACK *curr;
for( curr = currFunction->control
; ( curr != NULL ) && ( curr->id != CS_SWITCH )
; curr = curr->next );
return( curr );
}
static void parseCaseStmt( void )
{
CSTACK *my_switch;
SWCASE *case_entry;
TOKEN_LOCN srcposn;
my_switch = findSwitch();
if( my_switch == NULL ) {
CErr1( ERR_MISPLACED_CASE );
nextYYToken();
case_entry = makeCaseEntry( &srcposn, NULL );
if( case_entry != NULL ) {
CarveFree( carveSWCASE, case_entry );
}
case_entry = NULL;
} else {
nextYYToken();
case_entry = makeCaseEntry( &srcposn, my_switch );
}
if( case_entry == NULL ) {
currFunction->dead_code = FALSE;
return;
}
if( my_switch->u.s.cases == NULL ) {
my_switch->u.s.lo = case_entry->value;
my_switch->u.s.hi = case_entry->value;
}
CgFrontSwitchCase( my_switch->u.s.defn_scope
, currFunction->dead_code
, &srcposn
, case_entry->value );
currFunction->dead_code = FALSE;
RingAppend( &(my_switch->u.s.cases), case_entry );
if( ( CurToken == T_RIGHT_BRACE ) || ( CurToken == T_ALT_RIGHT_BRACE ) ) {
CErr1( ERR_STMT_REQUIRED_AFTER_CASE );
}
}
static void genDefaultStmt( // GENERATE A DEFAULT STATEMENT
CSTACK *my_switch, // - control block for switch
TOKEN_LOCN *posn ) // - source position
{
my_switch->u.s.default_dropped = TRUE;
CgFrontSwitchDefault( my_switch->u.s.defn_scope
, currFunction->dead_code
, posn );
currFunction->dead_code = FALSE;
}
static void parseDefaultStmt( void )
{
CSTACK *my_switch;
my_switch = findSwitch();
if( my_switch == NULL ) {
CErr1( ERR_MISPLACED_DEFAULT );
} else if( my_switch->u.s.default_dropped ) {
CErr1( ERR_ONLY_1_DEFAULT );
InfMsgPtr( INF_PREVIOUS_DEFAULT, &my_switch->u.s.default_locn );
} else {
SrcFileGetTokenLocn( &my_switch->u.s.default_locn );
}
nextYYToken();
mustRecog( T_COLON );
if( ( my_switch == NULL )
||( my_switch->u.s.default_dropped ) ) {
currFunction->dead_code = FALSE;
return;
}
LabelSwitch( my_switch->u.s.defn_scope );
genDefaultStmt( my_switch, &my_switch->u.s.default_locn );
if( ( CurToken == T_RIGHT_BRACE ) || ( CurToken == T_ALT_RIGHT_BRACE ) ) {
CErr1( ERR_STMT_REQUIRED_AFTER_DEFAULT );
}
}
static CSTACK *findBreakable( void )
{
CSTACK *curr;
Stack_forall( currFunction->control, curr ) {
switch( curr->id ) {
case CS_FOR:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?