cstmt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,481 行 · 第 1/3 页
C
1,481 行
/****************************************************************************
*
* 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: Convert C statements to expression trees.
*
****************************************************************************/
#include "cvars.h"
#include "i64.h"
typedef struct block_entry {
struct block_entry *prev_block;
struct block_entry *prev_loop;
int block_type;
int top_label;
int break_label;
int continue_label;
int try_index; /* TRY: current index */
int parent_index; /* TRY: parent index */
TREEPTR inc_var; /* variable used in FOR statement */
SYM_HANDLE sym_list; /* symbols defined in this block */
bool gen_endblock; /* set if OPR_ENDBLOCK needed */
} BLOCKDEFN, *BLOCKPTR;
// values for return_type
enum return_with {
RETURN_WITH_NONE = 0,
RETURN_WITH_NO_EXPR = 1,
RETURN_WITH_EXPR = 2,
};
struct return_info {
enum return_with with;
bool with_expr;
};
extern int NodeCount;
TREEPTR CurFuncNode;
int LabelIndex;
SYM_LISTS *SymListHeads;
static TREEPTR LastStmt;
static BLOCKPTR BlockStack;
static BLOCKPTR LoopStack;
static SWITCHPTR SwitchStack;
extern TREEPTR BaseConv( TYPEPTR typ1, TREEPTR op2 );
extern TREEPTR BoolConv( TYPEPTR typ, TREEPTR tree );
extern int LoopDecl( SYM_HANDLE *sym_head );
void StmtInit( void )
{
FirstStmt = NULL;
LastStmt = NULL;
SymListHeads = NULL;
}
static void ChkStringLeaf( TREEPTR leaf )
{
if( leaf->op.opr == OPR_PUSHSTRING ) {
leaf->op.string_handle->ref_count++;
}
}
static void ChkUseful( void )
{
if( CompFlags.useful_side_effect ) {
CWarn1( WARN_USEFUL_SIDE_EFFECT, ERR_USEFUL_SIDE_EFFECT );
} else {
CWarn1( WARN_MEANINGLESS, ERR_MEANINGLESS );
}
}
static void ChkStmtExpr( void )
{
TREEPTR tree;
tree = Expr();
if( CompFlags.meaningless_stmt == 1 ) {
ChkUseful();
}
AddStmt( tree );
if( CompFlags.pending_dead_code ) {
DeadCode = 1;
}
}
SYM_HANDLE GetBlockSymList( void )
{
return( BlockStack->sym_list );
}
void InitStmt( void )
{
BlockStack = NULL;
LoopStack = NULL;
SwitchStack = NULL;
}
void SwitchPurge( void )
{
SWITCHPTR sw;
CASEPTR c_entry, c_tmp;
while( (sw = SwitchStack) ) {
SwitchStack = sw->prev_switch;
c_entry = sw->case_list;
while( c_entry != NULL ) {
c_tmp = c_entry->next_case;
CMemFree( c_entry );
c_entry = c_tmp;
}
CMemFree( sw );
}
}
void AddStmt( TREEPTR stmt )
{
WalkExprTree( stmt, ChkStringLeaf, NoOp, NoOp, DoConstFold );
stmt = ExprNode( 0, OPR_STMT, stmt );
stmt->op.source_fno = SrcFno;
stmt->srclinenum = SrcLineNum;
stmt->op.unroll_count = UnrollCount;
if( FirstStmt == NULL ) FirstStmt = stmt;
if( LastStmt != NULL ) {
LastStmt->left = stmt;
}
LastStmt = stmt;
}
static void AddSymList( SYM_HANDLE sym_handle )
{
SYM_LISTS *symlist;
symlist = (SYM_LISTS *)CMemAlloc( sizeof( SYM_LISTS ) );
symlist->next = SymListHeads;
symlist->sym_head = sym_handle;
SymListHeads = symlist;
}
void GenFunctionNode( SYM_HANDLE sym_handle )
{
TREEPTR tree;
SYMPTR sym;
tree = LeafNode( OPR_FUNCTION );
sym = SymGetPtr( sym_handle );
tree->op.func.sym_handle = sym_handle;
tree->op.func.flags = FUNC_NONE;
if( ( Toggles & TOGGLE_INLINE ) | ( sym->attrib & FLAG_INLINE ) ){
if( !sym->naked ){
if( strcmp( sym->name, "main" ) != 0 ) {
tree->op.func.flags |= FUNC_OK_TO_INLINE;
}
}
}
tree->op.flags = OpFlags( sym->attrib );
tree->expr_type = sym->sym_type->object; // function return type
AddStmt( tree );
// Evil, evil globals! But we need this for later lookups in cgen.c
sym->u.func.start_of_func = LastStmt;
CurFuncNode = tree;
NodeCount = 0;
}
int NextLabel( void )
{
return( ++LabelIndex );
}
static void DropLabel( LABEL_INDEX label )
{
TREEPTR tree;
CompFlags.label_dropped = 1;
DeadCode = 0;
tree = LeafNode( OPR_LABEL );
tree->op.label_index = label;
AddStmt( tree );
}
static void DropBreakLabel( void )
{
if( BlockStack->break_label != 0 ) { /* 05-apr-92 */
DropLabel( BlockStack->break_label );
}
}
static void DropContinueLabel( void )
{
if( BlockStack->continue_label != 0 ) {
DropLabel( BlockStack->continue_label );
}
}
static TREEPTR BracketExpr( void )
{
TREEPTR tree;
MustRecog( T_LEFT_PAREN );
tree = Expr();
FoldExprTree( tree );
MustRecog( T_RIGHT_PAREN );
return( tree );
}
static void JumpCond( TREEPTR expr,
LABEL_INDEX label,
int jump_opcode,
int jump_opposite )
{
TREEPTR tree;
tree = BoolExpr( expr );
if( tree->op.opr == OPR_NOT ) {
tree->op.opr = jump_opposite;
} else {
tree = ExprNode( 0, jump_opcode, tree );
}
tree->op.label_index = label;
AddStmt( tree );
}
static void Jump( LABEL_INDEX label )
{
TREEPTR tree;
if( ! DeadCode ) {
tree = LeafNode( OPR_JUMP );
tree->op.label_index = label;
AddStmt( tree );
DeadCode = 1;
}
}
static int JumpFalse( TREEPTR expr, LABEL_INDEX label )
{
int jump_generated;
jump_generated = 0;
if( expr->op.opr == OPR_PUSHINT ) {
if( ! expr->op.long_value ) {
Jump( label );
jump_generated = 1;
}
FreeExprNode( expr );
} else {
JumpCond( expr, label, OPR_JUMPFALSE, OPR_JUMPTRUE );
jump_generated = 1;
}
return( jump_generated );
}
static void JumpTrue( TREEPTR expr, LABEL_INDEX label )
{
if( expr->op.opr == OPR_PUSHINT ) {
if( expr->op.long_value ) {
Jump( label );
}
FreeExprNode( expr );
} else {
JumpCond( expr, label, OPR_JUMPTRUE, OPR_JUMPFALSE );
}
}
void LookAhead( void )
{
SavedId = CStrSave( Buffer ); /* save current id */
SavedHash = HashValue; /* and its hash value */
SavedTokenLine = TokenLine; /* save linenum and fno 09-jul-95 */
SavedTokenFno = TokenFno;
NextToken(); /* get next token */
LAToken = CurToken; /* save it in look ahead */
CurToken = T_SAVED_ID; /* go back to saved id */
}
static int GrabLabels( void )
{
LABELPTR label;
label = NULL;
for( ;; ) {
if( CurToken == T_SAVED_ID ) { /* 09-jul-95 */
SrcLineNum = SavedTokenLine;
SrcFno = SavedTokenFno;
} else {
SrcLineNum = TokenLine;
SrcFno = TokenFno;
if( CurToken != T_ID ) break;
LookAhead();
}
if( LAToken != T_COLON ) break; /* quit if look ahead not : */
label = LkLabel( SavedId );
if( label->defined != 0 ) {
CErr2p( ERR_LABEL_ALREADY_DEFINED, label->name );
} else {
DropLabel( label->ref_list );
label->defined = 1; /* indicate label defined now */
}
CMemFree( SavedId ); /* free the saved id */
SavedId = NULL;
NextToken(); /* get next token */
}
if( label != NULL ) { /* label was found */
if( CurToken == T_RIGHT_BRACE ) {
CErr1( ERR_STMT_REQUIRED_AFTER_LABEL );
}
return( 1 ); // indicate label found
}
return( 0 );
}
static void UnWindTry( int try_scope )
{
#ifdef __SEH__
TREEPTR tree;
tree = LeafNode( OPR_UNWIND );
tree->op.try_index = try_scope;
AddStmt( tree );
#else
try_scope = try_scope;
#endif
}
static void ReturnStmt( SYM_HANDLE func_result, struct return_info *info )
{
TREEPTR tree;
BLOCKPTR block;
enum return_with with;
NextToken();
if( CurToken != T_SEMI_COLON ) {
TYPEPTR func_type;
func_type = CurFunc->sym_type->object;
SKIP_TYPEDEFS( func_type );
tree = RValue( Expr() );
ChkRetType( tree );
tree = BoolConv( func_type, tree );
tree = FixupAss( tree, func_type );
tree = ExprNode( 0, OPR_RETURN, tree );
tree->expr_type = func_type;
tree->op.sym_handle = func_result;
AddStmt( tree );
with = RETURN_WITH_EXPR;
info->with_expr = TRUE;
} else {
with = RETURN_WITH_NO_EXPR;
}
if( info->with == RETURN_WITH_NONE ) {
info->with = with;
}
if( info->with != with ) {
CErr1( ERR_INCONSISTENT_USE_OF_RETURN );
}
block = BlockStack; /* 16-apr-94 */
while( block != NULL ) {
if( (block->block_type == T__TRY) || (block->block_type == T___TRY) )
break;
block = block->prev_block;
}
if( block != NULL ) {
UnWindTry( -1 );
}
}
static void SetFuncReturnNode( TREEPTR tree )
{
TYPEPTR typ;
typ = CurFunc->sym_type->object;
tree->expr_type = typ;
SKIP_TYPEDEFS( typ );
if( typ->decl_type == TYPE_STRUCT || typ->decl_type == TYPE_UNION ) {
tree->right = LeafNode( OPR_NOP ); // place holder
tree->right->expr_type = NULL;
}
}
static void ChkRetValue( void )
{
TYPEPTR typ;
typ = CurFunc->sym_type;
typ = typ->object;
SKIP_TYPEDEFS( typ );
if( typ->decl_type != TYPE_VOID ) {
CWarn( WARN_MISSING_RETURN_VALUE,
ERR_MISSING_RETURN_VALUE, CurFunc->name );
}
}
static SYM_HANDLE GetLocalVarDecls( void )
{
SYM_HANDLE symlist;
SYM_HANDLE symhandle;
SYM_ENTRY sym;
DeclList( &symlist );
if( symlist != 0 ) {
symhandle = CurFunc->u.func.locals;
// symhandle will be non-zero if MakeNewSym was called while
// parsing the declaration list.
if( symhandle != 0 ) { // if some temporaries were created
for( ;; ) { // - find end of list
SymGet( &sym, symhandle );
if( sym.handle == 0 ) break;
symhandle = sym.handle;
}
sym.handle = symlist;
SymReplace( &sym, symhandle );
} else {
CurFunc->u.func.locals = symlist;
}
}
return( symlist );
}
static void DeadMsg( void )
/*************************/
{
CWarn1( WARN_DEAD_CODE, ERR_DEAD_CODE );
DeadCode = 2; /* so we don't get more messages */
}
static void StartNewBlock( void )
{
BLOCKPTR block;
block = (BLOCKPTR)CMemAlloc( sizeof( BLOCKDEFN ) );
block->block_type = CurToken;
block->top_label = 0;
block->continue_label = 0;
block->break_label = 0;
block->prev_block = BlockStack;
block->prev_loop = LoopStack;
block->gen_endblock = FALSE;
BlockStack = block;
}
static void LeftBrace( void )
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?