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 + -
显示快捷键?