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