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