498 lines
11 KiB
C++
498 lines
11 KiB
C++
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989-1999 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
|
|
***************************************************************************/
|
|
/****************************************************************************/
|
|
|
|
|
|
/*****************************************************************************
|
|
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->IsInterfacePointer() ) ||
|
|
pBasicCGClass->HasPointer() );
|
|
}
|
|
|
|
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() )
|
|
{
|
|
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;
|
|
}
|
|
|
|
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 *)
|
|
{
|
|
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->IsInterfacePointer() &&
|
|
((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()));
|
|
expr_node* pLenExpr = PresentedLengthExpression( pCCB );
|
|
expr_node* pFirstExpr = PresentedFirstExpression( pCCB );
|
|
expr_node* pFinalVal = 0;
|
|
|
|
if ( pLenExpr )
|
|
{
|
|
pFinalVal = new expr_b_arithmetic( OP_PLUS, pFirstExpr, pLenExpr );
|
|
}
|
|
else
|
|
{
|
|
pFinalVal = PresentedSizeExpression( pCCB );
|
|
}
|
|
|
|
Out_For( pCCB,
|
|
GetIndexResource(),
|
|
pFirstExpr,
|
|
pFinalVal,
|
|
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;
|
|
}
|