analcall.c

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

C
1,248
字号
                        }
                    } else if( OMR_CLASS_VAL
                                == ObjModelArgument( cl_type ) ) {
                        passStructOnStack( arg, ERR_CALL_WATCOM );
                    }
                }
            }
        }
        TemporaryClass( old );
    }
    return( call_expr );
}


#if _CPU == _AXP
static boolean canCoaxVAStartSym( PTREE *parg )
{
    PTREE orig_arg;
    PTREE arg;

    /*
        The reason we need this complexity is that there exists C++ code
        that uses class templates instantiated on reference types but the
        class contains member functions that have ", T v0, ... )" so we
        have to forge ahead generating (possibly incorrect code) because
        the inline function must be compiled but will never be called!
        see COOL\PROPERTY.CPP
    */
    orig_arg = PTreeOp( parg );
    arg = orig_arg;
    if( NodeIsUnaryOp( arg, CO_FETCH ) ) {
        arg = arg->u.subtree[0];
    }
    if( NodeIsUnaryOp( arg, CO_RARG_FETCH ) ) {
        arg = arg->u.subtree[0];
    }
    if( arg->op != PT_SYMBOL ) {
        return( FALSE );
    }
    *parg = NodeComma( orig_arg, PTreeAssign( NULL, arg ) );
    return( TRUE );
}

static PTREE convertVaStart(    // CONVERT va_start function call
    PTREE expr,                 // - expression
    arg_list *alist,            // - arguments for caller
    TYPE type )                 // - function type
{
    PTREE arg;
    arg_list *plist;            // - prototype arguments
    PTREE right;                // - right operand

    if( alist->num_args != 3 ) {
        return expr;
    }
    plist = TypeArgList( type );
    // va_list symbol
    arg = expr->u.subtree[1];
    if( ! arg_convert( arg, plist->type_list[0] ) ) {
        PTreeErrorNode( expr );
        return expr;
    }
    // second argument -- must be parameter to current function
    // - here we check for symbol
    // - we check that it is a parameter in transformVaStart
    arg = arg->u.subtree[0];
    right = PTreeOp( &arg->u.subtree[1] );
    if( right->op != PT_SYMBOL ) {
        if( ! canCoaxVAStartSym( &arg->u.subtree[1] ) ) {
            PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
            return expr;
        }
    }
    // third argument -- must be 0 or one
    arg = arg->u.subtree[0];
    right = PTreeOp( &arg->u.subtree[1] );
    if( right->op != PT_INT_CONSTANT ) {
        PTreeErrorExpr( expr, ERR_INVALID_VASTART_SYMBOL );
        return expr;
    }
    return expr;
}


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;
}
#endif


static boolean adjustForVirtualCall( // ADJUSTMENTS FOR POSSIBLE VIRTUAL CALL
    PTREE *this_node,           // - addr[ "this" node ]
    PTREE *routine,             // - routine to be called
    SEARCH_RESULT *result )     // - search result for routine
{
    SYMBOL sym;                 // - symbol for call
    unsigned retn;              // - return: TRUE ==> adjusted for virtual
    TYPE this_type;             // - target type for "this"
    PTREE expr;                 // - transformed expression
    boolean exact_call;         // - TRUE ==> this node is exact

    expr = *this_node;
    this_type = NodeType( expr );
    this_type = StructType( this_type );
    if( this_type != NULL ) {
        if( OMR_CLASS_VAL == ObjModelArgument( this_type ) ) {
            expr = NodeAssignTemporary( this_type, expr );
        } else {
            expr = NodeConvert( MakePointerTo( expr->type ), expr );
        }
        *this_node = expr;
    }
    sym = (*routine)->u.symcg.symbol;
    this_type = TypeThisForCall( expr, sym );
    /* virtual calls don't have to check for NULL pointers when they convert */
    expr->flags |= PTF_PTR_NONZERO;
    exact_call = expr->flags & PTF_MEMORY_EXACT;
    NodeConvertToBasePtr( this_node, this_type, result, TRUE );
    sym = SymDefaultBase( sym );
    if( ( SymIsVirtual( sym ) )
      &&( ! ( (*routine)->flags & PTF_COLON_QUALED ) )
      &&( ! exact_call ) ) {
        expr = AccessVirtualFnAddress( NodeDupExpr( this_node )
                                     , result
                                     , sym );
        expr->type = MakePointerTo( expr->type );
        *routine = NodeReplace( *routine, expr );
        retn = TRUE;
    } else {
        NodeFreeSearchResult( *routine );
        retn = FALSE;
    }
    return( retn );
}


static intrinsic_mapping* intrinsicMapping // GET INTRINSIC MAPPING
    ( SYMBOL sym )
{
    char *name;
    intrinsic_mapping *curr;

    name = sym->name->name;
    for( curr = mapIntrinsic; ; ++curr ) {
        const char* iname = curr->name;
        if( iname == NULL ) {
            curr = NULL;
            break;
        }
        /* it would be nice to do a pointer compare but we would
           need to convert the strings to NAMEs first (AFS) */
        if( strcmp( name, iname ) == 0 ) break;
    }
    return curr;
}


static PTREE insertArg(         // INSERT ARGUMENT BEFORE ARGUMENT SEQUENCE
    PTREE seq,                  // - argument sequence
    PTREE arg )                 // - argument
{
    if( seq == NULL ) {
        seq = arg;
    } else if( arg != NULL ) {
        arg->u.subtree[0] = seq;
        seq = arg;
    }
    return seq;
}


static PTREE appendArg(         // APPEND ARGUMENT AFTER ARGUMENT SEQUENCE
    PTREE seq,                  // - argument sequence
    PTREE arg )                 // - argument
{
    PTREE last;                 // - last arg in sequence

    if( seq == NULL ) {
        seq = arg;
    } else if( arg != NULL ) {
        for( last = seq
           ; last->u.subtree[0] != NULL
           ; last = last->u.subtree[0] );
        last->u.subtree[0] = arg;
    }
    return seq;
}


PC_CALLIMPL PcCallImpl(         // OBTAIN PC CALL IMPLEMENTATION
    TYPE ftype )                // - function type
{
    PC_CALLIMPL retn;           // - type of call implemented

    ftype = TypedefModifierRemove( ftype );
    if( TypeHasReverseArgs( ftype ) ) {
        if( ftype->flag & TF1_PLUSPLUS ) {
            retn = CALL_IMPL_REV_CPP;
        } else {
            retn = CALL_IMPL_REV_C;
        }
    } else if( TypeHasEllipsisArg( ftype ) ) {
        if( ftype->flag & TF1_PLUSPLUS ) {
            retn = CALL_IMPL_ELL_CPP;
        } else {
            retn = CALL_IMPL_ELL_C;
        }
    } else {
        if( ftype->flag & TF1_PLUSPLUS ) {
            retn = CALL_IMPL_CPP;
        } else {
            retn = CALL_IMPL_C;
        }
    }
    return retn;
}


static PTREE insertRetnCopy(    // INSERT COPY OF RETURN ON STACK
    PTREE callexpr,             // - call expression
    PTREE temp )                // - optional temporary
{
    if( temp != NULL ) {
        PTreeOpLeft( callexpr )->flags |= PTF_MEMORY_EXACT;
        callexpr->flags |= PTF_MEMORY_EXACT;
        callexpr = NodeCopyClassObject( temp, callexpr );
    }
    return callexpr;
}


static PTREE insertCppRetnArg(  // INSERT C++ RETURN ARGUMENT
    PTREE arglist,              // - argument list
    PTREE retnnode,             // - return node
    OMR return_kind )           // - kind of return
{
    if( return_kind == OMR_CLASS_REF ) {
        retnnode->flags |= PTF_ARG_RETURN;
        arglist = insertArg( arglist, NodeArg( retnnode ) );
    }
    return arglist;
}


static PTREE insertCppRetnCopy( // INSERT C++ RETURN COPY
    PTREE callnode,             // - node for call
    PTREE retnnode,             // - return node
    OMR return_kind )           // - kind of return
{
    switch( return_kind ) {
      case OMR_CLASS_VAL :
        callnode = insertRetnCopy( callnode, retnnode );
        break;
      case OMR_CLASS_REF :
        callnode->flags |= PTF_CLASS_RVREF;
        break;
    }
    return callnode;
}


static PTREE insertCDtor(       // INSERT CDTOR NODE INTO CALL LIST
    PTREE seq,                  // - argument sequence
    PTREE arg )                 // - argument
{
    PTREE* r_val;               // - reference[ arg value ]
    PTREE val;                  // - arg value

    if( arg != NULL ) {
        r_val = PTreeRefRight( arg );
        val = *r_val;
        if( val->op == PT_INT_CONSTANT ) {
            PTREE new_val = NodeIcUnsigned( IC_CDARG_VAL
                                          , val->u.uint_constant );
            new_val->type = val->type;
            *r_val = new_val;
            PTreeFree( val );
        }
    }
    return insertArg( seq, arg );
}


PTREE CallArgsArrange(          // ARRANGE CALL ARGUMENTS
    TYPE ftype,                 // - function type
    PTREE callnode,             // - node for call
    PTREE userargs,             // - user arguments
    PTREE thisnode,             // - this node
    PTREE cdtor,                // - cdtor node (ignored when thisnode==NULL)
    PTREE retnnode )            // - return node (for struct return)
{
    PTREE arglist;              // - argument list under construction
    OMR return_kind;            // - type of return

    if( thisnode != NULL ) {
        thisnode->flags |= PTF_ARG_THIS;
    }
    return_kind = ObjModelFunctionReturn( ftype );
    switch( PcCallImpl( ftype ) ) {
      case CALL_IMPL_REV_C :
        return_kind = OMR_CLASS_VAL;
        // drops thru
      case CALL_IMPL_REV_CPP :
        arglist = insertCDtor( thisnode, cdtor );
        arglist = insertCppRetnArg( arglist, retnnode, return_kind );
        arglist = appendArg( userargs, arglist );
        break;
      case CALL_IMPL_ELL_C :
      case CALL_IMPL_C :
        return_kind = OMR_CLASS_VAL;
        // drops thru
      case CALL_IMPL_ELL_CPP :
      case CALL_IMPL_CPP :
        arglist = insertCppRetnArg( userargs, retnnode, return_kind );
        arglist = insertCDtor( arglist, cdtor );
        arglist = insertArg( arglist, thisnode );
        break;
    }
    callnode->u.subtree[1] = arglist;
    callnode = insertCppRetnCopy( callnode, retnnode, return_kind );
    return callnode;
}

static void outputCallTriggeredWarning( PTREE expr, SYMBOL sym )
{
    MSG_NUM msg;
    char *name;

    msg = ERR_NULL;
    name = sym->name->name;
    if( name == CppSpecialName( SPECIAL_BEGINTHREAD ) ) {
        msg = WARN_MUST_BE_MULTITHREADED;
    } else if( name == CppSpecialName( SPECIAL_BEGINTHREADEX ) ) {
        msg = WARN_MUST_BE_MULTITHREADED;
    }
    if( msg != ERR_NULL ) {
        switch( msg ) {
        case WARN_MUST_BE_MULTITHREADED:
            if( !CompFlags.bm_switch_used ) {
                PTreeErrorExprName( expr, msg, name );
            }
            break;
        DbgDefault( "unexpected message number" );
        }
    }
}

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

⌨️ 快捷键说明

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