static bool zeroConstant( // TEST IF NODE IS ZERO CONSTANT PTREE expr ) // - the expression { PTREE orig; switch( expr->op ) { case PT_INT_CONSTANT: if( NULL == Integral64Type( expr->type ) ) { return( expr->u.int_constant == 0 ); } else { return( Zero64( &expr->u.int64_constant ) ); } case PT_FLOATING_CONSTANT: { target_ulong ul_val = BFCnvF32( expr->u.floating_constant ); return 0 == ul_val; } case PT_BINARY: orig = expr; expr = NodeRemoveCasts( expr ); if( expr == orig ) break; return( zeroConstant( expr ) ); } return( false ); }
static void dumpPTreeNode( // DUMP A PARSE TREE NODE PTREE node ) // - node in parse tree { static char buffer[128]; // - debugging buffer char *node_name; // - name of node VSTK_CTL ctl; // - VSTK control information (nodes) VSTK_CTL dup; // - VSTK control information (duplicates) int dup_out; // - last duplicate printed VstkOpen( &ctl, sizeof( PTREE ), 32 ); VstkOpen( &dup, sizeof( PTREE ), 8 ); dup_out = -1; for( ; ; ) { switch( node->op ) { case PT_ERROR : printf( "PT_ERROR" F_BADDR " ***** ERROR TREE *****" F_EOL , node ); break; case PT_INT_CONSTANT : node_name = "PT_INT_CONSTANT"; printf( F_NAME F_BADDR " flags" F_HEX_4 " type" F_PTR , node_name , node , node->flags , node->type ); if( NULL == Integral64Type( node->type ) ) { printf( " integer" F_HEX_4 , node->u.int_constant ); } else { printf( " integer-64" F_S64 , VAL64( node->u.int64_constant ) ); } dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; case PT_FLOATING_CONSTANT : { char buffer[256]; BFCnvFS( node->u.floating_constant, buffer, 256 ); printf( "PT_FLOATING_CONSTANT" F_BADDR " flags" F_HEX_4 " float" F_CPP_FLOAT , node , node->flags , buffer ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); } break; case PT_STRING_CONSTANT : stvcpy( buffer, node->u.string->string, node->u.string->len ); printf( "PT_STRING_CONSTANT" F_BADDR " flags" F_HEX_4 " string" F_STRING , node , node->flags , buffer ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; case PT_ID : printf( "PT_ID" F_BADDR " flags" F_HEX_4 " cgop" F_STRING F_NL " id" F_PTR "=" F_STRING " id_cgop" F_STRING " u.id.scope" F_PTR , node , node->flags , DbgOperator( node->cgop ) , node->u.id.name , NameStr( node->u.id.name ) , DbgOperator( node->id_cgop ) , node->u.id.scope ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; case PT_TYPE : printf( "PT_TYPE" F_BADDR " cgop" F_STRING " flags" F_HEX_4 " next" F_PTR " scope" F_PTR , node , DbgOperator( node->cgop ) , node->flags , node->u.type.next , node->u.type.scope ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; case PT_SYMBOL : if( node->cgop == CO_NAME_THIS ) { printf( "PT_SYMBOL" F_BADDR " flags" F_HEX_4 " this " , node , node->flags ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); } else if( node->cgop == CO_NAME_CDTOR_EXTRA ) { printf( "PT_SYMBOL" F_BADDR " flags" F_HEX_4 " cdtor_extra_parm " , node , node->flags ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); } else { printf( "PT_SYMBOL" F_BADDR " flags" F_HEX_4 " cgop" F_STRING F_NL " symbol" F_PTR " result" F_PTR , node , node->flags , DbgOperator( node->cgop ) , node->u.symcg.symbol , node->u.symcg.result ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); DumpSymbol( node->u.symcg.symbol ); } break; case PT_UNARY : printf( "PT_UNARY" F_BADDR F_POINTS F_ADDR " flags" F_HEX_4 " cgop" F_STRING , node , node->u.subtree[0] , node->flags , DbgOperator( node->cgop ) ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); PUSH_NODE( ctl, node->u.subtree[0] ); break; case PT_BINARY : printf( "PT_BINARY" F_BADDR F_POINTS F_ADDR "," F_ADDR " flags" F_HEX_4 " cgop" F_STRING , node , node->u.subtree[0] , node->u.subtree[1] , node->flags , DbgOperator( node->cgop ) ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); PUSH_NODE( ctl, node->u.subtree[1] ); PUSH_NODE( ctl, node->u.subtree[0] ); break; case PT_DUP_EXPR : { PTREE *duped; // - duplicated expression printf( "PT_DUP_EXPR" F_BADDR F_POINTS F_ADDR " flags" F_HEX_4 " node" F_ADDR , node , node->u.dup.subtree[0] , node->flags , node->u.dup.node ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); if( node->u.subtree[0] != NULL ) { for( duped = VstkTop( &dup ) ; ; duped = VstkNext( &dup, duped ) ) { if( duped == NULL ) { PUSH_NODE( dup, node->u.subtree[0] ); } else if( *duped == node->u.subtree[0] ) { break; } } } } break; case PT_IC : printf( "PT_IC" F_BADDR " " F_NAME " value" F_ADDR , node , DbgIcOpcode( node->u.ic.opcode ) , node->u.ic.value.pvalue ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; default : printf( "***INVALID***" F_BADDR " flags" F_HEX_4 " op" F_HEX_1 , node , node->flags , node->op ); dumpNodeType( node ); dumpLocation( &node->locn ); dumpPtreeFlags( node ); break; } { PTREE *next; // - addr[next node] next = VstkPop( &ctl ); if( next != NULL ) { node = *next; } else { ++dup_out; if( dup_out > VstkDimension( &dup ) ) break; next = VstkIndex( &dup, dup_out ); printf( "--------------- duplicate ------------\n" ); node = *next; } } } VstkClose( &ctl ); VstkClose( &dup ); }
PTREE CastIntConstant( PTREE expr, TYPE type, bool *happened ) { PTREE new_expr; target_ulong ul_val; float_handle dbl_val; type_id id; bool signed_type; signed_type = SignedIntType( expr->type ); id = TypedefModifierRemove( type )->id; ul_val = expr->u.uint_constant; if( NULL == Integral64Type( expr->type ) ) { switch( id ) { case TYP_SCHAR: ul_val = (target_schar) ul_val; /* fall through */ case TYP_SSHORT: ul_val = (target_short) ul_val; /* fall through */ case TYP_SINT: ul_val = (target_int) ul_val; /* fall through */ case TYP_SLONG: ul_val = (target_long) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; case TYP_UCHAR: ul_val = (target_uchar) ul_val; /* fall through */ case TYP_USHORT: ul_val = (target_ushort) ul_val; /* fall through */ case TYP_UINT: ul_val = (target_uint) ul_val; /* fall through */ case TYP_ULONG: ul_val = (target_ulong) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; case TYP_ULONG64: case TYP_SLONG64: if( PT_FLOATING_CONSTANT == expr->op ) { new_expr = PTreeInt64Constant ( BFCnvF64( expr->u.floating_constant ) , id ); } else { new_expr = PTreeInt64Constant( expr->u.int64_constant, id ); } break; case TYP_POINTER: case TYP_MEMBER_POINTER: ul_val = (target_ulong) ul_val; new_expr = PTreeIntConstant( ul_val, TYP_ULONG ); new_expr->type = type; break; case TYP_FLOAT: #if 0 // these are now identical, with canonical floating point if( signed_type ) { flt_val = BFCnvIF( expr->u.int_constant ); } else { flt_val = BFCnvUF( expr->u.uint_constant ); } new_expr = PTreeFloatingConstant( flt_val, id ); break; #endif case TYP_LONG_DOUBLE: case TYP_DOUBLE: if( signed_type ) { dbl_val = BFCnvIF( expr->u.int_constant ); } else { dbl_val = BFCnvUF( expr->u.uint_constant ); } new_expr = PTreeFloatingConstant( dbl_val, id ); break; case TYP_WCHAR: ul_val = (target_wchar) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; default: return( expr ); } } else { ul_val = expr->u.int_constant; switch( id ) { case TYP_SCHAR: ul_val = (target_schar) ul_val; /* fall through */ case TYP_SSHORT: ul_val = (target_short) ul_val; /* fall through */ case TYP_SINT: ul_val = (target_int) ul_val; /* fall through */ case TYP_SLONG: ul_val = (target_long) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; case TYP_SLONG64: case TYP_ULONG64: new_expr = PTreeInt64Constant( expr->u.int64_constant, id ); break; case TYP_UCHAR: ul_val = (target_uchar) ul_val; /* fall through */ case TYP_USHORT: ul_val = (target_ushort) ul_val; /* fall through */ case TYP_UINT: ul_val = (target_uint) ul_val; /* fall through */ case TYP_ULONG: ul_val = (target_ulong) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; case TYP_POINTER: case TYP_MEMBER_POINTER: ul_val = (target_ulong) ul_val; new_expr = PTreeIntConstant( ul_val, TYP_ULONG ); new_expr->type = type; break; case TYP_FLOAT: #if 0 // these are now identical, with canonical floating point if( signed_type ) { flt_val = BFCnvI64F( expr->u.int64_constant ); } else { flt_val = BFCnvU64F( expr->u.uint64_constant ); } new_expr = PTreeFloatingConstant( flt_val, id ); break; #endif case TYP_LONG_DOUBLE: case TYP_DOUBLE: if( signed_type ) { dbl_val = BFCnvI64F( expr->u.int64_constant ); } else { dbl_val = BFCnvU64F( expr->u.int64_constant ); } new_expr = PTreeFloatingConstant( dbl_val, id ); break; case TYP_WCHAR: ul_val = (target_wchar) ul_val; new_expr = PTreeIntConstant( ul_val, id ); break; default: return( expr ); } } *happened = true; new_expr->flags = expr->flags; new_expr = PTreeCopySrcLocation( new_expr, expr ); PTreeFree( expr ); return( new_expr ); }
PTREE FoldBinary( PTREE expr ) /****************************/ { PTREE orig1; PTREE orig2; PTREE op1; PTREE op2; PTREE op_t; PTREE op_f; PTREE op_test; TYPE type; unsigned typ1; unsigned typ2; bool cast_happened; bool has_decoration_left; bool has_decoration_right; bool has_decoration; type = expr->type; orig1 = expr->u.subtree[0]; orig2 = expr->u.subtree[1]; type = expr->type; op1 = overCondDecor( orig1 ); has_decoration_left = op1 != orig1; op2 = overCondDecor( orig2 ); has_decoration_right = op2 != orig2; has_decoration = has_decoration_left | has_decoration_left; if( notFoldable( op1 ) ) { if( notFoldable( op2 ) ) { return( expr ); } switch( expr->cgop ) { case CO_EQ: DbgVerify( ! has_decoration, "FoldBinary -- bad ==" ); if( zeroConstant( op2 ) ) { if( zeroConstant( op1 ) ) { expr = makeTrueFalse( expr, op1, 1 ); } else if( nonZeroExpr( op1 ) ) { expr = makeTrueFalse( expr, op1, 0 ); } } break; case CO_NE: DbgVerify( ! has_decoration, "FoldBinary -- bad !=" ); if( zeroConstant( op2 ) ) { if( zeroConstant( op1 ) ) { expr = makeTrueFalse( expr, op1, 0 ); } else if( nonZeroExpr( op1 ) ) { expr = makeTrueFalse( expr, op1, 1 ); } } break; case CO_PLUS_EQUAL : case CO_MINUS_EQUAL : case CO_AND_EQUAL : case CO_OR_EQUAL : case CO_XOR_EQUAL : case CO_EQUAL: /* have to be careful with pointer scaling of numbers */ DbgVerify( ! has_decoration, "FoldBinary -- bad equals" ); if( ArithType( type ) != NULL ) { expr->u.subtree[1] = castConstant( op2, type, &cast_happened ); } break; case CO_CONVERT: DbgVerify( ! has_decoration, "FoldBinary -- bad convert" ); op_test = castConstant( op2, type, &cast_happened ); if( cast_happened ) { /* op2 was freed */ op_test = PTreeCopySrcLocation( op_test, expr ); NodeFreeDupedExpr( op1 ); PTreeFree( expr ); return( op_test ); } break; case CO_COMMA : // // X, c -- can be optimized when X is PT_IC( IC_COND_TRUE ) // and comma node has PTF_COND_END set // if( (expr->flags & PTF_COND_END) && op1->op == PT_IC && op1->u.ic.opcode == IC_COND_TRUE ) { expr = pruneExpr( expr, &expr->u.subtree[1], op2 ); } break; } return( expr ); } if( notFoldable( op2 ) ) { switch( expr->cgop ) { case CO_EQ: DbgVerify( ! has_decoration, "FoldBinary -- bad ==" ); if( zeroConstant( op1 ) ) { if( zeroConstant( op2 ) ) { expr = makeTrueFalse( expr, op2, 1 ); } else if( nonZeroExpr( op2 ) ) { expr = makeTrueFalse( expr, op2, 0 ); } } break; case CO_NE: DbgVerify( ! has_decoration, "FoldBinary -- bad !=" ); if( zeroConstant( op1 ) ) { if( zeroConstant( op2 ) ) { expr = makeTrueFalse( expr, op2, 0 ); } else if( nonZeroExpr( op2 ) ) { expr = makeTrueFalse( expr, op2, 1 ); } } break; case CO_AND_AND: // DbgVerify( has_decoration, "FoldBinary -- bad &&" ); if( ! zeroConstant( op1 ) ) { /* 1 && X => X (X is already boolean) */ expr = pruneExpr( expr, &expr->u.subtree[1], op2 ); } else { /* 0 && X => 0 */ return pruneExpr( expr, &expr->u.subtree[0], op1 ); } break; case CO_OR_OR: // DbgVerify( has_decoration, "FoldBinary -- bad ||" ); if( zeroConstant( op1 ) ) { /* 0 || X => X (X is already boolean) */ return pruneExpr( expr, &expr->u.subtree[1], op2 ); } else { /* 1 || X => 1 */ return pruneExpr( expr, &expr->u.subtree[0], op1 ); } break; case CO_COMMA: /* c , X => X */ // DbgVerify( ! has_decoration, "FoldBinary -- bad comma" ); expr->u.subtree[1] = NULL; op2 = PTreeCopySrcLocation( op2, expr ); NodeFreeDupedExpr( expr ); return( op2 ); case CO_QUESTION: DbgVerify( ! has_decoration, "FoldBinary -- bad ?" ); op_t = op2->u.subtree[0]; op_f = op2->u.subtree[1]; has_decoration = isCondDecor( op_t ); DbgVerify( has_decoration == isCondDecor( op_f ) , "FoldBinary -- bad ?:" ); if( has_decoration ) { op_t = op_t->u.subtree[1]; op_f = op_f->u.subtree[1]; } if( ! zeroConstant( op1 ) ) { /* 1 ? T : F => T */ if( has_decoration ) { op2->u.subtree[0]->u.subtree[1] = NULL; } else { op2->u.subtree[0] = NULL; } op2 = op_t; } else { /* 0 ? T : F => F */ if( has_decoration ) { op2->u.subtree[1]->u.subtree[1] = NULL; } else { op2->u.subtree[1] = NULL; } op2 = op_f; } op2 = PTreeCopySrcLocation( op2, expr ); NodeFreeDupedExpr( expr ); return( op2 ); } } else { typ1 = op1->op; typ2 = op2->op; if( ! isIntFloatOp( typ1 ) || ! isIntFloatOp( typ2 ) ) { // (void)0 can make it here return expr; } if( typ1 != typ2 ) { if( PT_FLOATING_CONSTANT == typ1 ) { if( NULL == Integral64Type( op2->type ) ) { if( SignedIntType( op2->type ) ) { op2->u.floating_constant = BFCnvIF( op2->u.int_constant ); } else { op2->u.floating_constant = BFCnvUF( op2->u.uint_constant ); } } else { if( SignedIntType( op2->type ) ) { op2->u.floating_constant = BFCnvI64F( op2->u.int64_constant ); } else { op2->u.floating_constant = BFCnvU64F( op2->u.int64_constant ); } } typ2 = PT_FLOATING_CONSTANT; op2->op = typ2; } else { if( NULL == Integral64Type( op1->type ) ) { if( SignedIntType( op1->type ) ) { op1->u.floating_constant = BFCnvIF( op1->u.int_constant ); } else { op1->u.floating_constant = BFCnvUF( op1->u.uint_constant ); } } else { if( SignedIntType( op1->type ) ) { op1->u.floating_constant = BFCnvI64F( op1->u.int64_constant ); } else { op1->u.floating_constant = BFCnvU64F( op1->u.int64_constant ); } } typ1 = PT_FLOATING_CONSTANT; op1->op = typ2; } } if( PT_FLOATING_CONSTANT == typ1 ) { op1 = foldFloating( expr->cgop, op1, op2->u.floating_constant ); } else if( SignedIntType( op1->type ) ) { if( NULL == Integral64Type( op1->type ) && NULL == Integral64Type( op2->type ) ) { op1 = foldInt( expr->cgop, op1, op2->u.int_constant ); } else { op1 = foldInt64( expr->cgop, op1, op2->u.int64_constant ); } } else { if( NULL == Integral64Type( op1->type ) && NULL == Integral64Type( op2->type ) ) { op1 = foldUInt( expr->cgop, op1, op2->u.uint_constant ); } else { op1 = foldUInt64( expr->cgop, op1, op2->u.int64_constant ); } } if( op1 != NULL ) { /* binary op was folded! */ if( has_decoration ) { orig1->u.subtree[1] = NULL; orig2->u.subtree[1] = NULL; } else { expr->u.subtree[0] = NULL; } op1 = castConstant( op1, type, &cast_happened ); op1 = PTreeCopySrcLocation( op1, expr ); NodeFreeDupedExpr( expr ); return op1; } } return( expr ); }