asexpr.c

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

C
506
字号
                r_val = (double)CONST_VALUE( right );
            } else {
                r_val = FP_CONST_VALUE( right );
            }
            switch( tree->type ) {
            case ET_TIMES:
                result = l_val * r_val;
                break;
            case ET_DIVIDE:
                result = l_val / r_val;
                break;
            case ET_MOD:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            case ET_PLUS:
                result = l_val + r_val;
                break;
            case ET_MINUS:
                result = l_val - r_val;
                break;
            case ET_SHIFT_L:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            case ET_SHIFT_R:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            case ET_OR:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            case ET_XOR:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            case ET_AND:
                Error( ILLEGAL_BINARY_EXPR );
                break;
            default:
                Error( UNEXPECTED_BINARY_CLASS );
            }
            FP_CONST_VALUE( tree ) = result;
            tree->type = ET_FP_CONSTANT;
        }
        etFree( left );
        etFree( right );
    }
    return( tree );
}

static expr_tree *relocFold( expr_tree *tree ) {
/***********************************************
    Any time we have a '+' or '-' node, one of the operands
    could be a relocatable constant. In order to handle this,
    all adds and subtracts come through this routine instead
    of binaryFold.
*/
    expr_tree   *left;
    expr_tree   *right;
    signed_32   factor;

    assert( tree->type == ET_PLUS || tree->type == ET_MINUS );
    factor = ( tree->type == ET_PLUS ? 1 : -1 );
    left = ETBurn( BINARY_LEFT( tree ) );
    right = ETBurn( BINARY_RIGHT( tree ) );
    if( _IsLeaf( left->type ) && _IsLeaf( right->type ) ) {
        if( left->type == ET_RELOCATABLE || left->type == ET_UNNAMED_RELOCATABLE ) {
            if( right->type == ET_CONSTANT ) {
                /* reloc +/- constant -> ok */
                RELOC_TARGET( tree ) = RELOC_TARGET( left );
                RELOC_TYPE( tree ) = RELOC_TYPE( left );
                RELOC_DISP( tree ) = RELOC_DISP( left );
                RELOC_DISP( tree ) += CONST_VALUE( right ) * factor;
                tree->type = left->type;
                etFree( left );
                etFree( right );
            } else {
                /* reloc +/- reloc -> ok if - */
                /* FIXME - need some symbol table magic here */
            }
        } else {
            if( right->type == ET_RELOCATABLE || right->type == ET_UNNAMED_RELOCATABLE ) {
                /* constant +/- reloc -> ok if + */
                if( tree->type == ET_PLUS ) {
                    RELOC_TARGET( tree ) = RELOC_TARGET( right );
                    RELOC_TYPE( tree ) = RELOC_TYPE( right );
                    RELOC_DISP( tree ) = RELOC_DISP( right );
                    RELOC_DISP( tree ) += CONST_VALUE( left );
                    tree->type = right->type;
                    etFree( left );
                    etFree( right );
                }
            } else {
                /* constant +- constant -> call binary fold */
                tree = binaryFold( tree );
            }
        }
    }
    return( tree );
}

extern expr_tree *ETBurn( expr_tree *tree ) {
/********************************************
    Burn down the given tree as much as possible, returning
    whatever is left. Ideally, we will be left with a leaf
    but this is not always possible (an unresolved reloc which
    was part of the "reloc - reloc -> abs" deal).
*/
    switch( tree->type ) {
    case ET_CONSTANT:
    case ET_FP_CONSTANT:
    case ET_UNNAMED_RELOCATABLE:
    case ET_RELOCATABLE:
        break;
    case ET_NOT:
    case ET_UNARY_MINUS:
    case ET_PARENS:
        tree = unaryFold( tree );
        break;
    case ET_PLUS:
    case ET_MINUS:
        tree = relocFold( tree );
        break;
    case ET_TIMES:
    case ET_MOD:
    case ET_DIVIDE:
    case ET_SHIFT_L:
    case ET_SHIFT_R:
    case ET_AND:
    case ET_OR:
    case ET_XOR:
        tree = binaryFold( tree );
        break;
    }
    return( tree );
}

extern void ETFree( expr_tree *tree ) {
/**************************************
    Free up the entire sub tree.
*/

    switch( tree->type ) {
    case ET_CONSTANT:
    case ET_FP_CONSTANT:
    case ET_UNNAMED_RELOCATABLE:
    case ET_RELOCATABLE:
        break;
    case ET_NOT:
    case ET_UNARY_MINUS:
    case ET_PARENS:
        ETFree( UNARY_CHILD( tree ) );
        break;
    case ET_PLUS:
    case ET_MINUS:
    case ET_TIMES:
    case ET_MOD:
    case ET_DIVIDE:
    case ET_SHIFT_L:
    case ET_SHIFT_R:
    case ET_AND:
    case ET_OR:
    case ET_XOR:
        ETFree( BINARY_LEFT( tree ) );
        ETFree( BINARY_RIGHT( tree ) );
        break;
    }
    etFree( tree );
}

#ifdef _STANDALONE_
#ifndef NDEBUG
static char *nodeNames[] = {
    "Constant",         /* ET_CONSTANT */
    "FP Constant",      /* ET_FP_CONSTANT */
    "Unnamed Reloc",    /* ET_UNNAMED_RELOCATABLE */
    "Relocation",       /* ET_RELOCATABLE */
    "Not",              /* ET_NOT */
    "Parens",           /* ET_PARENS */
    "Unary Minus",      /* ET_UNARY_MINUS */
    "Times",            /* ET_TIMES */
    "Mod",              /* ET_MOD */
    "Divide",           /* ET_DIVIDE */
    "Plus",             /* ET_PLUS */
    "Minus",            /* ET_MINUS */
    "Shift_l",          /* ET_SHIFT_L */
    "Shift_r",          /* ET_SHIFT_R */
    "And",              /* ET_AND */
    "Xor",              /* ET_XOR */
    "Or"                /* ET_OR */
};

static void outIndent( int level ) {
/***********************************
    Tab the text out a little ways.
*/
    while( level-- ) {
        printf( "    " );
    }
}

static char *relocString[] = {
    "ASM_RELOC_WORD",
    "ASM_RELOC_HALF_HI",
    "ASM_RELOC_HALF_HA",
    "ASM_RELOC_HALF_LO",
    "ASM_RELOC_JUMP"
};

static void doDump( expr_tree *tree, int level ) {
/*************************************************
    Print a node at the given level of the tree.
*/
    switch( tree->type ) {
    case ET_CONSTANT:
        outIndent( level );
        printf( "%s(%ld)\n", nodeNames[ tree->type ], CONST_VALUE( tree ) );
        break;
    case ET_FP_CONSTANT:
        outIndent( level );
        printf( "%s(%lf)\n", nodeNames[ tree->type ], FP_CONST_VALUE( tree ) );
        break;
    case ET_UNNAMED_RELOCATABLE:
        outIndent( level );
        printf( "%s(#%d,%s,%ld)\n", nodeNames[ tree->type ], RELOC_LABELNUM( tree ), relocString[RELOC_TYPE( tree )], RELOC_DISP( tree ) );
        break;
    case ET_RELOCATABLE:
        outIndent( level );
        printf( "%s(%lx,%s,%ld)\n", nodeNames[ tree->type ], RELOC_SYMBOL( tree ), relocString[RELOC_TYPE( tree )], RELOC_DISP( tree ) );
        break;
    case ET_NOT:
    case ET_UNARY_MINUS:
    case ET_PARENS:
        outIndent( level );
        printf( "%s\n", nodeNames[ tree->type ] );
        doDump( UNARY_CHILD( tree ), level + 1 );
        break;
    default:
        doDump( BINARY_RIGHT( tree ), level + 1 );
        outIndent( level );
        printf( "%s\n", nodeNames[ tree->type ] );
        doDump( BINARY_LEFT( tree ), level + 1 );
        break;
    }
}

extern void ETDump( expr_tree *tree ) {
/**************************************
    Dump a copy of the tree to stdout.
*/
    doDump( tree, 0 );
    fflush( stdout );
}
#endif
#endif

⌨️ 快捷键说明

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