windows-nt/Source/XPSP1/NT/com/rpc/midl/codegen/arraygen.cxx
2020-09-26 16:20:57 +08:00

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