fnbody.c

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

C
2,160
字号
    FNLABEL *curr;
    FNLABEL *new_label;

    RingIterBeg( currFunction->labels, curr ) {
        if( curr->name == name ) {
            return( curr );
        }
    } RingIterEnd( curr )
    new_label = RingCarveAlloc( carveFNLABEL, &currFunction->labels );
    new_label->name = name;
    new_label->block = currFunction->block_count;
    new_label->defined = FALSE;
    new_label->dangerous = FALSE;
    new_label->destination.id = CgFrontLabelGoto();
    new_label->destination.defn = LabelAllocLabDef();
    if( PragToggle.unreferenced ) {
        new_label->referenced = FALSE;
    } else {
        new_label->referenced = TRUE;
    }
    return( new_label );
}

static void parseLabels( void )
{
    FNLABEL *label;

    label = NULL;
    for(;;) {
        if( CurToken == T_ID ) {
            LookPastName();
        } else if( CurToken != T_SAVED_ID ) {
            break;
        }
        if( LAToken != T_COLON ) break;
        label = findLabel( SavedId );
        if( label->defined ) {
            CErr2p( ERR_LABEL_ALREADY_DEFINED, label->name );
            InfMsgPtr( INF_PREVIOUS_LABEL, &label->destination.defn->locn );
        } else {
            label->defined = TRUE;
            CgFrontLabdefGoto( label->destination.id );
            LabelDefine( label->destination.defn );
        }
        currFunction->dead_code = FALSE;
        nextYYToken();
        nextYYToken();
    }
    if( label != NULL ) {
        if( ( CurToken == T_RIGHT_BRACE )
         || ( CurToken == T_ALT_RIGHT_BRACE ) ) {
            CErr1( ERR_STMT_REQUIRED_AFTER_LABEL );
        }
    }
}


static void parseIfStmt( void )
{
    CSTACK *if_block;

    ensureLiveCode();
    if_block = beginControl( CS_IF );
    initBlkLabel( &if_block->outside );
    initBlkLabel( &if_block->u.i.else_part );
    nextYYToken();
    openScope();
    if( EXPR_ANAL_OK == parseBracketExpr( &AnalyseBoolExpr ) ) {
        if( if_block->expr_true ) {
            CgFrontCode( IC_EXPR_TRASH );
        } else if( if_block->expr_false ) {
            CgFrontCode( IC_EXPR_TRASH );
            if( ! currFunction->dead_code ) {
                jumpBlkLabel( &if_block->u.i.else_part, O_GOTO );
            }
        } else {
            if( currFunction->dead_code ) {
                CgFrontCode( IC_EXPR_TRASH );
            } else {
                jumpBlkLabel( &if_block->u.i.else_part, O_IF_FALSE );
            }
        }
    } else {
        jumpBlkLabel( &if_block->u.i.else_part, O_GOTO );
        currFunction->dead_code = FALSE;
    }
}


static void parseElseStmt( void )
{
    CSTACK *if_block;

    nextYYToken();
    if_block = currFunction->control;
    if_block->id = CS_ELSE;
    if( ( ! currFunction->dead_code )
      &&( ! if_block->expr_false ) ) {
        jumpBlkLabel( &if_block->outside, O_GOTO );
    }
    if( ! if_block->expr_true ) {
        dumpBlkLabel( &if_block->u.i.else_part );
    }
    CgFrontLabfreeCs( 1 );
}


static CSTACK *beginLoopControl( int id )
{
    CSTACK *loop;

    loop = beginControl( id );
    initBlkLabel( &loop->outside );
    initBlkLabel( &loop->u.l.continue_loop );
    loop->u.l.top_loop = CgFrontLabelCs();
    return( loop );
}


static CSTACK *beginLoop( int id )
{
    CSTACK *loop;

    nextYYToken();
    loop = beginLoopControl( id );
    dumpCSLabel( loop->u.l.top_loop );
    return( loop );
}

static void parseWhileStmt( void )
{
    CSTACK *loop;

    loop = beginLoop( CS_WHILE );
    openScope();
    if( EXPR_ANAL_OK == parseBracketExpr( &AnalyseBoolExpr ) ) {
        if( loop->expr_true ) {
            CgFrontCode( IC_EXPR_TRASH );
        } else if( loop->expr_false ) {
            CgFrontCode( IC_EXPR_TRASH );
            jumpBlkLabel( &loop->outside, O_GOTO );
        } else {
            jumpBlkLabel( &loop->outside, O_IF_FALSE );
        }
    } else {
        jumpBlkLabel( &loop->outside, O_GOTO );
        currFunction->dead_code = FALSE;
    }
}

static void parseForStmt( void )
{
    EXPR_ANAL test_type;
    EXPR_ANAL inc_type;
    PTREE test_expr;
    PTREE inc_expr;
    CSTACK *loop;
    CGLABEL around;
    boolean test_was_const;

    nextYYToken();
    mustRecog( T_LEFT_PAREN );
    if( ! CompFlags.use_old_for_scope ) {
        openScope();
    }
    if( CurToken == T_SEMI_COLON ) {
        mustRecog( T_SEMI_COLON );
    } else {
        ensureLiveCode();
        declExprStmt( TRUE );
    }
    if( CurToken == T_SEMI_COLON ) {
        test_type = EXPR_ANAL_NONE;
    } else {
        test_expr = safeParseExpr( T_SEMI_COLON );
        test_was_const = NodeIsConstantInt( test_expr );
        test_type = exprAnalyse( &AnalyseBoolExpr, &test_expr );
    }
    mustRecog( T_SEMI_COLON );
    if( CurToken != T_RIGHT_PAREN ) {
        inc_expr = safeParseExpr( T_RIGHT_PAREN );
        inc_type = exprAnalyse( &AnalyseStmtExpr, &inc_expr );
    } else {
        inc_type = EXPR_ANAL_NONE;
    }
    mustRecog( T_RIGHT_PAREN );
    loop = beginLoopControl( CS_FOR );
    switch( inc_type ) {
      case EXPR_ANAL_OK :
        around = CgFrontLabelCs();
        doJUMP( IC_LABEL_CS, O_GOTO, around );
        dumpCSLabel( loop->u.l.top_loop );
        emitCodeExpr( inc_expr );
        dumpCSLabel( around );
        CgFrontLabfreeCs( 1 );
        break;
      case EXPR_ANAL_NONE :
        dumpCSLabel( loop->u.l.top_loop );
        break;
    }
    if( test_type == EXPR_ANAL_OK ) {
        warnBoolConst( test_expr, test_was_const );
        emitCodeExpr( test_expr );
        if( loop->expr_true ) {
            CgFrontCode( IC_EXPR_TRASH );
        } else {
            jumpBlkLabel( &loop->outside, O_IF_FALSE );
        }
    }
    openScope();
}


static PTREE analyseSwitchExpr( // ANALYSE SWITCH EXPRESSION
    PTREE expr )            // - parsed expression
{
    CSTACK *switch_block;

    expr = AnalyseIntegralExpr( expr );
    if( expr->op != PT_ERROR ) {
        if( NULL != Integral64Type( expr->type ) ) {
            SetErrLoc( &expr->locn );
            CErr1( ERR_64BIT_SWITCH );
        }
        switch_block = currFunction->control;
        switch_block->u.s.type = expr->type;
        if( UnsignedIntType( expr->type ) ) {
            switch_block->u.s.is_signed = FALSE;
        } else {
            switch_block->u.s.is_signed = TRUE;
        }
    }
    return( expr );
}


static void parseSwitchStmt( void )
{
    CSTACK *switch_block;

    ensureLiveCode();
    nextYYToken();
    switch_block = beginControl( CS_SWITCH );
    switch_block->u.s.type = NULL;
    openScope();
    initBlkLabel( &switch_block->outside );
    switch_block->u.s.cases = NULL;
    switch_block->u.s.imm_block = NULL;
    switch_block->u.s.default_dropped = 0;
    switch_block->u.s.defn_scope = GetCurrScope();
    switch_block->u.s.is_signed = TRUE;
    switch_block->u.s.default_locn.src_file = NULL;
    SrcFileGetTokenLocn( &switch_block->u.s.switch_locn );
    parseBracketExpr( &analyseSwitchExpr );
    CgFrontSwitchBeg();
    LabelSwitchBeg();
    FunctionBodyDeadCode();
    openScope();
    if( ( CurToken == T_LEFT_BRACE ) || ( CurToken == T_ALT_LEFT_BRACE ) ) {
        switch_block->u.s.block_after = TRUE;
    } else {
        switch_block->u.s.block_after = FALSE;
    }
}

static boolean is_dup_case(     // DIAGNOSE A DUPLICATE CASE
    CSTACK *my_switch,          // - control-stack entry
    PTREE  case_value,          // - exprn for case
    unsigned err_code )         // - code for error message
{
    SWCASE *curr;               // - current case in search
    target_ulong case_uint;     // - value to look for
    auto char buff[16];         // - buffer for duplicate value

    case_uint = case_value->u.uint_constant;
    RingIterBeg( my_switch->u.s.cases, curr ) {
        if( curr->value == case_uint ) {
            if( my_switch->u.s.is_signed ) {
                ltoa( case_value->u.int_constant, buff, 10 );
            } else {
                ultoa( case_value->u.uint_constant, buff, 10 );
            }
            CErr2p( err_code, buff );
            InfMsgPtr( INF_PREVIOUS_CASE, &curr->defined );
            return( TRUE );
        }
    } RingIterEnd( curr )
    return( FALSE );
}

static SWCASE *makeCaseEntry(   // MAKE CASE/DEFAULT ENTRY
    TOKEN_LOCN *srcposn,        // - position in source
    CSTACK *my_switch )         // - control information
{
    SWCASE *ce;
    PTREE case_value;
    boolean casted;

    case_value = safeParseExpr( T_COLON );
    ce = NULL;
    if( case_value == NULL ) {
        srcposn->src_file = NULL;
    } else {
        case_value = PTreeForceIntegral( case_value );
        if( case_value == NULL ) {
            srcposn->src_file = NULL;
        } else {
            *srcposn = case_value->locn;
            if( ( my_switch != NULL ) && ( my_switch->u.s.type != NULL ) ) {
                if( ! is_dup_case( my_switch
                                 , case_value
                                 , ERR_DUPLICATE_CASE_VALUE ) ) {
                    case_value = CastIntConstant( case_value
                                                , my_switch->u.s.type
                                                , &casted );
                    if( ( ! casted )
                      ||( ! is_dup_case( my_switch
                                       , case_value
                                       , ERR_DUPLICATE_CONV_CASE_VALUE ) ) ) {
                        if( NULL == Integral64Type( case_value->type ) ) {
                            ce = CarveAlloc( carveSWCASE );
                            ce->next = NULL;
                            ce->value = case_value->u.uint_constant;
                            SrcFileGetTokenLocn( &ce->defined );
                        } else {
                            PTreeErrorExpr( case_value, ERR_64BIT_CASE );
                        }
                    }
                }
                LabelSwitch( my_switch->u.s.defn_scope );
            }
            PTreeFree( case_value );
        }
    }
    mustRecog( T_COLON );
    return( ce );
}

static CSTACK *findSwitch( void )
{
    CSTACK *curr;

    for( curr = currFunction->control
       ; ( curr != NULL ) && ( curr->id != CS_SWITCH )
       ; curr = curr->next );
    return( curr );
}


static void parseCaseStmt( void )
{
    CSTACK *my_switch;
    SWCASE *case_entry;
    TOKEN_LOCN srcposn;

    my_switch = findSwitch();
    if( my_switch == NULL ) {
        CErr1( ERR_MISPLACED_CASE );
        nextYYToken();
        case_entry = makeCaseEntry( &srcposn, NULL );
        if( case_entry != NULL ) {
            CarveFree( carveSWCASE, case_entry );
        }
        case_entry = NULL;
    } else {
        nextYYToken();
        case_entry = makeCaseEntry( &srcposn, my_switch );
    }
    if( case_entry == NULL ) {
        currFunction->dead_code = FALSE;
        return;
    }
    if( my_switch->u.s.cases == NULL ) {
        my_switch->u.s.lo = case_entry->value;
        my_switch->u.s.hi = case_entry->value;
    }
    CgFrontSwitchCase( my_switch->u.s.defn_scope
                     , currFunction->dead_code
                     , &srcposn
                     , case_entry->value );
    currFunction->dead_code = FALSE;
    RingAppend( &(my_switch->u.s.cases), case_entry );
    if( ( CurToken == T_RIGHT_BRACE ) || ( CurToken == T_ALT_RIGHT_BRACE ) ) {
        CErr1( ERR_STMT_REQUIRED_AFTER_CASE );
    }
}

static void genDefaultStmt(     // GENERATE A DEFAULT STATEMENT
    CSTACK *my_switch,          // - control block for switch
    TOKEN_LOCN *posn )          // - source position
{
    my_switch->u.s.default_dropped = TRUE;
    CgFrontSwitchDefault( my_switch->u.s.defn_scope
                        , currFunction->dead_code
                        , posn );
    currFunction->dead_code = FALSE;
}

static void parseDefaultStmt( void )
{
    CSTACK *my_switch;

    my_switch = findSwitch();
    if( my_switch == NULL ) {
        CErr1( ERR_MISPLACED_DEFAULT );
    } else if( my_switch->u.s.default_dropped ) {
        CErr1( ERR_ONLY_1_DEFAULT );
        InfMsgPtr( INF_PREVIOUS_DEFAULT, &my_switch->u.s.default_locn );
    } else {
        SrcFileGetTokenLocn( &my_switch->u.s.default_locn );
    }
    nextYYToken();
    mustRecog( T_COLON );
    if( ( my_switch == NULL )
      ||( my_switch->u.s.default_dropped ) ) {
        currFunction->dead_code = FALSE;
        return;
    }
    LabelSwitch( my_switch->u.s.defn_scope );
    genDefaultStmt( my_switch, &my_switch->u.s.default_locn );
    if( ( CurToken == T_RIGHT_BRACE ) || ( CurToken == T_ALT_RIGHT_BRACE ) ) {
        CErr1( ERR_STMT_REQUIRED_AFTER_DEFAULT );
    }
}

static CSTACK *findBreakable( void )
{
    CSTACK *curr;

    Stack_forall( currFunction->control, curr ) {
        switch( curr->id ) {
        case CS_FOR:

⌨️ 快捷键说明

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