示例#1
0
static PTREE doCopySubstitution( // EFFECT COPY SUBSTITUTION
    PTREE* a_repl,              // - addr[ temporary to be replaced ]
    PTREE orig,                 // - addr[ original node ]
    PTREE tgt,                  // - target
    PTREE dtor )                // - NULL or CO_DTOR node on right
{
    PTREE repl;                 // - temporary to be replaced

    repl = NodeRemoveCastsCommas( *a_repl );
    DbgVerify( repl->op == PT_SYMBOL, "doCopySubstitution -- not symbol" );
    DbgVerify( SymIsTemporary( repl->u.symcg.symbol )
             , "doCopySubstitution -- not temporary" );
    if( dtor != NULL ) {
        PTREE old = orig;
        DbgVerify( dtor->u.subtree[0]->u.symcg.symbol
                        == repl->u.symcg.symbol
                 , "doCopySubstitution -- not same temporary" );
        orig = dtor->u.subtree[1];
        dtor->u.subtree[1] = NULL;
        NodeFreeDupedExpr( old );
    }
    repl->u.symcg.symbol->flag = 0;
    *a_repl = NodeReplace( *a_repl, tgt );
    orig = NodeConvertFlags( ClassTypeForType( tgt->type )
                           , orig
                           , PTF_LVALUE
                           | PTF_MEMORY_EXACT
                           | PTF_SIDE_EFF
                           | PTF_MEANINGFUL );
    return orig;
}
示例#2
0
static PTREE pruneExpr(         // PRUNE ONE SIDE FROM EXPRESSION
    PTREE orig,                 // - original expression
    PTREE* ref,                 // - subtree[0] or [1] in orig
    PTREE undec )               // - undecorated result
{
    if( *ref == undec ) {
        *ref = NULL;
    } else {
        (*ref)->u.subtree[1] = NULL;
    }
    undec = PTreeCopySrcLocation( undec, orig );
    NodeFreeDupedExpr( orig );
    return undec;
}
示例#3
0
static PTREE makeTrueFalse( PTREE expr, PTREE op, int value )
{
    PTREE node;

    if(( op->flags & PTF_SIDE_EFF ) != 0 ) {
        return( expr );
    }
    if( anachronismFound( op ) ) {
        return( expr );
    }
    node = NodeOffset( value );
    node = NodeSetBooleanType( node );
    node = PTreeCopySrcLocation( node, expr );
    NodeFreeDupedExpr( expr );
    return( node );
}
示例#4
0
PTREE CopyOptimize              // COPY OPTIMIZATION
    ( PTREE right               // - base source operand (function call)
    , PTREE src                 // - original source operand
    , PTREE left                // - target operand
    , PTREE dtor                // - NULL or CO_DTOR expression
    , CALL_OPT opt )            // - type of optimization
{
    PTREE expr;                 // - resultant expression
    PTREE parm;                 // - parameter node to be replaced

    switch( opt ) {
      case CALL_OPT_NONE :
        DbgVerify( 0, "CopyOptimize -- CALL_OPT_NONE" );
        break;
      case CALL_OPT_CTOR :
        for( parm = right->u.subtree[1]
           ; 0 == ( parm->flags & PTF_ARG_THIS )
           ; parm = parm->u.subtree[0] ) ;
        expr = doCopyElimination( parm, src, left, dtor );
        break;
      case CALL_OPT_FUN_CALL :
        for( parm = right->u.subtree[1]
           ; 0 == ( parm->flags & PTF_ARG_RETURN )
           ; parm = parm->u.subtree[0] ) ;
        expr = doCopyElimination( parm, src, left, dtor );
        break;
      case CALL_OPT_BIN_COPY :
        expr = doCopySubstitution( &right->u.subtree[0], src, left, dtor );
        break;
      case CALL_OPT_ERR :
        PTreeErrorNode( left );
        NodeFreeDupedExpr( src );
        expr = left;
        break;
      DbgDefault( "CopyOptimize -- impossible optimization" );
    }
    return expr;
}
示例#5
0
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 );
}
示例#6
0
PTREE AnalyseCall(              // ANALYSIS FOR CALL
    PTREE expr,                 // - call expression
    CALL_DIAG *diagnostic )     // - diagnostics used for function problems
{
    PTREE *r_args;              // - reference( arguments )
    PTREE *r_func;              // - reference( function )
    PTREE *ptlist;              // - nodes for arguments
    PTREE left;                 // - left operand ( the function )
    PTREE right;                // - right operand ( the arguments )
    PTREE this_node;            // - node for "this" computation
    PTREE deref_args;           // - member pointer dereference args
    PTREE last_arg;             // - last argument
    PTREE static_fn_this;       // - "this" for a static member
    PTREE templ_args;           // - explicit template arguments
    SYMBOL sym;                 // - function symbol
    SYMBOL caller_sym;          // - function that is doing the call
    TYPE type;                  // - temporary type
    TYPE fn_type;               // - function type
    type_flag fn_mod;           // - function modifier flags
    unsigned count;             // - # args, caller
    arg_list *alist;            // - arg_list for caller
    intrinsic_mapping *intr_map;// - mapping for intrinsic function
    SEARCH_RESULT *result;      // - searching result
    boolean membptr_deref;      // - TRUE ==> member pointer dereference
    boolean has_ellipsis;       // - TRUE ==> ellipsis in argument list
    boolean virtual_call;       // - TRUE ==> virtual call
    TEMP_PT_LIST default_list;  // - default PTREE list
    TEMP_ARG_LIST default_args; // - default arg_list
    FNOV_DIAG fnov_diag;        // - diagnosis information;

    r_args = PTreeRefRight( expr );
    last_arg = *r_args;
    right = NodeReverseArgs( &count, last_arg );
    *r_args = right;
    r_func = PTreeRefLeft( expr );
    left = *r_func;
    membptr_deref = FALSE;
    this_node = NULL;
    intr_map = NULL;
    static_fn_this = NULL;
    virtual_call = FALSE;
    switch( left->cgop ) {
      case CO_DOT:
      case CO_ARROW:
        this_node = left->u.subtree[0];
        left->u.subtree[0] = NULL;
        left = NodePruneTop( left );
        *r_func = left;
        r_func = PTreeRefLeft( expr );
        left = *r_func;
        if( ( left->op == PT_ID ) && ( left->cgop == CO_NAME_DTOR ) ) {
            /* dtor of a non-class type */
            left = NodePruneTop( *r_func );
            /* NYI: verify dtor call has no arguments */
            expr->u.subtree[0] = NULL;
            NodeFreeDupedExpr( expr );
            expr = NodeConvert( GetBasicType( TYP_VOID ), this_node );
            expr = NodeComma( expr, left );
            return( expr );
        }
        break;
      case CO_CALL_EXEC_IND:
        if( left->flags & PTF_CALLED_ONLY ) {
            /* member pointer dereference being called */
            deref_args = left->u.subtree[1];
            this_node = NodeDupExpr( &(deref_args->u.subtree[1]) );
            membptr_deref = TRUE;
        }
        break;
    }
    alist = ArgListTempAlloc( &default_args, count );
    ptlist = PtListAlloc( default_list, count );
    NodeBuildArgList( alist, ptlist, right, count );
    if( this_node == NULL ) {
        alist->qualifier = FunctionThisQualifier();
    } else {
        alist->qualifier = BaseTypeClassFlags( NodeType( this_node ) );
    }

    if( NodeIsBinaryOp( left, CO_TEMPLATE ) ) {
        DbgAssert( left->u.subtree[0]->op == PT_SYMBOL );

        templ_args = left->u.subtree[1];

        left->u.subtree[1] = NULL;
        left = NodePruneTop( left );
        *r_func = left;
        r_func = PTreeRefLeft( expr );
        left = *r_func;
    } else {
        templ_args = NULL;
    }

    if( left->op == PT_SYMBOL ) {
        FNOV_RESULT ovret;
        SYMBOL orig;        // - original symbol
        sym = left->u.symcg.symbol;
        orig = sym;
        if( left->cgop == CO_NAME_CONVERT ) {
            ovret = UdcOverloadedDiag( &sym
                                 , left->u.symcg.result
                                 , sym
                                 , SymFuncReturnType( sym )
                                 , alist->qualifier
                                 , &fnov_diag );
        } else {
            ovret = FuncOverloadedDiag( &sym
                                   , left->u.symcg.result
                                   , sym
                                   , alist
                                   , ptlist
                                   , templ_args
                                   , &fnov_diag );
        }

        switch( ovret ) {
          case FNOV_AMBIGUOUS :
            CallDiagAmbiguous( expr, diagnostic->msg_ambiguous, &fnov_diag );
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
          case FNOV_NO_MATCH :
            if( this_node == NULL ) {
                if( SymIsThisFuncMember( orig ) ) {
                    this_node = NodeThisCopyLocation( left );
                }
            }
            if( this_node != NULL ) {
                if( ( ! SymIsCtor( orig ) )
                  &&( ! SymIsDtor( orig ) )
                  &&( CNV_OK != AnalysePtrCV
                                ( this_node
                                , TypeThisSymbol( orig
                                                , this_node->flags & PTF_LVALUE )
                                , NodeType( this_node )
                                , CNV_FUNC_THIS ) ) ) {
                    PTreeErrorNode( expr );
                    InfSymbolDeclaration( orig );
                    NodeFreeDupedExpr( this_node );
                    ArgListTempFree( alist, count );
                    PtListFree( ptlist, count );
                    return( expr );
                }
            }
            CallDiagNoMatch( expr
                           , diagnostic->msg_no_match_one
                           , diagnostic->msg_no_match_many
                           , this_node
                           , orig
                           , &fnov_diag );
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
        }
        FnovFreeDiag( &fnov_diag );
        left->u.symcg.symbol = sym;
        result = left->u.symcg.result;
        if( this_node == NULL ) {
            if( SymIsThisFuncMember( sym ) ) {
                if( result->use_this ) {
                    this_node = NodeThisCopyLocation( left );
                    if( this_node == NULL ) {
                        PTreeErrorExpr( expr, ERR_INVALID_NONSTATIC_ACCESS );
                        InfSymbolDeclaration( sym );
                        ArgListTempFree( alist, count );
                        PtListFree( ptlist, count );
                        return( expr );
                    }
                } else {
                    PTreeErrorExpr( expr, ERR_BARE_FUNCTION_ACCESS );
                    InfSymbolDeclaration( sym );
                    ArgListTempFree( alist, count );
                    PtListFree( ptlist, count );
                    return( expr );
                }
            }
        }
        if( ! AnalyseSymbolAccess( expr, left, this_node, &diagAccess ) ) {
            NodeFreeDupedExpr( this_node );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            return( expr );
        }
        type = sym->sym_type;
        fn_type = TypeGetActualFlags( type, &fn_mod );
        if( fn_type->flag & TF1_INTRINSIC ) {
            intr_map = intrinsicMapping( sym );
            if( intr_map == NULL ) {
                outputCallTriggeredWarning( expr, sym );
            }
        }
        if( fn_mod & TF1_FAR16 ) {
            /* we are calling a far16 function */
            caller_sym = ScopeFunctionInProgress();
            caller_sym->flag |= SF_FAR16_CALLER;
        }
        left->type = type;
        if( this_node == NULL ) {
            if( SymIsThisFuncMember( sym ) ) {
                this_node = NodeThisCopyLocation( left );
            }
        } else {
            if( SymIsStaticFuncMember( sym ) ) {
                #ifdef OLD_STATIC_MEMBER_ACCESS
                    NodeFreeDupedExpr( this_node );
                #else
                    static_fn_this = this_node;
                #endif
                this_node = NULL;
            }
        }
        if( this_node != NULL ) {
            TYPE pted;
            pted = TypePointedAtModified( this_node->type );
            if( pted == NULL ) {
                pted = this_node->type;
            }
            if( TypeTruncByMemModel( pted ) ) {
                if( SymIsCtor( sym ) ) {
                    PTreeErrorExpr( this_node, ERR_CTOR_OBJ_MEM_MODEL );
                } else if( SymIsDtor( sym ) ) {
                    PTreeErrorExpr( this_node, ERR_DTOR_OBJ_MEM_MODEL );
                } else {
                    PTreeErrorExpr( this_node, ERR_THIS_OBJ_MEM_MODEL );
                }
                InfSymbolDeclaration( sym );
                PTreeErrorNode( expr );
                NodeFreeDupedExpr( this_node );
                ArgListTempFree( alist, count );
                PtListFree( ptlist, count );
                NodeFreeDupedExpr( static_fn_this );
                return( expr );
            }
            if( adjustForVirtualCall( &this_node, r_func, result ) ) {
                virtual_call = TRUE;
                expr->cgop = CO_CALL_EXEC_IND;
                left = VfunSetupCall( expr->u.subtree[0] );
                left = VfnDecorateCall( left, sym );
            } else {
                expr->cgop = CO_CALL_EXEC;
                left = NodeUnaryCopy( CO_CALL_SETUP, expr->u.subtree[0] );
                SymMarkRefed( sym );
            }
        } else {
            NodeFreeSearchResult( left );
            expr->cgop = CO_CALL_EXEC;
            left = NodeUnaryCopy( CO_CALL_SETUP, expr->u.subtree[0] );
            SymMarkRefed( sym );
        }
    } else {
        if( ! membptr_deref ) {
            /* i.e, p->foo() where foo is a pointer to a function */
            NodeFreeDupedExpr( this_node );
            this_node = NULL;
        }
        sym = NULL;
        left = expr->u.subtree[0];
        type = TypedefModifierRemove( left->type );
        if( type->id == TYP_POINTER ) {
            type = type->of;
        }
        fn_type = TypeGetActualFlags( type, &fn_mod );
        if( fn_mod & TF1_FAR16 ) {
            /* we are calling a far16 function */
            caller_sym = ScopeFunctionInProgress();
            caller_sym->flag |= SF_FAR16_CALLER;
        }
        if( ! TypeHasNumArgs( type, count ) ) {
            PTreeErrorExpr( expr, ERR_PARM_COUNT_MISMATCH_POINTER );
            CErr2p( INF_FUNCTION_TYPE, type );
            ArgListTempFree( alist, count );
            PtListFree( ptlist, count );
            NodeFreeDupedExpr( static_fn_this );
            return( expr );
        }
        expr->cgop = CO_CALL_EXEC_IND;
        left = VfunSetupCall( left );
    }
    expr->u.subtree[0] = left;
#if _CPU == _AXP
    if( intr_map != NULL && intr_map->cgop == CO_VASTART ) {
        expr = convertVaStart( expr, alist, type );
    } else {
        expr = NodeConvertCallArgList( expr, count, type, &expr->u.subtree[1] );
    }
#else
    expr = NodeConvertCallArgList( expr, count, type, &expr->u.subtree[1] );
#endif
    if( expr->op != PT_ERROR ) {
        TYPE ftype;             // - function type
        PTREE cdtor;            // - CDTOR node
        PTREE callnode;         // - call node
        PTREE retnnode;         // - return node (for struct return)
        callnode = expr;
        if( this_node == NULL ) {
            cdtor = NULL;
        } else {
            this_node = NodeArg( this_node );
            if( virtual_call ) {
                this_node->flags |= PTF_ARG_THIS_VFUN;
            }
            if( sym != NULL && SymIsDtor( sym ) ) {
                cdtor = NodeArg( NodeCDtorArg( DTOR_NULL ) );
            } else {
                cdtor = NULL;
            }
        }
        ftype = type;
        type = TypedefModifierRemove( type );
        has_ellipsis = TypeHasEllipsisArg( type );
        type = type->of;
        {
            TYPE tgt = TypeReference( type );
            if( tgt == NULL ) {
                expr->type = type;
            } else {
                expr->type = tgt;
                expr->flags |= PTF_LVALUE;
            }
        }
        if( sym != NULL ) {
            if( ! AddDefaultArgs( sym, expr ) ) {
                NodeFreeDupedExpr( cdtor );
                NodeFreeDupedExpr( this_node );
                ArgListTempFree( alist, count );
                PtListFree( ptlist, count );
                return expr;
            }
        }
        if( NULL != TypeReference( type ) ) {
            expr->flags |= PTF_LVALUE;
        }
        if( OMR_CLASS_REF == ObjModelArgument( type ) ) {
            retnnode = NodeTemporary( type );
            retnnode = PTreeCopySrcLocation( retnnode, expr );
        } else {
            retnnode = NULL;
        }
        expr = CallArgsArrange( ftype
                              , callnode
                              , callnode->u.subtree[1]
                              , this_node
                              , cdtor
                              , retnnode );
        if( retnnode != NULL ) {
            expr = NodeDtorExpr( expr, retnnode->u.symcg.symbol );
            if( SymRequiresDtoring( retnnode->u.symcg.symbol ) ) {
                expr = PtdCtoredExprType( expr, NULL, type );
            }
        }
        type = StructType( type );
        if( type != NULL && ! TypeDefined( type ) ) {
            PTreeErrorExpr( expr, ERR_RETURN_UNDEFD_TYPE );
        }
        if( intr_map != NULL && expr->op != PT_ERROR ) {
#if _CPU == _AXP
            if( intr_map->cgop == CO_VASTART ) {
                expr = transformVaStart( expr );
            } else {
                expr = PTreeIntrinsicOperator( expr, intr_map->cgop );
            }
#else
            expr = PTreeIntrinsicOperator( expr, intr_map->cgop );
#endif
            expr->flags |= PTF_MEANINGFUL | PTF_SIDE_EFF;
        }
    }
    if( static_fn_this != NULL ) {
        expr = NodeCommaIfSideEffect( static_fn_this, expr );
    }
    ArgListTempFree( alist, count );
    PtListFree( ptlist, count );
    return expr;
}
示例#7
0
static PTREE transformVaStart   // TRANSFORM TO CO_VASTART OPCODE
    ( PTREE expr )              // - va_start expression
{
    SYMBOL pre_ellipsis_sym;
    SYMBOL stop;
    SYMBOL curr;
    SYMBOL fn;
    SCOPE caller_arg_scope;
    unsigned offset;
    target_size_t arg_size;
    PTREE arg1;
    PTREE arg2;
    PTREE arg3;
    PTREE valist;

    // second argument -- must be pre-... parameter
    arg1 = expr->u.subtree[1];
    arg2 = arg1->u.subtree[0];
    arg3 = arg2->u.subtree[0];
    pre_ellipsis_sym = PTreeOp( &arg2->u.subtree[1] )->u.symcg.symbol;
    caller_arg_scope = ScopeFunctionScopeInProgress();
    fn = ScopeFunction( caller_arg_scope );
    offset = 0;
    if( ObjModelFunctionReturn( fn->sym_type ) == OMR_CLASS_VAL ) {
        offset += TARGET_PACKING;
    }
    if( SymIsThisMember( fn ) ) {
        offset += TARGET_PACKING;
        if( SymCDtorExtraParm( fn ) ) {
            offset += TARGET_PACKING;
        }
    }
    stop = ScopeOrderedStart( caller_arg_scope );
    curr = NULL;
    for(;;) {
        curr = ScopeOrderedNext( stop, curr );
        if( curr == NULL ) {
            PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
            return( expr );
        }
        if( ObjModelArgument( curr->sym_type ) == OMR_CLASS_REF ) {
            arg_size = TARGET_PACKING;
        } else {
            arg_size = CgMemorySize( curr->sym_type );
            arg_size += TARGET_PACKING - 1;
            arg_size &= ~( TARGET_PACKING - 1 );
        }
        offset += arg_size;
        if( curr == pre_ellipsis_sym ) break;
    }
    if( ScopeOrderedNext( stop, curr ) != NULL ) {
        PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
        return( expr );
    }
    // third argument -- va_list symbol
    valist = arg1->u.subtree[1];
    arg1->u.subtree[1] = NULL;
    if( arg3->u.subtree[1]->u.int_constant == 0 ) {
        // compensate for "void *__alist;" arg in <varargs.h>
        offset -= TARGET_PACKING;
    }
    NodeFreeDupedExpr( expr );
    expr = NodeBinary( CO_VASTART, valist, NodeOffset( offset ) );
    return expr;
}