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