📄 cstmt2.c
字号:
/****************************************************************************
*
* 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"
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 */
} 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;
void ChkStmtExpr( void );
static void EndOfStmt( void );
static void LeftBrace( void );
static void BreakStmt( void );
static void LeaveStmt( void );
static void ContinueStmt( void );
static void DropBreakLabel( void );
static void DropContinueLabel( void );
static void DefaultStmt( void );
static void ElseStmt( void );
static void GotoStmt( void );
static void ForStmt( void );
static void EndForStmt( void );
static void StmtExpr( void );
static void ChkUseful( void );
static void CaseStmt( void );
static void TryStmt( void );
static int EndTry( void );
static void UnWindTry( int try_scope );
static void NewLoop( void );
static void startNewBlock( void );
static void PopBlock( void );
static void SwitchStmt( void );
static void EndSwitch( void );
static void JumpCond( TREEPTR expr, LABEL_INDEX label, int jump_opcode,
int jump_opposite );
void StmtInit( void ){
FirstStmt = NULL;
LastStmt = NULL;
SymListHeads = NULL;
}
void ChkStringLeaf( TREEPTR leaf )
{
if( leaf->op.opr == OPR_PUSHSTRING ) {
leaf->op.string_handle->ref_count++;
}
}
SYM_HANDLE GetBlockSymList( void )
{
return( BlockStack->sym_list );
}
void InitStmt( void )
{
BlockStack = NULL;
LoopStack = NULL;
SwitchStack = NULL;
}
void SwitchPurge()
{
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;
}
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 cgen2.c
sym->u.func.start_of_func = LastStmt;
CurFuncNode = tree;
NodeCount = 0;
}
int NextLabel()
{
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 TREEPTR BracketExpr()
{
TREEPTR tree;
MustRecog( T_LEFT_PAREN );
tree = Expr();
FoldExprTree( tree );
MustRecog( T_RIGHT_PAREN );
return( 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 );
}
}
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 );
}
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()
{
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 ReturnStmt( SYM_HANDLE func_result, struct return_info *info )
{
TREEPTR tree;
BLOCKPTR block;
enum return_with with;
NextToken();
if( CurToken != T_SEMI_COLON ) {
tree = RValue( Expr() );
ChkRetType( tree );
tree = ExprNode( 0, OPR_RETURN, tree );
tree->expr_type = CurFunc->sym_type->object;
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 ) 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;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
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()
{
TYPEPTR typ;
typ = CurFunc->sym_type;
typ = typ->object;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( typ->decl_type != TYPE_VOID ) {
CWarn( WARN_MISSING_RETURN_VALUE,
ERR_MISSING_RETURN_VALUE, CurFunc->name );
}
}
void GetLocalVarDecls()
{
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;
}
}
}
static void DeadMsg( void ){
/***************************/
CWarn1( WARN_DEAD_CODE, ERR_DEAD_CODE );
DeadCode = 2; /* so we don't get more messages */
}
void Statement( void )
{
LABEL_INDEX end_of_func_label;
SYM_HANDLE func_result;
TREEPTR tree;
char return_at_outer_level;
char skip_to_next_token;
struct return_info return_info;
SYM_ENTRY sym;
#ifndef NDEBUG
if( DebugFlag >= 1 ) {
printf( "***** line %d, func=%s\n", TokenLine, CurFunc->name );
PrintStats();
}
#endif
++FuncCount;
return_info.with = RETURN_WITH_NONE; /* indicate no return statements */
return_info.with_expr = FALSE;
CompFlags.label_dropped = 0;
CompFlags.addr_of_auto_taken = 0; /* 23-oct-91 */
end_of_func_label = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -