fnbody.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,160 行 · 第 1/5 页
C
2,160 行
/****************************************************************************
*
* 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 <stddef.h>
#include "preproc.h"
#include "errdefns.h"
#include "memmgr.h"
#include "carve.h"
#include "ring.h"
#include "stack.h"
#include "name.h"
#include "yydriver.h"
#include "cgfront.h"
#include "cgsegid.h"
#include "codegen.h"
#include "dbg.h"
#include "class.h"
#include "fold.h"
#include "context.h"
#include "rtfuncod.h"
#include "ctexcept.h"
#include "template.h"
#include "fnbody.h"
#include "initdefs.h"
#include "objmodel.h"
#include "asmstmt.h"
#ifndef NDEBUG
#include "pragdefn.h"
#endif
#include "toggle.h"
static FUNCTION_DATA *currFunction;
static SUICIDE_CALLBACK functionSuicide;
static carve_t carveCSTACK;
static carve_t carveSWCASE;
static carve_t carveFNLABEL;
static carve_t carveFNCATCH;
enum // EXPR_ANAL -- result of expression analysis
{ EXPR_ANAL_OK // - expression parsed, analyzis succeeded
, EXPR_ANAL_NONE // - no expression existed to be parsed
, EXPR_ANAL_ERR // - expression parsed, analysis failed
};
typedef unsigned EXPR_ANAL; // - typed as unsigned for efficiency
static void nextYYToken( void )
{
ParseFlush(); // cleanup YYDRIVER
NextToken();
}
static void mustRecog( int token )
{
ParseFlush(); // cleanup YYDRIVER
MustRecog( token );
}
void FunctionBodyDeadCode( // MARK DEAD-CODE IN CURRENT FUNCTION
void )
{
currFunction->dead_code = TRUE;
currFunction->dead_diagnosed = FALSE;
}
static void doJUMP( int op, unsigned condition, CGLABEL destination )
{
CgFrontGotoNear( op, condition, destination );
if( condition == O_GOTO ) {
FunctionBodyDeadCode();
}
}
static void dumpCSLabel( CGLABEL lbl )
{
CgFrontLabdefCs( lbl );
currFunction->dead_code = FALSE;
}
static void dumpBlkLabel( // DUMP A BLOCK LABEL
BLK_LABEL *lab ) // - the label
{
if( lab->defn != NULL ) {
dumpCSLabel( lab->id );
LabelDefine( lab->defn );
}
}
static void dumpOutsideLabel( // DUMP THE LABEL FOR THE OUTSIDE OF A BLOCK
CSTACK *curr ) // - current block
{
dumpBlkLabel( &curr->outside );
}
static LAB_REF *refBlkLabel( // REFERENCE A BLOCK LABEL
BLK_LABEL *lab ) // - the label
{
if( lab->defn == NULL ) {
lab->defn = LabelAllocLabDef();
}
return LabelAllocLabRef( lab->defn );
}
static void jumpBlkLabel( // JUMP TO BLOCK LABEL
BLK_LABEL *lab, // - the label
unsigned condition ) // - type of jump
{
LabelRefFree( refBlkLabel( lab ) );
doJUMP( IC_LABEL_CS, condition, lab->id );
}
static void jumpFwdBlkLabel( // JUMP FORWARD TO BLOCK LABEL
BLK_LABEL *lab ) // - the label
{
SrcPosnEmitCurrent();
LabelGotoFwd( refBlkLabel( lab ) );
doJUMP( IC_LABEL_CS, O_GOTO, lab->id );
}
static void initBlkLabel( // INITIALIZE BLOCK LABEL
BLK_LABEL *lab ) // - the label
{
lab->id = CgFrontLabelCs();
lab->defn = NULL;
}
static void ensureLiveCode( // ENSURE WE DON'T HAVE DEAD CODE (PARSE)
void )
{
if( currFunction->dead_code && ! currFunction->dead_diagnosed ) {
CErr1( WARN_DEAD_CODE );
currFunction->dead_diagnosed = TRUE;
}
}
static void ensureLiveExpr( // ENSURE WE DON'T HAVE DEAD CODE (EXPR)
PTREE expr ) // - parsed expression
{
if( currFunction->dead_code && ! currFunction->dead_diagnosed ) {
PTreeWarnExpr( expr, WARN_DEAD_CODE );
currFunction->dead_diagnosed = TRUE;
}
}
static PTREE emitCodeExpr( PTREE expr )
{
ensureLiveExpr( expr );
return( IcEmitExpr( expr ) );
}
static PTREE safeParseExpr( int end_token )
{
if( CurToken == T_EOF ) {
return( NULL );
}
return( ParseExpr( end_token ) );
}
static EXPR_ANAL exprAnalyse(
PTREE (*analyse_rtn)( PTREE ),
PTREE *expr )
{
EXPR_ANAL retn;
if( *expr == NULL ) {
retn = EXPR_ANAL_NONE;
} else {
*expr = (*analyse_rtn)( *expr );
if( (*expr)->op == PT_ERROR ) {
retn = EXPR_ANAL_ERR;
} else {
retn = EXPR_ANAL_OK;
}
}
return( retn );
}
static void warnBoolConstVal( // WARN: FOR A CONSTANT VALUE
boolean is_zero, // - TRUE ==> zero constant
boolean parsed_int_const, // - user coded an int constant
PTREE expr ) // - expression
{
CSTACK *ctl; // - top control stack
ctl = currFunction->control;
if( is_zero ) {
ctl->expr_false = TRUE;
switch( ctl->id ) {
case CS_IF :
PTreeWarnExpr( expr, WARN_IF_ALWAYS_FALSE );
break;
case CS_FOR :
PTreeWarnExpr( expr, WARN_FOR_FALSE );
break;
case CS_WHILE :
PTreeWarnExpr( expr, WARN_WHILE_FALSE );
break;
case CS_DO :
if( ! parsed_int_const ) {
PTreeWarnExpr( expr, WARN_WHILE_FALSE );
}
break;
case CS_SWITCH :
PTreeWarnExpr( expr, WARN_SWITCH_ALWAYS_CONSTANT );
break;
}
} else {
ctl->expr_true = TRUE;
switch( ctl->id ) {
case CS_WHILE :
case CS_DO :
if( ! parsed_int_const ) {
PTreeWarnExpr( expr, WARN_WHILE_TRUE );
}
break;
case CS_FOR :
if( ! parsed_int_const ) {
PTreeWarnExpr( expr, WARN_FOR_TRUE );
}
break;
case CS_IF :
PTreeWarnExpr( expr, WARN_IF_ALWAYS_TRUE );
break;
case CS_SWITCH :
PTreeWarnExpr( expr, WARN_SWITCH_ALWAYS_CONSTANT );
break;
}
}
}
static void warnBoolConst( // WARN, WHEN SPECIFIC BOOLEAN CONSTANT
PTREE expr, // - analysed expression
boolean parsed_int_const ) // - user coded an int constant
{
if( NodeIsConstantInt( expr ) ) {
warnBoolConstVal( NodeIsZeroConstant( expr )
, parsed_int_const
, expr );
} else if( expr->flags & PTF_PTR_NONZERO ) {
warnBoolConstVal( FALSE, parsed_int_const, expr );
}
}
static EXPR_ANAL parseBracketExpr(
PTREE (*analyse_rtn)( PTREE ) )
{
PTREE expr;
EXPR_ANAL retn;
boolean parsed_int_const;
mustRecog( T_LEFT_PAREN );
expr = safeParseExpr( T_RIGHT_PAREN );
parsed_int_const = NodeIsConstantInt( expr );
retn = exprAnalyse( analyse_rtn, &expr );
if( retn != EXPR_ANAL_NONE ) {
warnBoolConst( expr, parsed_int_const );
emitCodeExpr( expr );
}
mustRecog( T_RIGHT_PAREN );
return( retn );
}
static void checkDeclLocation( void )
{
switch( currFunction->control->id ) {
case CS_IF:
CErr1( WARN_DCL_IF );
break;
case CS_ELSE:
CErr1( WARN_DCL_ELSE );
break;
case CS_SWITCH:
CErr1( WARN_DCL_SWITCH );
break;
case CS_FOR:
CErr1( WARN_DCL_FOR );
break;
case CS_WHILE:
CErr1( WARN_DCL_WHILE );
break;
case CS_DO:
CErr1( WARN_DCL_DO );
break;
}
}
static void emitStmtExpr( PTREE expr_tree )
{
ensureLiveExpr( expr_tree );
expr_tree = AnalyseStmtExpr( expr_tree );
expr_tree = emitCodeExpr( expr_tree );
}
static void declExprStmt( boolean for_stmts_decl )
{
PTREE expr_tree;
if( CurToken == T_EOF ) return;
expr_tree = ParseExprDecl();
if( expr_tree != NULL ) {
emitStmtExpr( expr_tree );
} else {
if( ! for_stmts_decl ) {
checkDeclLocation();
}
}
}
static CSTACK *beginControl( int id )
{
CSTACK *new_block;
new_block = StackCarveAlloc( carveCSTACK, &currFunction->control );
//printf( "PUSH: %p (%u) %s\n", new_block, id, (currFunction->fn_scope) ? (ScopeFunction( currFunction->fn_scope )->name->name) : "?" );
new_block->id = id;
new_block->outside.defn = NULL;
new_block->try_var = NULL;
SrcFileGetTokenLocn( &new_block->defined );
switch( id ) {
case CS_IF:
new_block->u.i.else_part.defn = NULL;
break;
case CS_FOR:
case CS_DO:
case CS_WHILE:
new_block->u.l.continue_loop.defn = NULL;
break;
case CS_BLOCK:
new_block->u.b.block = currFunction->block_count;
break;
}
new_block->expr_true = FALSE;
new_block->expr_false = FALSE;
return( new_block );
}
static void labelDefFree( BLK_LABEL *lab )
{
LabelDefFree( lab->defn );
lab->defn = NULL;
}
static void endControl( void )
{
CSTACK *old_block;
old_block = StackPop( &(currFunction->control) );
if( old_block == NULL ) return;
//printf( "POP: %p (%u) %s\n", old_block, old_block->id, ScopeFunction( currFunction->fn_scope )->name->name );
labelDefFree( &(old_block->outside) );
switch( old_block->id ) {
case CS_IF:
case CS_ELSE:
labelDefFree( &(old_block->u.i.else_part) );
break;
case CS_FOR:
case CS_DO:
case CS_WHILE:
labelDefFree( &(old_block->u.l.continue_loop) );
break;
}
CarveFree( carveCSTACK, old_block );
}
static void openScope( void )
{
ScopeBeginBlock( currFunction->block_count++ );
LabelBlockOpen( currFunction->dead_code );
}
static void closeScope( void )
{
LabelBlockClose( currFunction->dead_code );
ScopeEnd( SCOPE_BLOCK );
}
static void startBlock( void )
{
beginControl( CS_BLOCK );
openScope();
currFunction->depth++;
}
static void endBlock( void )
{
if( currFunction->depth > currFunction->outer_depth ) {
closeScope();
}
currFunction->depth--;
}
static FNLABEL *findLabel( char *name )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?