membptr.c

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

C
1,688
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "plusplus.h"
#include "cgfront.h"
#include "cgback.h"
#include "errdefns.h"
#include "fnbody.h"
#include "fnovload.h"
#include "fold.h"
#include "vfun.h"
#include "initdefs.h"

#ifndef NDEBUG
    #include "dbg.h"
    #include "pragdefn.h"
#endif

typedef enum                    // CLASSIFICATION OF MEMBER-PTR EXPRESSIONS
{   MP_ZERO                     // - zero
,   MP_CONST                    // - member pointer constant
,   MP_EXPR                     // - member-pointer expression
,   MP_INVALID                  // - invalid operand
,   MP_DIMENSION                // # of different types for comparison
,   MP_ADDR_OF = MP_DIMENSION   // - &class::item detected
,   MP_MEMB_FN                  // - member function, by self
} MP_TYPE;

#define MP_OPS( op1, op2 ) op1*MP_DIMENSION+op2


static PTREE membPtrTemporary(  // PLACE MEMBER PTR IN TEMPORARY
    PTREE expr )                // - member-ptr expression
{
    expr = NodeAssign( NodeTemporary( expr->type ), expr );
    expr->flags |= PTF_MEMORY_EXACT;
    return expr;
}


static PTREE membPtrStoreTemp(  // STORE MEMBER PTR EXPR IN TEMPORARY
    PTREE expr )
{
    PTREE a_expr;               // - for better addressing

    a_expr = membPtrTemporary( expr );
    MembPtrAssign( &a_expr );
    return NodeRvalue( a_expr );
}


static boolean nodeIsMembPtrCon(// TEST IF NODE CAN BE MEMBER-PTR CONST
    PTREE node )                // - node to be tested
{
    if( node->op == PT_SYMBOL && node->flags & PTF_COLON_QUALED ) {
        return TRUE;
    } else {
        return CompFlags.extensions_enabled;    // KLUGE for MFC
    }
}


static TYPE membPtrObject(      // GET OBJECT TYPE FOR MEMBER PTR
    TYPE mp )                   // - a member-ptr type
{
    return MemberPtrType( mp )->of;
}


static CNV_RETN validateOkObjs( // VALIDATE TARGET ONLY ADDS QUALIFICATION
    PTREE expr,                 // - expression for errors
    boolean check_qual,         // - TRUE ==> check CV qualification
    TYPE o1,                    // - source object type
    TYPE o2 )                   // - target object type
{
    CNV_RETN retn;              // - return: TRUE ==> objects are same
    type_flag f1;               // - flags: object[1]
    type_flag f2;               // - flags: object[2]
    type_flag f3;               // - flags: object[1]
    type_flag f4;               // - flags: object[2]

    retn = CNV_OK;
    o1 = TypeModFlagsEC( TypeReferenced( o1 ), &f1 );
    f1 &= ~TF1_MPTR_REMOVE;
    o2 = TypeModFlagsEC( TypeReferenced( o2 ), &f2 );
    f2 &= ~TF1_MPTR_REMOVE;
    if( TypesIdentical( o1, o2 ) ) {
        f4 = f2;
        f3 = f1 | ( f4 & TF1_CV_MASK );
        if( f3 == f4 ) {
            retn = CNV_OK;
        } else {
            if( check_qual ) {
                retn = CNV_ERR;
            } else {
                retn = CNV_IMPOSSIBLE;
            }
        }
    } else {
        retn = CNV_ERR;
    }
    if( retn == CNV_ERR ) {
        PTreeErrorExpr( expr, ERR_MEMB_PTR_OBJS_MISMATCH );
        retn = CNV_ERR;
    }
    return retn;
}


static CNV_RETN validateMpObjs( // VALIDATE BOTH MEMPTR'S ARE TO SAME TYPE
    PTREE expr,                 // - expression for error
    boolean check_qual,         // - TRUE ==> check CV qualification
    TYPE mp1,                   // - source type
    TYPE mp2 )                  // - target type
{
    return validateOkObjs( expr
                         , check_qual
                         , membPtrObject( mp1 )
                         , membPtrObject( mp2 ) );
}


static CNV_RETN validateAddrOfObj( // VALIDATE &class::item OBJECT
    PTREE expr,                 // - expression for constant
    TYPE mp )                   // - target member-ptr type
{
    TYPE mp_obj;                // - object type for member ptr
    TYPE ad_obj;                // - object type for & object
    CNV_RETN retn;              // - return: conversion

    mp_obj = membPtrObject( mp );
    ad_obj = PTreeOpLeft( expr )->type;
    if( FunctionDeclarationType( mp_obj ) &&
        FunctionDeclarationType( ad_obj ) ) {
        /* wait until overload to check types */
        retn = CNV_OK;
    } else {
        retn = validateOkObjs( expr, TRUE, ad_obj, mp_obj );
    }
    return retn;
}


static TYPE memberPtrLayout(    // SET TYPE, OFFSETS FOR MEMBER-PTR OBJECT
    unsigned *offset_delta,     // - addr[delta offset]
    unsigned *offset_index )    // - addr[delta index]
{
    TYPE type_offset;           // - type of an offset
    unsigned delta;             // - offset of delta

    delta = CgCodePtrSize();
    *offset_delta = delta;
    type_offset = TypeTargetSizeT();
    *offset_index = delta + CgMemorySize( type_offset );
    return type_offset;
}


static TYPE memberPtrHostClass( // GET HOST CLASS FOR MEMBER PTR.
    TYPE mp_type )              // - member ptr. type
{
    return MemberPtrClass( MemberPtrType( mp_type ) );
}


static SCOPE scopeMembPtrType(  // GET SCOPE FOR A MEMBER POINTER TYPE
    TYPE type )                 // - a memb-ptr type
{
    SCOPE scope;                // - scope of class for member pointer

    type = memberPtrHostClass( type );
    if( type == NULL ) {
        scope = NULL;
    } else {
        scope = type->u.c.scope;
    }
    return scope;
}


static PTREE accessOp(          // ACCESS AN OPERAND
    PTREE base,                 // - lvalue operand
    unsigned offset,            // - offset of item
    TYPE type )                 // - type of item
{
    PTREE expr;                 // - resultant expression

    expr = NodeBinary( CO_DOT, base, NodeOffset( offset ) );
    expr->type = type;
    expr->flags |= PTF_LVALUE;
    return expr;
}


static PTREE addToLeft(         // FABRICATE AN ADDITION TO LEFT
    PTREE left,                 // - left operand
    PTREE right,                // - right operand
    TYPE type )                 // - type of result
{
    PTREE expr;                 // - resultant expression

    expr = NodeBinary( CO_PLUS, left, right );
    expr->type = type;
    return expr;
}


static PTREE addOffset(         // ADD AN OFFSET TO AN LVALUE
    PTREE field,                // - field
    unsigned offset,            // - offset
    TYPE type )                 // - type of field
{
    PTREE expr;                 // - resultant expression

    expr = addToLeft( field, NodeOffset( offset ), type );
    expr->flags &= ~ PTF_LVALUE;
    return expr;
}


static void generateOffsetFunc( // GENERATE CODE FOR OFFSET FUNCTION
    SYMBOL func,                // - function to be generated
    PTREE node )                // - symbol node used as a member
{
    SCOPE stashed_scope;        // - saved: CurrScope
    FUNCTION_DATA func_fd;      // - function data
    SCOPE scope_class;          // - scope for class
    SYMBOL ret;                 // - return symbol
    TYPE type_ret;              // - type of return value
    PTREE expr;                 // - expression in body of function
    SYMBOL previous_func;       // - current function, if any
    SYMBOL refed;               // - referenced symbol
    SEARCH_RESULT *result;      // - info for accessing vfptr

    refed = node->u.symcg.symbol;
    previous_func = CgFrontCurrentFunction();
    func->flag |= SF_INITIALIZED;
    stashed_scope = GetCurrScope();
    scope_class = SymScope( func );
    SetCurrScope(scope_class);
    ScopeBeginFunction( func );
    FunctionBodyStartup( func, &func_fd, FUNC_NO_STACK_CHECK );
    type_ret = SymFuncReturnType( func );
    ret = SymFunctionReturn();
    if( SymIsThisDataMember( refed ) ) {
        expr = NodeBinary( CO_PLUS
                         , NodeThis()
                         , NodeOffset( refed->u.offset ) );
        expr->type = refed->sym_type;
        expr = NodeFetchReference( expr );
    } else {
        if( SymIsVirtual( refed ) ) {
            VfnReference( refed );
            result = node->u.symcg.result;
            expr = AccessVirtualFnAddress( NodeThis(), result, refed );
        } else {
            expr = MakeNodeSymbol( refed );
        }
    }
    expr->type = ret->sym_type;
    expr = NodeAssign( MakeNodeSymbol( ret ), expr );
    expr->type = type_ret;
    expr->flags |= PTF_LVALUE;
    IcEmitExpr( NodeDone( expr ) );
    CgFrontReturnSymbol( ret );
    FunctionBodyShutdown( func, &func_fd );
    ScopeEnd( SCOPE_FUNCTION );
    SetCurrScope(stashed_scope);
    CgFrontResumeFunction( previous_func );
}


static TYPE dereferenceFnType(  // GET TYPE OF DE-REFERENCING FUNCTION
    TYPE obj_type )             // - type of object pointed at
{
    TYPE fn_type;               // - function type

    fn_type = MakeSimpleFunction( MakePointerTo( obj_type ), NULL );
    fn_type = MakeCommonCodeData( fn_type );
    return fn_type;
}


TYPE MembPtrDerefFnPtr(   // GET TYPE OF DE-REFERENCING FUNC. POINTER
    void )
{
    return MakePointerTo( dereferenceFnType( GetBasicType( TYP_VOID ) ) );
}


// These names should be notated as being overlayable (this function can
// exist in many object files) but not combinable (cannot be combined
// with a function with a different name), because comparisons of
// member pointers compare the function addresses within member-pointer
// structures.
//
static SYMBOL membPtrOffsetFunc(// GET OFFSET FUNCTION FOR MEMBER
    PTREE node )                // - symbol node
{
    char *name;                 // - name for offset function
    SCOPE scope;                // - source scope
    SEARCH_RESULT *result;      // - lookup result
    SYMBOL src;                 // - symbol referenced
    SYMBOL tgt;                 // - symbol for offset function

    src = node->u.symcg.symbol;
    scope = SymScope( src );
    name = CppMembPtrOffsetName( src );
    result = ScopeContainsMember( scope, name );
    if( result == NULL ) {
        tgt = SymCreate( dereferenceFnType( TypeReferenced( src->sym_type ) )
                       , SC_MEMBER
                       , SF_REFERENCED
                       , name
                       , scope );
        generateOffsetFunc( tgt, node );
    } else {
        tgt = result->sym_name->name_syms;
        ScopeFreeResult( result );
    }
    return tgt;
}


static PTREE computeNewDelta(   // COMPUTE NEW DELTA
    PTREE new_delta,            // - new delta
    PTREE *new_index,           // - reference[ new_index RVALUE ]
    MEMBER_PTR_CAST *inf )      // - operands information
{
    PTREE node;                 // - node under construction
    int delta;                  // - delta
    TYPE type;                  // - element type

    type = TypeTargetSizeT();
    if( inf->delta_reqd ) {
        delta = ( inf->safe ) ? inf->delta : -inf->delta;
        if( inf->test_reqd ) {
            node = addOffset( NodeDupExpr( &new_delta ), delta, type );
            node = FoldBinary( node );
            node = NodeBinary( CO_COLON, new_delta, node );
            node->type = type;
            node = NodeBinary( CO_QUESTION
                             , NodeCompareToZero( NodeDupExpr( new_index ) )
                             , node );
            node->type = type;
        } else {
            node = addOffset( new_delta, delta, type );
        }
        new_delta = FoldBinary( node );
    }
    return new_delta;
}


static PTREE computeNewIndex(   // COMPUTE NEW INDEX
    PTREE new_index,            // - new_index RVALUE
    MEMBER_PTR_CAST *inf )      // - operands information
{
    TYPE type;                  // - element type
    PTREE node;                 // - node under construction
    PTREE off_node;             // - offset node

    if( inf->mapping_reqd ) {
        type = TypeTargetSizeT();
        if( inf->mapping == NULL ) {
            off_node = NodeOffset( inf->vb_index );
            off_node->type = type;
            if( inf->single_mapping ) {
                node = NodeBinary( (inf->vb_index == 0 ) ? CO_GT : CO_EQ
                                 , NodeDupExpr( &new_index )
                                 , NodeOffset( inf->single_test ) );
                node = NodeSetBooleanType( node );
                node = FoldBinary( node );
                new_index = NodeBinary( CO_COLON, off_node, new_index );
                new_index->type = type;
                new_index = NodeBinary( CO_QUESTION
                                      , node
                                      , new_index );
                new_index->type = type;
                new_index = FoldBinary( new_index );
            } else {
                NodeFreeDupedExpr( new_index );
                new_index = off_node;
            }
        } else {
            node = MakeNodeSymbol( inf->mapping );
            node = NodeBinary( CO_DOT, node, new_index );
            node->type = type;
            node->flags |= PTF_LVALUE;
            new_index = NodeFetch( node );
            new_index->flags &= ~PTF_LVALUE;
        }
    }

⌨️ 快捷键说明

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