fnbody.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,160 行 · 第 1/5 页

C
2,160
字号
                                  , SF_REFERENCED | SF_ALIAS | SF_CATCH_ALIAS
                                  , name );
    catch_var->u.alias = try_var;
    return catch_var;
}


static void parseCatchHandler(  // PARSE CATCH STATEMENT
    void )
{
    DECL_INFO *info;            // - info. about parsed catch variable
    SYMBOL try_var;             // - try variable
    SYMBOL catch_var;           // - variable for catch
    CSTACK *try_block;          // - try block for catch
    TOKEN_LOCN posn;            // - position of catch
    TOKEN_LOCN blk;             // - position of catch block

    SrcFileGetTokenLocn( &posn );
    try_block = currFunction->control;
    if( ( try_block->id != CS_CATCH ) && ( try_block->id != CS_TRY ) ) {
        CErr1( ERR_MISPLACED_CATCH );
        try_block = NULL;
    }
    ExceptionsCheck();
    nextYYToken();
    mustRecog( T_LEFT_PAREN );
    if( CurToken == T_DOT_DOT_DOT ) {
        nextYYToken();
        info = NULL;
    } else {
        info = ParseException();
        if( info == NULL ) {
            try_block = NULL;
        }
    }
    mustRecog( T_RIGHT_PAREN );
    currFunction->dead_code = FALSE;
    SrcPosnEmitCurrent();
    SrcFileGetTokenLocn( &blk );
    mustRecog( T_LEFT_BRACE );
    startBlock();
    SrcPosnEmitCurrent();
    if( try_block != NULL ) {
        if( info == NULL ) {
            makeFNCATCH( NULL, try_block, &posn );
        } else {
            makeFNCATCH( info->type, try_block, &posn );
            try_var = updateTryVar( try_block, info->type );
        }
        try_block->id = CS_CATCH;
        ++try_block->u.t.catch_no;
        LabelSwitch( try_block->u.t.defn_scope );
        SrcFileGetTokenLocn( &posn );
        CgFrontSwitchCase( try_block->u.t.defn_scope
                         , FALSE
                         , &posn
                         , try_block->u.t.catch_no );
        LabelBlkCatch( &blk, try_block );
        if( info != NULL ) {
            if( ! try_block->u.t.catch_err ) {
                catch_var = makeCatchVar( try_var, info );
                if( catch_var != NULL ) {
                    LabelDeclInited( catch_var );
                    if( SymRequiresDtoring( catch_var ) ) {
                        IcEmitDtorAutoSym( catch_var );
                    }
                }
            }
            FreeDeclInfo( info );
        }
    }
}

static void parseAsmStmt( TYPE fn_type )
{
    PTREE expr;

    ParseFlush();       // cleanup YYDRIVER
    expr = AsmStmt();
    if( expr != NULL ) {
        emitStmtExpr( expr );
        if( fn_type->flag & TF1_NAKED ) {
            FunctionBodyDeadCode();
        }
    }
}


static boolean endOfStmt(       // PROCESS END-OF-STATEMENT
    boolean recog )             // - TRUE ==> need to recognize token
{
    CSTACK *top_block;
    CSTACK *next;
    int id;
    boolean dead_code;

    top_block = currFunction->control;
    id = top_block->id;
    for(;;) {
        switch( id ) {
        case CS_BLOCK:
            next = top_block->next;
            switch( next->id ) {
            case CS_SWITCH :
                if( top_block->u.b.block_switch ) {
                    if( next->u.s.default_dropped || ! GetCurrScope()->dtor_naked ) {
                        if( ! next->u.s.default_dropped ) {
                            TOKEN_LOCN locn;
                            locn = SrcPosnEmitCurrent();
                            genDefaultStmt( next, &locn );
                        }
                        next->u.s.imm_block = GetCurrScope();
                    }
                }
                if( ! currFunction->dead_code ) {
                    SrcPosnEmitCurrent();
                    jumpFwdBlkLabel( &next->outside );
                }
                break;
            case CS_CATCH :
                if( ! currFunction->dead_code ) {
                    SrcPosnEmitCurrent();
                    jumpFwdBlkLabel( &next->outside );
                }
                break;
            case CS_TRY :
                if( ! currFunction->dead_code ) {
                    SrcPosnEmitCurrent();
                    jumpFwdBlkLabel( &next->outside );
                }
                break;
            }
            endBlock();
            break;
        case CS_IF:
            if( recog ) {
                nextYYToken();
                recog = FALSE;
            }
            if( CurToken == T_ELSE ) {
                parseElseStmt();
                /* Note that the scope opened in parseIfStmt is not
                 * closed when there is an "else" part. Also note that
                 * parseElseStmt doesn't open a new scope, so the
                 * closeScope in the CS_ELSE case below will close the
                 * scope opened in parseIfStmt.
                 *
                 * See 6.4 (3): the name introduced by a declaration
                 * in a conditoin is in scope until the end of the
                 * "else" part. BTW, re-declaring that name is not
                 * allowed by the standard, but the current code
                 * doesn't catch that.
                 */ 
                return recog;
            }
            if( ! top_block->expr_true ) {
                dumpBlkLabel( &top_block->u.i.else_part );
            }
            closeScope();
            CgFrontLabfreeCs( 2 );
            break;
        case CS_ELSE:
            dead_code = currFunction->dead_code;
            if( ! top_block->expr_false ) {
                dumpOutsideLabel( top_block );
            }
            if( ! dead_code ) {
                currFunction->dead_code = FALSE;
            }
            closeScope();
            CgFrontLabfreeCs( 1 );
            break;
        case CS_FOR:
        case CS_WHILE:
            if( top_block->u.l.continue_loop.defn != NULL ) {
                dumpBlkLabel( &top_block->u.l.continue_loop );
            }
            closeScope();
            doJUMP( IC_LABEL_CS, O_GOTO, top_block->u.l.top_loop );
            dumpOutsideLabel( top_block );
            if( id == CS_FOR && ! CompFlags.use_old_for_scope ) {
                closeScope();
            }
            CgFrontLabfreeCs( 3 );
            break;
        case CS_DO:
            if( recog ) {
                nextYYToken();
                recog = FALSE;
            }
            mustRecog( T_WHILE );
            if( top_block->u.l.continue_loop.defn != NULL ) {
                dumpBlkLabel( &top_block->u.l.continue_loop );
            }
            if( EXPR_ANAL_OK == parseBracketExpr( &AnalyseBoolExpr ) ) {
                ensureLiveCode();
                if( top_block->expr_false ) {
                    CgFrontCode( IC_EXPR_TRASH );
                } else if( top_block->expr_true ) {
                    CgFrontCode( IC_EXPR_TRASH );
                    doJUMP( IC_LABEL_CS, O_GOTO, top_block->u.l.top_loop );
                } else {
                    jumpBlkLabel( &top_block->outside, O_IF_FALSE );
                    doJUMP( IC_LABEL_CS, O_GOTO, top_block->u.l.top_loop );
                }
            } else {
                doJUMP( IC_LABEL_CS, O_GOTO, top_block->u.l.top_loop );
                currFunction->dead_code = FALSE;
            }
            mustRecog( T_SEMI_COLON );
            dumpOutsideLabel( top_block );
            CgFrontLabfreeCs( 3 );
            break;
        case CS_SWITCH:
            closeScope();
            if( NULL == top_block->u.s.imm_block ) {
                if( ! top_block->u.s.default_dropped ) {
                    CgFrontCodeUint( IC_SWITCH_OUTSIDE
                                   , top_block->outside.id - 1 );
                    if( top_block->outside.defn == NULL ) {
                        top_block->outside.defn = LabelAllocLabDef();
                    }
                }
                if( ( ! currFunction->dead_code )
                  &&( ! top_block->u.s.block_after ) ) {
                    jumpFwdBlkLabel( &top_block->outside );
                }
            }
            SrcPosnEmit( &top_block->u.s.switch_locn );
            CgFrontSwitchEnd();
            SrcPosnEmitCurrent();
            dumpOutsideLabel( top_block );
            CgFrontLabfreeCs( 1 );
            if( top_block->u.s.cases != NULL ) {
                RingCarveFree( carveSWCASE, &(top_block->u.s.cases) );
            } else {
                // make sure switch is valid before warning
                if( top_block->u.s.type != NULL ) {
                    SetErrLoc( &top_block->u.s.switch_locn );
                    CErr1( WARN_SWITCH_NO_CASE_LABELS );
                }
            }
            closeScope();
            break;
        case CS_TRY:
            if( recog ) {
                nextYYToken();
                recog = FALSE;
            }
            if( CurToken == T_CATCH ) return recog;
            if( ! top_block->u.t.catch_err ) {
                CErr1( ERR_CATCH_MISSING );
            }
            completeTry( top_block );
            break;
        case CS_CATCH:
            if( recog ) {
                nextYYToken();
                recog = FALSE;
            }
            if( CurToken == T_CATCH ) return recog;
            completeTry( top_block );
            break;
        }
        endControl();
        top_block = currFunction->control;
        if( top_block == NULL ) return recog;
        id = top_block->id;
        if( id == CS_FUNCTION || id == CS_BLOCK ) break;
    }
    return recog;
}


// Scalar return values are assigned to a magic symbol.
//
// Class return values are allocated in the caller. The magic symbol is
// in the function scope, under the magic name (as the last parameter).
//
static void insertFunctionReturn( SYMBOL func )
{
    TYPE ret;               // - return type
    TYPE base;              // - base type for return
    SYMBOL retn_sym;        // - return symbol

    ret = FunctionDeclarationType( func->sym_type );
    base = TypedefModifierRemove( ret->of );
    switch( ObjModelFunctionReturn( ret ) ) {
      case OMR_VOID :
        break;
      case OMR_SCALAR :
      case OMR_CLASS_VAL :
        retn_sym = SymAllocReturn( GetCurrScope(), base );
        CgFrontCodePtr( IC_FUNCTION_RETN, retn_sym );
        break;
      case OMR_CLASS_REF :
        if( NULL == SymFunctionReturn() ) {
            retn_sym = SymAllocReturn( GetCurrScope()->enclosing, base );
            CgFrontCodePtr( IC_FUNCTION_RETN, retn_sym );
        }
        break;
    }
}


static void exceptSpec(         // GENERATE AN EXCEPTION SPECIFICATION
    TYPE except )               // - type of spec
{
    boolean err_occurred;       // - TRUE ==> error during type-sig

    TypeSigFind( 0, except, NULL, &err_occurred );
#ifndef NDEBUG
    if( err_occurred ) {
        CFatal( "setExceptionSpecs -- unexpected error" );
    }
#endif
    CgFrontCodePtr( IC_EXCEPT_SPEC, except );
    ScopeKeep( GetCurrScope() );
}


static void setExceptionSpecs(  // SET EXCEPTION SPEC.S FOR FUNCTION
    SYMBOL func )               // - the function
{
    TYPE *excepts;              // - vector of exception specifications
    TYPE except;                // - current exception specification
    boolean no_excepts_allowed; // - TRUE ==> no exceptions allowed

    excepts = SymFuncArgList( func )->except_spec;
    if( excepts != NULL ) {
        ExceptionsCheck();
        no_excepts_allowed = TRUE;
        for( ; ; ) {
            except = *excepts++;
            if( NULL == except ) break;
            no_excepts_allowed = FALSE;
            exceptSpec( except );
        }
        if( no_excepts_allowed ) {
            exceptSpec( NULL );
        }
        FunctionHasRegistration();
    }
}


static void initFunctionData(   // INITIALIZE FUNCTION DATA (BEFORE FNSTARTUP)
    SYMBOL func,                // - function
    FUNCTION_DATA *f )          // - data
{
    char *fn_name;

    CtxFunction( func );
    f->next = currFunction;
    currFunction = f;
    f->fn_scope = NULL;
    f->depth = 0;
    f->outer_depth = 0;
    f->control = NULL;
    f->labels = NULL;
    f->block_count = 0;
    f->flag_count = 0;
    f->init_var.var = NULL;
    f->init_var.mask = 1;
    f->access_errs = NULL;
    f->retn_opt_sym = NULL;
    f->dead_code = FALSE;
    f->dead_diagnosed = FALSE;
    f->always_dead_code = FALSE;
    f->is_ctor = FALSE;
    f->is_dtor = FALSE;
    f->is_assign = FALSE;
    f->is_defarg = FALSE;
    f->ret_reqd = FALSE;
    f->has_mem_init = FALSE;
    f->has_state_tab = FALSE;
    f->can_throw = FALSE;
    f->does_throw = FALSE;
    f->ctor_test = FALSE;
    f->floating_ss = FALSE;
    f->retn_opt = TRUE;
    fn_name = func->name->name;
    if( fn_name == CppConstructorName() ) {
        f->is_ctor = TRUE;
    } else if( fn_name == CppDestructorName() ) {
        f->is_dtor = TRUE;
    } else if( fn_name == CppOperatorName( CO_EQUAL ) ) {
        f->is_assign = TRUE;
    }
}

static void doFnStartup( SYMBOL func
                       , FUNCTION_DATA *fdata
                       , REWRITE *mem_initial
                       , TOKEN_LOCN *srcposn
                       , enum special_func flags )
{
    PTREE mem_init;

    fdata->fn_scope = GetCurrScope();
    func->flag |= SF_INITIALIZED;
    if( flags & FUNC_NO_STACK_CHECK ) {
        /* in case the type was derived from a stack-checked function */
        func->sym_type = RemoveFunctionFlag( func->sym_type, TF1_STACK_CHECK );
    } else {
        if( PragToggle.check_stack ) {
            func->sym_type = AddFunctionFlag( func->sym_type, TF1_STACK_CHECK );
        }
    }
    fdata->init_state_tab = CgFrontFuncOpen( func, srcposn );
    CgSegIdFunction( func );
    LabelInitFunc( &fdata->label_mem );
    startBlock();
    setExceptionSpecs( func );
    insertFunctionReturn( func );
    if( fdata->is_ctor ) {
        mem_init = ClassMemInit( func, mem_initial );
        CtorPrologue( func, mem_init, &startBlock );
        FnRetnOptOff();
        startBlock();
    } else if( fdata->is_dtor ) {
        DtorPrologue( func, &fdata->end_dtor, &fdata->dtor_beg );
        FnRetnOptOff();
        startBlock();
    }
    fdata->outer_depth = fdata->depth;
}

void FunctionBodyStartup(       // COMMON START-UP FOR ALL COMPILED FUNCTIONS
    SYMBOL func,                // - function being compiled
    FUNCTION_DATA *f,           // - function data for current function
    enum special_func flags )   // - extra flags

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?