Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

992 lines
24 KiB

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1989 Microsoft Corporation
Module Name:
arraygen.cxx
Abstract:
Implementation of array marshall and unmarshall.
Notes:
History:
Nov-13-1993 VibhasC Created.
----------------------------------------------------------------------------*/
/****************************************************************************
* include files
***************************************************************************/
#include "becls.hxx"
#pragma hdrstop
/****************************************************************************
* local definitions
***************************************************************************/
/****************************************************************************
* local data
***************************************************************************/
/****************************************************************************
* externs
***************************************************************************/
/****************************************************************************/
CG_STATUS
CG_ARRAY::GenMarshall(
CCB * pCCB )
{
node_skl * pType;
unsigned short i;
unsigned short NoOfDims = GetDimensions();
ID_CG MyID = GetCGID();
BOOL fHasConformance = (MyID == ID_CG_CONF_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
BOOL fHasVariance = (MyID == ID_CG_VAR_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
expr_node * pSrc = pCCB->GetSourceExpression();
expr_node * pDest = pCCB->GetDestExpression();
expr_node * pFinalFirstExpr;
expr_node * pFinalLengthExpr;
expr_node * pElementSizeExpr;
CG_ARRAY * pThis;
CG_NDR * pBasicCGClass= GetBasicCGClass();
BOOL fArrayElementsMustBeMarshalled = !IsArrayOfRefPointers();
if( fArrayElementsMustBeMarshalled == TRUE )
{
// For each dimension, marshall the conformance information and variance
// information.
if( !IsFixedArray() )
{
// For each dimension, marshall the conformance information if
// necessary.
GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT );
if( fHasConformance )
{
// Advance and align the buffer pointer to 4.
Out_AdvanceAndAlignTo( pCCB, AL_4 );
// Output the conformance information for each dimension.
for( i = 0, pThis = (CG_ARRAY *)this;
i < NoOfDims;
++i, pThis = (CG_ARRAY *)pThis->GetChild()
)
{
Out_MarshallBaseType( pCCB,
pType,
pDest,
pThis->PresentedSizeExpression( pCCB ) );
}
}
if( fHasVariance )
{
Out_AdvanceAndAlignTo( pCCB, AL_4 );
for( i = 0, pThis = (CG_ARRAY *)this;
i < NoOfDims;
++i, pThis = (CG_ARRAY *)pThis->GetChild()
)
{
Out_MarshallBaseType( pCCB,
pType,
pDest,
pThis->PresentedFirstExpression( pCCB ) );
Out_MarshallBaseType( pCCB,
pType,
pDest,
pThis->PresentedLengthExpression( pCCB ) );
}
}
}
// If a block copy is not possible or there are embedded pointers, then
// a member by member copy is performed, else a block copy.
if( ! IsBlockCopyPossible() )
{
GenDimByDimProcessing( pCCB, CG_ACT_MARSHALL );
}
else
{
pElementSizeExpr = new expr_constant( GetBasicCGClass()-> GetWireSize() );
pFinalFirstExpr = FinalFirstExpression( pCCB );
pFinalFirstExpr = new expr_b_arithmetic( OP_STAR,
pFinalFirstExpr,
pElementSizeExpr );
pFinalLengthExpr= fHasVariance ? FinalLengthExpression( pCCB ) :
FinalSizeExpression( pCCB );
pFinalLengthExpr= new expr_b_arithmetic( OP_STAR,
pFinalLengthExpr,
pElementSizeExpr );
Out_Copy( pCCB,
pDest,
new expr_b_arithmetic(OP_PLUS,
MakeCastExprPtrToUChar(pSrc),
pFinalFirstExpr ),
pFinalLengthExpr,
pDest );
}
pCCB->SetCurAlignmentState(MAKE_WC_ALIGNMENT(GetWireAlignment()));
}
if( HasPointer() )
pCCB->SetHasAtLeastOneDeferredPointee();
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenSizing(
CCB * pCCB )
{
ID_CG MyID = GetCGID();
BOOL fHasConformance = (MyID == ID_CG_CONF_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
BOOL fHasVariance = (MyID == ID_CG_VAR_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
expr_node * pFinalLengthExpr;
expr_node * pElementSizeExpr;
BOOL fArrayElementsMustBeMarshalled = !IsArrayOfRefPointers();
ITERATOR VarListToBeMangled;
if( fArrayElementsMustBeMarshalled == TRUE )
{
// If a block copy is not possible or there are embedded pointers, then
// a member by member copy is performed, else a block copy.
if( fHasConformance ||
fHasVariance ||
!IsBlockCopyPossible()
)
{
if( !IsBlockCopyPossible() )
{
GenDimByDimProcessing( pCCB, CG_ACT_SIZING );
}
else
{
pElementSizeExpr = new expr_constant( GetBasicCGClass()->GetWireSize() );
pFinalLengthExpr= fHasVariance ? FinalLengthExpression( pCCB ) :
FinalSizeExpression( pCCB );
pFinalLengthExpr= new expr_b_arithmetic( OP_STAR,
pFinalLengthExpr,
pElementSizeExpr );
// Mangle the expression for the correct prefix.
SetPrefixes( VarListToBeMangled,
pCCB->GetPrefix(),
pFinalLengthExpr );
Out_PlusEquals( pCCB,
pCCB->GetStandardResource( ST_RES_LENGTH_VARIABLE ),
pFinalLengthExpr
);
// Were done with expressions, remove the prefix.
ResetPrefixes( VarListToBeMangled,
pFinalLengthExpr );
}
}
}
if( HasPointer() )
pCCB->SetHasAtLeastOneDeferredPointee();
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenUnMarshall(
CCB * pCCB )
{
node_skl * pType;
unsigned short i;
unsigned short NoOfDims = GetDimensions();
ID_CG MyID = GetCGID();
BOOL fHasConformance = (MyID == ID_CG_CONF_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
BOOL fHasVariance = (MyID == ID_CG_VAR_ARRAY) ||
(MyID == ID_CG_CONF_VAR_ARRAY);
expr_node * pSrc = pCCB->GetSourceExpression();
expr_node * pDest = pCCB->GetDestExpression();
expr_node * pFinalSizeExpr;
expr_node * pFinalFirstExpr;
expr_node * pFinalLengthExpr;
expr_node * pElementSizeExpr;
CG_ARRAY * pThis;
BOOL fIsTopLevelArray;
BOOL fArrayElementsMustBeMarshalled = !IsArrayOfRefPointers();
BOOL fNeedsUnMarshall = TRUE;
fIsTopLevelArray = (pCCB->GetCurrentEmbeddingLevel() == 0) &&
(pCCB->GetCurrentIndirectionLevel() == 0 );
if( (pCCB->GetCodeGenSide() == CGSIDE_SERVER ) && pCCB->IsRefAllocDone() )
{
pDest = MakeRefExprOutOfDeref( pDest );
pDest = MakeReferentExpressionIfNecessary( pDest );
}
if( !IsFixedArray() )
{
// For each undimension, marshall the conformance information if
// necessary.
GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_LONG, TYPE_INT );
if( fHasConformance )
{
// Advance and align the buffer pointer to 4.
Out_AdvanceAndAlignTo( pCCB, AL_4 );
// UnMarshall the conformance information for each dimension.
for( i = 0, pThis = (CG_ARRAY *)this;
i < NoOfDims;
++i, pThis = (CG_ARRAY *)pThis->GetChild()
)
{
Out_UnMarshallBaseType( pCCB,
pType,
pThis->GetSizeResource(),
pSrc
);
}
}
if( fHasVariance )
{
Out_AdvanceAndAlignTo( pCCB, AL_4 );
for( i = 0, pThis = (CG_ARRAY *)this;
i < NoOfDims;
++i, pThis = (CG_ARRAY *)pThis->GetChild()
)
{
Out_UnMarshallBaseType( pCCB,
pType,
pThis->GetFirstResource(),
pSrc );
Out_UnMarshallBaseType( pCCB,
pType,
pThis->GetLengthResource(),
pSrc );
}
}
}
// Now allocate for the array.
pElementSizeExpr = new expr_constant( GetBasicCGClass()->GetMemorySize() );
pFinalSizeExpr = FinalSizeExpression( pCCB );
pFinalSizeExpr = new expr_b_arithmetic( OP_STAR,
pFinalSizeExpr,
pElementSizeExpr
);
Out_IfAlloc(pCCB,
pDest,
pSrc,
pFinalSizeExpr );
// If a block copy is not possible or there are embedded pointers, then
// a member by member copy is performed, else a block copy.
if( fNeedsUnMarshall && !IsArrayOfRefPointers() )
{
if( ! IsBlockCopyPossible() )
{
GenDimByDimProcessing( pCCB, CG_ACT_UNMARSHALL );
}
else
{
pFinalFirstExpr = FinalFirstExpression( pCCB );
pFinalFirstExpr = new expr_b_arithmetic( OP_STAR,
pFinalFirstExpr,
pElementSizeExpr );
pFinalLengthExpr= fHasVariance ? FinalLengthExpression( pCCB ) :
FinalSizeExpression( pCCB );
pFinalLengthExpr= new expr_b_arithmetic( OP_STAR,
pFinalLengthExpr,
pElementSizeExpr );
if( (pCCB->GetCodeGenSide() == CGSIDE_CLIENT) && fIsTopLevelArray )
{
Out_Copy( pCCB,
new expr_b_arithmetic( OP_PLUS,
MakeCastExprPtrToUChar(pDest),
pFinalFirstExpr ),
pSrc,
pFinalLengthExpr,
pSrc
);
}
else
{
Out_IfCopy( pCCB,
new expr_b_arithmetic(
OP_PLUS,
MakeCastExprPtrToUChar(pDest),
pFinalFirstExpr ),
pSrc,
pFinalLengthExpr
);
}
}
}
pCCB->SetCurAlignmentState(MAKE_WC_ALIGNMENT(GetWireAlignment()));
if( HasPointer() )
pCCB->SetHasAtLeastOneDeferredPointee();
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenFollowerMarshall(
CCB * pCCB )
{
ALIGNMENT_PROPERTY Al = pCCB->GetCurAlignmentState();
pCCB->SetCurAlignmentState( AL_WC1 );
pCCB->SetNextWireAlignment( AL_1 );
GenDimByDimProcessing( pCCB, CG_ACT_FOLLOWER_MARSHALL );
pCCB->SetNextWireAlignment( Al );
pCCB->SetCurAlignmentState(MAKE_WC_ALIGNMENT(pCCB->GetCurAlignmentState()));
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenFollowerUnMarshall(
CCB * pCCB )
{
ALIGNMENT_PROPERTY Al = pCCB->GetCurAlignmentState();
pCCB->SetCurAlignmentState( AL_WC1 );
pCCB->SetNextWireAlignment( AL_1 );
GenDimByDimProcessing( pCCB, CG_ACT_FOLLOWER_UNMARSHALL );
pCCB->SetNextWireAlignment( Al );
pCCB->SetCurAlignmentState(MAKE_WC_ALIGNMENT(pCCB->GetCurAlignmentState()));
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenFollowerSizing(
CCB * pCCB )
{
// This method will be called only when there is a pointer as the
// basic type of the array. In such a case, depending on the type of the
// pointer, determine whether it needs sizing at all. A simple pointer
// does not need sizing.
if( GetBasicCGClass()->GetCGID() == ID_CG_PTR )
return CG_OK;
return GenDimByDimProcessing( pCCB, CG_ACT_FOLLOWER_SIZING );
}
/*****************************************************************************
utility
*****************************************************************************/
BOOL
CG_ARRAY::IsBlockCopyPossible()
{
return GetBasicCGClass()->IsBlockCopyPossible();
}
expr_node *
CG_ARRAY::FinalSizeExpression( CCB * pCCB )
{
CG_NDR * pC;
expr_node * pFSExpr;
if( (pC = (CG_NDR *)GetChild())->IsArray() )
{
pFSExpr = ((CG_ARRAY *)pC)->FinalSizeExpression( pCCB );
pFSExpr = new expr_b_arithmetic(OP_STAR,
pFSExpr,
PresentedSizeExpression( pCCB ));
}
else
pFSExpr = PresentedSizeExpression( pCCB );
if( pFSExpr->IsConstant() )
pFSExpr = new expr_constant( pFSExpr->Evaluate() );
return pFSExpr;
}
expr_node *
CG_ARRAY::FinalFirstExpression( CCB * pCCB )
{
CG_NDR * pC;
expr_node * pFFExpr;
// for an array a[ 0th ][ 1st]...[nth] the final first expression is:
// ((First Of nth dim) * Size Nth dim ) + First N-1th dim) * Size N-1th dim
// and so on.
if( (pC = (CG_NDR *)GetChild())->IsArray() )
{
pFFExpr = ((CG_ARRAY *)pC)->FinalFirstExpression( pCCB );
pFFExpr = new expr_b_arithmetic(OP_STAR,
pFFExpr,
((CG_ARRAY *)pC)->PresentedSizeExpression( pCCB ));
pFFExpr = new expr_b_arithmetic( OP_PLUS,
pFFExpr,
((CG_ARRAY *)pC)->PresentedFirstExpression( pCCB ));
}
else
pFFExpr = PresentedFirstExpression( pCCB );
if( pFFExpr->IsConstant() )
pFFExpr = new expr_constant( pFFExpr->Evaluate() );
return pFFExpr;
}
expr_node *
CG_ARRAY::FinalLengthExpression( CCB * pCCB )
{
CG_NDR * pC;
expr_node * pFLExpr;
if( (pC = (CG_NDR *)GetChild())->IsArray() )
{
pFLExpr = ((CG_ARRAY *)pC)->FinalLengthExpression( pCCB );
pFLExpr = new expr_b_arithmetic(OP_STAR,
pFLExpr,
PresentedLengthExpression( pCCB ));
}
else
pFLExpr = PresentedLengthExpression( pCCB );
if( pFLExpr->IsConstant() )
pFLExpr = new expr_constant( pFLExpr->Evaluate() );
return pFLExpr;
}
CG_NDR *
CG_ARRAY::GetBasicCGClass()
{
CG_NDR * pC = (CG_NDR *)GetChild();
while( pC->IsArray() && (pC->GetCGID() != ID_CG_STRING_ARRAY) )
{
pC = (CG_NDR *)pC->GetChild();
}
return pC;
}
BOOL
CG_ARRAY::HasPointer()
{
CG_NDR * pBasicCGClass = (CG_NDR *)GetBasicCGClass();
return ( ( pBasicCGClass->IsPointer() &&
(pBasicCGClass->GetCGID() != ID_CG_INTERFACE_PTR) ) ||
pBasicCGClass->HasPointer() );
}
CG_STATUS
CG_ARRAY::GenFree(
CCB * pCCB )
{
BOOL fHasPtrUnderneath;
fHasPtrUnderneath = (HasPointer() || GetBasicCGClass()->HasPointer());
if( !fHasPtrUnderneath )
return CG_OK;
#if 0
if( pCCB->GetCurrentIndirectionLevel() > 0 )
pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary( pCCB->GetSourceExpression()));
#else
if( pCCB->IsRefAllocDone() )
pCCB->SetSourceExpression(
MakeDereferentExpressionIfNecessary( pCCB->GetSourceExpression()));
#endif // 0
GenDimByDimProcessing( pCCB, CG_ACT_FREE );
return CG_OK;
}
CG_STATUS
CG_ARRAY::S_GenInitOutLocals(
CCB * pCCB )
{
BOOL fFixedArrayOfXmitOrRepAs= FALSE;
// If this is a fixed array, then the array would have been allocated
// already. Remember, there is also a pointer associated with it.
// Emit the initialization to the allocated array.
// If this is a conformant array, then the size would have been
// unmarshalled before this and so we need to allocate.
if( IsFixedArray() )
{
ID_CG ChildID = ((CG_NDR *)GetChild())->GetCGID();
if( ((CG_NDR *)GetChild())->IsXmitRepOrUserMarshal() )
{
fFixedArrayOfXmitOrRepAs = TRUE;
}
Out_Assign( pCCB,
pCCB->GetSourceExpression(),
MakeAddressExpressionNoMatterWhat( GetResource() ) );
}
else
{
CGPHASE Phase = pCCB->GetCodeGenPhase();
expr_node * pElementSizeExpr =
new expr_constant( GetBasicCGClass()-> GetMemorySize() );
expr_node * pFinalSizeExpr;
BOOL fIsSigned;
// Get the final size expression.
// Make array believe it is actually on the marshall side, so that the
// presented expression comes out right.
pCCB->SetCodeGenPhase( CGPHASE_MARSHALL );
pFinalSizeExpr = FinalSizeExpression( pCCB );
fIsSigned = !((node_base_type *)pFinalSizeExpr->AlwaysGetType()->GetBasicType())->IsUnsigned();
pFinalSizeExpr = new expr_b_arithmetic( OP_STAR,
pFinalSizeExpr,
pElementSizeExpr );
// Allocate the proper size.
// If the size expression is signed and the value is less than 0, we
// need to raise an exception.
if( pCCB->MustCheckBounds() && fIsSigned )
{
expr_node * pCheckExpr;
pCheckExpr = new expr_op_binary( OP_LESS,
pFinalSizeExpr,
new expr_constant(0L));
Out_If( pCCB, pCheckExpr);
Out_RaiseException( pCCB, "RPC_X_INVALID_BOUND" );
Out_Endif( pCCB );
}
Out_Alloc( pCCB,
pCCB->GetSourceExpression(),
0,
pFinalSizeExpr );
pCCB->SetCodeGenPhase( Phase );
}
if( IsArrayOfRefPointers() || fFixedArrayOfXmitOrRepAs )
{
// Zero out this array of pointers.
expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
pProc->SetParam( new expr_param( pCCB->GetSourceExpression() ) );
pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
pProc->SetParam( new expr_param( new expr_sizeof( GetType())));
pCCB->GetStream()->NewLine();
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
}
return CG_OK;
}
CG_STATUS
CG_ARRAY::GenDimByDimProcessing(
CCB * pCCB,
CG_ACT Act )
{
CG_NDR * pC = (CG_NDR *)GetChild();
pCCB->PushEmbeddingLevel();
switch( Act )
{
case CG_ACT_MARSHALL:
case CG_ACT_SIZING:
case CG_ACT_FOLLOWER_MARSHALL:
case CG_ACT_FOLLOWER_SIZING:
pCCB->SetSourceExpression(new expr_index(
pCCB->GetSourceExpression(),
GetIndexResource()));
Out_For( pCCB,
GetIndexResource(),
PresentedFirstExpression( pCCB ),
PresentedSizeExpression( pCCB ),
new expr_constant( 1L )
);
if( Act == CG_ACT_MARSHALL )
pC->GenMarshall( pCCB );
else if( Act == CG_ACT_SIZING )
pC->GenSizing( pCCB );
else if( Act == CG_ACT_FOLLOWER_MARSHALL )
pC->GenFollowerMarshall( pCCB );
else
pC->GenFollowerSizing( pCCB );
Out_EndFor( pCCB );
break;
case CG_ACT_UNMARSHALL:
case CG_ACT_FOLLOWER_UNMARSHALL:
pCCB->SetDestExpression(new expr_index(
pCCB->GetDestExpression(),
GetIndexResource()));
Out_For( pCCB,
GetIndexResource(),
PresentedFirstExpression( pCCB ),
PresentedSizeExpression( pCCB ),
new expr_constant( 1L )
);
if( Act == CG_ACT_UNMARSHALL )
((CG_NDR *)GetChild())->GenUnMarshall( pCCB );
else
((CG_NDR *)GetChild())->GenFollowerUnMarshall( pCCB );
Out_EndFor( pCCB );
break;
case CG_ACT_FREE:
case CG_ACT_FOLLOWER_FREE:
pCCB->SetSourceExpression(new expr_index(
pCCB->GetSourceExpression(),
GetIndexResource()));
Out_For( pCCB,
GetIndexResource(),
PresentedFirstExpression( pCCB ),
PresentedSizeExpression( pCCB ),
new expr_constant( 1L )
);
((CG_NDR *)GetChild())->GenFree( pCCB );
Out_EndFor( pCCB );
break;
case CG_ACT_OUT_ALLOCATE:
pCCB->SetSourceExpression(new expr_index(
pCCB->GetSourceExpression(),
GetIndexResource()));
Out_For( pCCB,
GetIndexResource(),
PresentedFirstExpression( pCCB ),
PresentedSizeExpression( pCCB ),
new expr_constant( 1L )
);
((CG_NDR *)GetChild())->S_GenInitOutLocals( pCCB );
Out_EndFor( pCCB );
break;
default:
assert( FALSE && !"Dim by dim processing not implemented" );
break;
}
pCCB->PopEmbeddingLevel();
return CG_OK;
}
expr_node *
CG_CONFORMANT_ARRAY::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
expr_node * pExpr = GetSizeIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_VARYING_ARRAY::PresentedLengthExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetLengthResource();
}
else
{
expr_node * pExpr = GetLengthIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_VARYING_ARRAY::PresentedFirstExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetFirstResource();
}
else
{
expr_node * pExpr = GetFirstIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_CONFORMANT_VARYING_ARRAY::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
expr_node * pExpr = GetSizeIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_CONFORMANT_VARYING_ARRAY::PresentedLengthExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetLengthResource();
}
else
{
expr_node * pExpr = GetLengthIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_CONFORMANT_VARYING_ARRAY::PresentedFirstExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetFirstResource();
}
else
{
expr_node * pExpr = GetFirstIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_FIXED_ARRAY::PresentedSizeExpression(
CCB * pCCB )
{
expr_node * pExpr = new expr_constant( GetSizeIsExpr()->Evaluate() );
return pExpr;
}
expr_node *
CG_STRING_ARRAY::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
expr_node * pExpr = GetSizeIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
expr_node *
CG_CONFORMANT_STRING_ARRAY::PresentedSizeExpression(
CCB * pCCB )
{
if( pCCB->GetCodeGenPhase() == CGPHASE_UNMARSHALL )
{
return GetSizeResource();
}
else
{
expr_node * pExpr = GetSizeIsExpr();
if( pExpr->IsConstant() )
pExpr = new expr_constant( pExpr->Evaluate() );
return pExpr;
}
}
BOOL
CG_ARRAY::IsArrayOfRefPointers()
{
CG_NDR * pCG = GetBasicCGClass();
return ( pCG->IsPointer() &&
(pCG->GetCGID() != ID_CG_INTERFACE_PTR) &&
((CG_POINTER *)pCG)->IsRef() );
}
BOOL
CG_ARRAY::MustBeAllocatedOnUnMarshall(
CCB * pCCB )
{
BOOL fIsTopLevelArray = (pCCB->GetCurrentEmbeddingLevel() == 0) &&
(pCCB->GetCurrentIndirectionLevel() == 0 );
//
// The array must be allocated if:
// 1. Not a top level array on client or server.
// 2. On the server side, if it is an array of ref pointers.
// 3. Is not fixed.
if(!fIsTopLevelArray ||
((pCCB->GetCodeGenSide() == CGSIDE_SERVER) && IsArrayOfRefPointers()) ||
!IsFixedArray()
)
return TRUE;
else
return FALSE;
}
CG_STATUS
CG_ARRAY::GenRefChecks(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Perform ref pointer checks on an array of ref pointers.
Arguments:
pCCB - The code gen block.
Return Value:
CG_OK
Notes:
----------------------------------------------------------------------------*/
{
if( IsArrayOfRefPointers() )
{
pCCB->SetSourceExpression(new expr_index(
pCCB->GetSourceExpression(),
GetIndexResource()));
Out_For( pCCB,
GetIndexResource(),
PresentedFirstExpression( pCCB ),
PresentedSizeExpression( pCCB ),
new expr_constant( 1L )
);
((CG_NDR *)GetChild())->GenRefChecks( pCCB );
Out_EndFor( pCCB );
}
return CG_OK;
}
CG_STATUS
CG_ARRAY::S_GenInitInLocals(
CCB * pCCB )
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Routine Description:
Arguments:
Return Value:
CG_OK
Notes:
----------------------------------------------------------------------------*/
{
if( IsArrayOfRefPointers() && IsFixedArray() )
{
expr_node * pSrc = pCCB->GetSourceExpression();
expr_node * InLocalResource = GetInLocalResource();
expr_node * pExpr = new expr_assign(
pSrc,
MakeAddressExpressionNoMatterWhat(
InLocalResource ));
pCCB->GetStream()->NewLine();
pExpr->PrintCall( pCCB->GetStream(), 0, 0 );
pCCB->GetStream()->Write(';');
expr_proc_call * pProc = new expr_proc_call( MIDL_MEMSET_RTN_NAME );
pProc->SetParam( new expr_param( pSrc ) );
pProc->SetParam( new expr_param( new expr_constant( 0L ) ) );
pProc->SetParam( new expr_param( new expr_sizeof( GetType())));
pCCB->GetStream()->NewLine();
pProc->PrintCall( pCCB->GetStream(), 0, 0 );
}
return CG_OK;
}